我是 iptables 新手,我想了解 iptables nat 的工作原理。我有一台装有 lxc 容器的 Linux 机器。机器网络配置如下:eth0 接口将机器连接到互联网(其 IPv4 地址为 10.9.63.173)和用于 lxc 容器的 veth-1 接口(192.168.2.1)。在 lxc 容器上有一个连接到 veth-1 的 eth0 接口(192.168.2.2)。
在 Linux 机器上我添加了两个 iptables 规则:
1) iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 10.9.63.173
2) iptables -t nat -A PREROUTING -d 10.9.63.173 -j DNAT --to-destination 192.168.2.2
如果我从 lxc 容器执行 ping 8.8.8.8,则一切正常(离开 Linux 计算机时,源 IP 被转换为 10.9.63.173)。但第二条规则从未与 ping echo 回复匹配。我使用 tcpdump 观察了 eth0(10.9.63.173)上的传入数据包,输出如下:
23:34:33.151565 IP google-public-dns-a.google.com > host.local: ICMP echo reply, id 536, seq 174, length 64
因此,目的地为 10.9.63.173 的数据包到达 eth0 接口。
我有三个问题:
1)为什么 nat 预路由规则从未匹配?
2)iptables 如何知道如何修改回复以便将其转发到 192.168.2.2?
3)SNAT 目标是否可以修改源端口(无需明确指示转换为特定端口)?
谢谢!
答案1
Iptables 使用 NAT 表和 conntrack 机器。这样,如果您的容器发起连接,它将匹配 SNAT 规则,写入 NAT 表,并填充 conntrack 表。
当收到回复时,conntrack 知道(通过源和目标 IP 和端口,如果连接是 TCP,则知道 TCP 序列)该数据包属于该连接,并将其发送到正确的 NAT 对应关系。
每个连接,只有第一个数据包会匹配 NAT 规则,然后每个其他数据包都会遵循相同的路径(或反向路径)。
如果有新的连接从外部进入您的容器,它将匹配 DNAT 规则。
SNAT无法修改源端口。
答案2
1)为什么 nat 预路由规则从未匹配?
iptables NAT 在“连接”上工作*,只有每个“连接”的第一个数据包会经过用户控制的 nat 表。
2)iptables 如何知道如何修改回复以便将其转发到 192.168.2.2?
当“连接”的第一个数据包通过 NAT 时,它会在内部连接跟踪表中建立一个条目。这用于转换连接的后续数据包。
3)SNAT 目标是否可以修改源端口(无需明确指示转换为特定端口)?
是的,可以,但默认情况下,只有在必要时才会这样做,以避免产生歧义。
* 这里的“连接”是指一组可用于将请求与其相应响应进行匹配的标准。例如,TCP/UDP 的源 ip/源端口/目标 ip/目标端口三元组或 ICMP 查询的源 ip/类型/id/代码/目标 ip。
答案3
我猜想应该阅读一下 TCP 和连接跟踪:http://www.iptables.info/en/connection-state.html
目前我所知道的SNAT只能修改源IP地址。