如何使用 iptables 将通过网桥传输的数据包 DNAT 回其来源?

如何使用 iptables 将通过网桥传输的数据包 DNAT 回其来源?

我有一个host1,它有一个 WAN 接口eth0( 1.2.3.4) 和一个 LAN 接口eth1( 10.41.82.1)。LAN 内部有一个 ,host2带有 IP 地址10.41.82.2

传入的连接将使用以下 iptables 规则1.2.3.4:22转发到:host2host1

root@host1:~# iptables -t nat -A OUTPUT     -d 1.2.3.4 -p tcp --dport 22 -j DNAT --to 10.41.82.2:22
root@host1:~# iptables -t nat -A PREROUTING -d 1.2.3.4 -p tcp --dport 22 -j DNAT --to 10.41.82.2:22

这工作正常,除了当host2试图访问时1.2.3.4:22

root@host2:~# telnet 1.2.3.4 22
Trying 1.2.3.4...

root@host2:~# ping 1.2.3.4
PING 1.2.3.4 56(84) bytes of data.
64 bytes from 1.2.3.4: icmp_seq=1 ttl=64 time=0.125 ms
64 bytes from 1.2.3.4: icmp_seq=2 ttl=64 time=0.279 ms

root@host2:~# tcptraceroute 1.2.3.4 22
traceroute to 1.2.3.4, 30 hops max, 60 byte packets
 1  * * *
 2  * * *
 3  * * *
 4  * * *
 5  * * *
(and so on)

看起来数据包正在循环转发。如您所见,ping 成功,因此路由和 IP 转发设置正确。

我做错了什么?我该如何解决这个问题?


更新:

正如 BillThor 的回复中提到的,以及Freezetux 关于 DNAT 的教程,我需要添加一条规则。我现在已经完成了(请注意,我已为SNAT添加了 LAN 地址,因为此规则适用于数据包目的地已更改的情况):host2-dPOSTROUTING

root@host1:~# iptables -t nat -A POSTROUTING -d 10.41.82.2 -p tcp --dport 22 -j SNAT --to 10.41.82.1

不幸的是,这并不能解决问题,一切仍然和上面描述的一样。有趣的是,SNAT根据运行时显示的计数器,规则似乎从未匹配过iptables -t nat -nvL


更新2:

我发现当我运行 时tcpdump -i eth1,即使我使用与此案例无关的参数(例如 )运行它,tcpdump -i eth1 port 34238它也会突然起作用。但仅限于tcpdump运行时。

到目前为止我没有提到的是,因为我认为这无关紧要,这eth1实际上是一座桥梁,host2是一个 Xen 域。我开始怀疑我的问题可能与此有关。

答案1

失败的原因原来与它eth1实际上是一个桥接接口有关。它实际上host2是一个运行在上的 Xen 虚拟机host1eth1是用于主机和客户机之间通信的桥梁。

我通过调用bridge link set dev vif2.0 hairpin on(或者brctl hairpin eth1 vif2.0 on)解决了该问题。vif2.0是 Xen 创建的虚拟网络接口,是eth1网桥的一部分。

因此,为了使发夹式 NAT 在桥接接口上工作,请确保为数据包进入的接口(桥接的一部分)启用桥接发夹式连接。

SNAT最终没有必要添加规则。


systemd-networkd还有指示在 *.network 文件中启用发夹结构:

[Bridge]
HairPin=true

我不确定在我的情况下是否要将它添加到eth1.network或添加到vif2.0.network(通常不存在),但最终它们都不起作用。

答案2

您要执行的操作称为发夹式 NAT。host2 最好直接连接到 host1。

如果您希望此功能正常工作,请对源自本地网络到外部 IP 的流量使用 SNAT 和 DNAT。

另一个可行的解决方案是添加一条从 host2 到 host1 的路由,将流量路由到路由器而不是本地网络。

相关内容