OpenWRT路由器端口映射的实现

路由器地址:192.168.199.1
内网主机A:192.168.199.161
映射端口(内外网相同):8080

勾选 Enable NAT Loopback,也叫作hairpinning
https://en.wikipedia.org/wiki/Hairpinning

从内网另一台主机B上,使用 hping3 -S -p 8080 192.168.202.99 来从内网访问地址

在内网目标主机A192.168.199.161上抓包,可见数据来自 192.168.199.1 -> 192.168.199.161 ,即源地址为路由器,而不是主机B!

原理如下:

OpenWRT路由器上的IPTABLES

Chain zone_lan_prerouting (1 references)
#内网访问外网8080, 全部转向机器A:8080
6 312 DNAT tcp -- * * 192.168.199.0/24 192.168.202.99 tcp dpt:8080 /* 8080 (reflection) / to:192.168.199.161:8080
#另一个隧道端口(访问隧道地址亦然)
0 0 DNAT tcp -- * * 192.168.199.0/24 10.7.0.3 tcp dpt:8080 /
8080 (reflection) */ to:192.168.199.161:8080

Chain zone_wan_prerouting (2 references)
# 外网访问外网8080,全部转向机器A:8080
1 52 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 /* 8080 */ to:192.168.199.161:8080

Chain zone_lan_postrouting (1 references)
#内网机器访问机器A:8080, 由前面prerouting转过来的(DNAT),再做一次SNAT,把源地址改为路由器的地址。
6 312 SNAT tcp -- * * 192.168.199.0/24 192.168.199.161 tcp dpt:8080 /* 8080 (reflection) */ to:192.168.199.1

可以为了支持NAT Loopback,内网地址访问映射端口,要做两次NAT转换,一次是DNAT,另一次是SNAT。不仅如此,数据都要经过路由器中转,而不是直连的!

原文时间:2016.4