我在 Linux 上的 NAT 连接方面遇到了问题。
我正在使用 Debian 10 和 iptables 来做一些 SNAT 来强制所有从 eth0 传出的数据包到特定的 UDP 端口以使用连接到 eth0 的特定 IP:
iptables -t nat -D POSTROUTING -o eth0 -p udp --dport 38041 -j SNAT --to-source 10.230.0.1
但有时,源 IP 会被重新分配,并且会发生变化。在我的示例中,它从 10.230.0.1 变为 10.230.0.4。IP 被重新分配给 eth0,iptables 规则被删除,并添加了新的 iptables 规则(具有正确的 IP)
iptables -t nat -D POSTROUTING -o eth0 -p udp --dport 38041 -j SNAT --to-source 10.230.0.1
iptables -t nat -A POSTROUTING -o eth0 -p udp --dport 38041 -j SNAT --to-source 10.230.0.4
当我查看我的 iptables 规则时,一切看起来都正常:
#iptables -t nat -nL
...
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
SNAT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:38041 to:10.230.0.4
但它不起作用。当我使用 tcpdump 查看我的流量时:
#tcpdump -i eth0 udp port 38041
21:21:25.829610 IP 10.253.0.1.38041 > xx.xx.xx.xx.38041: [...payload...]
我尝试使用 netstat-nat,但没有得到任何东西。
旧的 IP 仍在使用 natted 连接。我不明白为什么。而且这种情况发生在多台服务器上,所以我不认为这是一种故障。
您知道如何正确地彻底废除该规则并用新规则取而代之吗?
谢谢 !
答案1
您需要使用conntrack -D
删除与这些连接相关的 NAT 状态,或者等到它们在不活动后超时。
iptables 的 NAT 始终是有状态的 – 每个数据包流都会经过该nat
表只有一次,系统会记住随后的转换。(这适用于 TCP 连接以及无连接 UDP 流,并且为了正确地“取消 NAT”响应数据包是必要的,因为没有明确的 iptables 规则来实现这一点。)
NAT 状态存储在内核的连接跟踪子系统。只要 conntrack 有针对您特定源→目的地的记录,它就会始终应用相同的转换,而忽略您的 iptablesnat
规则。