我有一个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
转发到:host2
host1
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
-d
POSTROUTING
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 虚拟机host1
,eth1
是用于主机和客户机之间通信的桥梁。
我通过调用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 的路由,将流量路由到路由器而不是本地网络。