局域网内访问WAN IP的端口转发失效问题求助
看起来你遇到了Linux路由器上常见的**发夹NAT(Hairpin NAT)**问题——也就是LAN内主机访问路由器WAN IP时,端口转发无法正常工作的情况。先帮你梳理下问题和解决方案:
问题分析
从你提供的信息来看:
- WAN到LAN的端口转发(外部访问
192.168.137.54:67转到10.0.0.165:22)是正常的,但LAN内主机(比如10.0.0.129)访问这个WAN IP端口时失败。 - Wireshark的抓包结果很关键:请求是
10.0.0.129 → 192.168.137.54:67,但回复直接从10.0.0.165 → 10.0.0.129发回了。这就导致客户端(10.0.0.129)收到的回复源IP不是它请求的192.168.137.54,所以会直接丢弃这个无效响应。
原因在于:LAN内主机访问WAN IP时,数据包经过路由器的DNAT规则转到了LAN内的目标主机,但目标主机看到请求的源IP是同网段的LAN IP(10.0.0.129),就直接把回复发回去,没有经过路由器的SNAT处理,导致路径不完整。
解决方案
解决这个问题的核心是给LAN内访问WAN IP的流量添加**源地址转换(SNAT)**规则,让目标主机的回复先回到路由器,再由路由器转发给客户端。
方法1:精准针对该端口转发规则添加SNAT
执行以下iptables命令:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -d 10.0.0.165 -p tcp --dport 22 -j SNAT --to-source 10.0.0.1
这条规则的作用是:当LAN网段(10.0.0.0/24)的主机访问10.0.0.165的22端口时,把数据包的源地址改成路由器的LAN接口IP(10.0.0.1)。这样10.0.0.165会把回复发给路由器,路由器再把回复的源地址改成WAN IP(192.168.137.54)的67端口,发回给请求主机。
方法2:通用的LAN内发夹NAT规则(适合多个端口转发场景)
如果你有多个端口转发规则需要支持LAN内访问,可以添加更通用的规则:
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o br0 -j MASQUERADE
这条规则会对所有从LAN网段发出、从LAN接口(br0)出去的流量做源地址转换,自动使用路由器的LAN IP作为源地址,覆盖所有类似的发夹转发场景。
验证步骤
- 添加规则后,用以下命令确认规则已生效:
iptables -nvL -t nat --line-numbers
检查POSTROUTING链中是否存在你刚添加的规则。
2. 再次用LAN内主机测试访问192.168.137.54:67,应该能正常连接到10.0.0.165的22端口了。
3. 可以再抓包验证,此时回复的源IP应该是192.168.137.54:67,而不是10.0.0.165:22。
补充说明
看你当前的iptables规则,FORWARD链已经允许了br0接口的所有流量(ACCEPT all -- br0 * 0.0.0.0/0 0.0.0.0/0),所以不需要额外修改FORWARD规则。如果后续遇到问题,可以检查这条规则是否还存在。
备注:内容来源于stack exchange,提问作者Leandro Schmitz

