假设我们有一个公共网站,example.com
其解析为1.1.1.1
。实际的 Web 服务器位于路由器/防火墙后面,并且正在监听端口8080
。
简单的设置对于互联网用户来说没问题,但对于192.168.1.0
范围内的其他客户端则不行。 中的客户端192.168.1.3
无法连接到1.1.1.1:80
。我们有 发夹型NAT问题,(也描述在微罗蒂克 维基)。
假设我们不通过配置路由器来解决问题,而是通过iptables
Web 服务器本身来解决问题。此命令指示端口 8080 上的所有传出数据包都通过路由器发送:
iptables -t mangle -A OUTPUT -p tcp -m tcp --sport 8080 -j MARK --set-xmark 1
ip rule add fwmark 1 table natreflect
ip route add default via 192.168.1.1 table natreflect
上述配置解决了192.168
范围内的所有客户端,但并未解决客户端192.168.1.2
本身的问题。
当客户端192.168.1.2
想要连接到时1.1.1.1:80
,它会192.168.1.2:34567->1.1.1.1:80
向路由器发送一个数据包。路由器执行 NAT 并将数据包发送192.168.1.2:34567->192.168.1.2:8080
到 Web 服务器(例如在其eth0
接口上)。Web 服务器接收此数据包。数据包穿过链mangle.PREROUTING
和nat.PREROUTING
,但无法到达mangle.INPUT
(并且无法建立连接)。
有什么问题?(rp_filter
在所有接口上设置为 0)
答案1
服务器似乎很难192.168.1.2
接受来自从其自己的 IP 192.168.1.2
,但从范围来看关联,不是范围主持人,因此来自其自己的 IP,但不是它本身。这似乎是一个路由问题,可能有解决方案,也可能没有解决方案。人们仍然可以绕过这种情况,这样它就不会发生。
为了避免这种情况,在初始数据包离开 Web 服务器192.168.1.2
并开始传输之前,只需在其上添加一个 iptables 规则,将连接从其自身1.1.1.1:80
直接重定向到正确的位置:其自身。
iptables -t nat -A OUTPUT -s 192.168.1.2 -d 1.1.1.1 -p tcp --dport 80 -j REDIRECT --to-ports 8080
一个替代的和等效的规则(至少在最近的内核上,可能不适用于旧内核)是:
iptables -t nat -A OUTPUT -s 192.168.1.2 -d 1.1.1.1 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.2:8080
只需在其他设置中添加此规则,来自外部、LAN 和 Web 服务器的连接都会表现相同:它们工作正常,保留源 IP,并且在所有情况下目标 IP 都是192.168.1.2
。唯一的缺点是必须知道1.1.1.1
。