我的目标很简单:使用 IP 转发构建高容量、快速、低延迟的软交换机。我有一个服务器测试“服务器”和 2 个测试客户端:“客户端 1”和“客户端 2”。“客户端 1:c1”正在向“服务器:s1”发送 udp 数据包,“客户端 2:c2”正在向“服务器:s2”发送 udp 数据包。我只想将“客户端:c1”数据包转发到“客户端:c2”,反之亦然。如果只使用服务器上的 1 个端口就可以做到这一点,我不会介意。“客户端 1”和“客户端 2”目前是一个简单的 udp 发送方线程,它正在连续发送 udp 数据包。现在我正在应用规则:
sudo iptables --table nat --append PREROUTING --protocol udp --destination 'Server' --dport 's1' --jump DNAT --to-destination 'Client2:c2'
sudo iptables --table nat --append PREROUTING --protocol udp --destination 'Server' --dport 's2' --jump DNAT --to-destination 'Client1:c1'
sudo iptables --table nat --append POSTROUTING --protocol udp --destination 'Client2' --dport 'c2' --jump SNAT --to-source 'Server:s0'
sudo iptables --table nat --append POSTROUTING --protocol udp --destination 'Client1' --dport 'c1' --jump SNAT --to-source 'Server:s0'
如果我立即应用此规则,然后启动“客户端 1”和“客户端 2”线程,它就可以正常工作。即使我一次删除所有规则,它也可以正常工作,但如果我在“客户端 1”和“客户端 2”连续发送数据时开始逐一添加/删除这些规则,问题就开始了。
行为 1:'Client1' 和 'Client2' 正在运行(由于未应用任何规则,因此没有任何反应),然后我一次将 4 条规则应用于 'Server',然后它应该像以前一样工作,但不是......现在 'Server' 仅将 'Client1' 数据包转发到 'Client2',甚至 SNAT 也不起作用。但经过一段不确定的时间后,它却可以正常工作。其他行为就像这样,当我将某些规则应用于 'Server' iptable 时,如果 'Client1' 和 'Client2' 正在运行,则规则不会立即生效。
行为 2:我也遇到过这种情况,我刷新了 nat 表,但服务器仍在转发一段时间。
行为 3:当“客户端 1”和“客户端 2”仍在发送/接收时,逐条应用/删除规则时,规则不会随机生效
我搜索了几篇文章,发现 iptables 规则立即生效,但我们的情况并非如此,特别是有些规则有效,有些则突然失效,我们这里做错了什么?是否有某种缓存“服务器”iptable 维护,还是需要重新加载,尽管我发现没有重新加载的选项?** 我对“socat”不感兴趣,因为它将数据包带到用户空间,而用户空间对大量数据包有瓶颈。** 提前感谢任何帮助..!
答案1
下面的内容将重定向从 到client1:port1
的所有内容server:ports
,并将其传递到client2:port2
,其中它显示为来自server:ports
:
iptables -t nat -A PREROUTING -p udp -s client1 --sport port1 -d server --dport ports -j DNAT --to-destination client2:port2
iptables -t nat -A POSTROUTING -p udp -s client1 --sport port1 -d client2 --dport port2 -j SNAT --to-source server:ports
第一条规则将目的地从 更改为server:ports
(client2:port2
因为它是DNAT
规则),第二条规则将源从client1:port1
更改为server:ports
。当数据包通过第二条规则时,目的地已经改变,但源没有改变,因此规则中的匹配可能看起来很奇怪。回复将自动进行反向转换。
如果您希望在客户端 2 上发起的对话(而非回复)也能以类似的方式工作,则需要添加镜像规则:
iptables -t nat -A PREROUTING -p udp -s client2 --sport port2 -d server --dport ports -j DNAT --to-destination client1:port1
iptables -t nat -A POSTROUTING -p udp -s client2 --sport port2 -d client1 --dport port1 -j SNAT --to-source server:ports
如果服务器有任何过滤,则需要添加允许转发的数据包通过的规则:
iptables -t filter -A FORWARD -p udp -s client1 --sport port1 -d client2 --dport port2 -j ACCEPT
iptables -t filter -A FORWARD -p udp -s client2 --sport port2 -d client1 --dport port1 -j ACCEPT
这里的地址也看起来是半翻译的,因为数据包总是按照以下顺序穿过防火墙:PREROUTING
,,FORWARD
。POSTROUTING
现在,客户端 1 将完全相信自己在与 进行对话server:ports
(至少在网络层面;当然数据包可能包含一些提示真正应答者的信息)。客户端 2 也是如此,它将确信自己在与 进行对话server:ports
。
还要记住,一旦对话开始,防火墙就会记住其状态;删除或添加规则不会对已建立的连接产生任何直接影响,因为该nat
表始终仅由连接中的第一个数据包遍历;转换结果存储在状态表中,该表用于转换答复和后续数据包cat /proc/net/nf_conntrack
。该状态表可以通过或使用包中的实用程序查看conntrack-tools
。对于 UDP,“连接”由地址、端口和暂停在对话中,当在一定时间内(默认为 30 秒)在任何方向上都看不到数据包时,“结束”。
我也想明确地说明这一点:转发或路由绝不是由 iptables 执行的。无论存在什么 iptables 规则,路由和转发都将根据路由策略数据库规则和路由表内容执行。它只是不正确说“iptables 的 ip 转发“,因为 iptables 仅设置转换。它配置内核防火墙过滤规则和网络地址和端口转换规则,例如内核如何更改数据包中的地址,这显然会影响其路由决策(因为路由决策基于地址)。