![需要 iptables 端口转发来实现双向 UDP](https://linux22.com/image/697649/%E9%9C%80%E8%A6%81%20iptables%20%E7%AB%AF%E5%8F%A3%E8%BD%AC%E5%8F%91%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%8F%8C%E5%90%91%20UDP.png)
简而言之:我需要在面向连接的协议上进行端口重定向,就像 TCP 一样 - 但我需要它适用于 UDP。我有一个使用 UDP 进行传输的自定义面向连接协议。
尤其:
- 要配置的机器正在监听端口 5005 UDP。
- UDP 数据包预计来自 10.1.2.10。
- 这台机器应该将该数据包转发到 10.1.2.20 端口 5010。
- ... 反之亦然!
对于 4,更准确地说:当一个数据包来自 10.1.2.10 时,它会被分配一个随机端口,比如 52000。然后,这台机器在 UDP 端口 5005 上接收数据包并将其转发到 10.1.2.20:5010,同时还具有一些随机选择的源端口,比如 52001。现在,当有一个数据包从 10.1.2.20 端口 5010 到达这台机器端口 52001 时,它也应该将其重定向到 10.1.2.10 端口 52000。
此外,如果有数据包从 10.1.2.10 上的另一个端口传来,则端口分配和相应的反向数据包重定向规则也应适用。可以为任何流量设置 10 秒的超时时间,之后将删除反向跟踪规则。
如果使用 iptables 无法做到这一点,我也可以接受 - 我将回归到用户空间解决方案。但使用 iptables 可以简化部署。
答案1
因此,您的代理服务器正在执行双重 NAT,双向伪装(通过隐藏另一个真实的对等体)。
必须在其(单个)接口上将其配置为路由器,否则将无法转发任何内容。假设接口名称为 eth0,其 IP 为 10.1.2.50:
echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
现在由于双重 NAT,
PREROUTING
和/或中的转换POSTROUTING
会阻止仅使用相同的过滤器来匹配流。因此,在PREROUTING
a中CONNMARK
用于标记流,然后可以在中立即重用PREROUTING
(并避免重复特定测试以简化管理),稍后在 中POSTROUTING
。-p udp
仍然需要注意,因为我们要求SNAT
和/或DNAT
更改 UDP 端口。此后,只要不超时(通常第一次回复为 30 秒,然后为 3 分钟),conntrack 将处理所有未来交换iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j CONNMARK --set-mark 0x1 iptables -t nat -A PREROUTING -p udp -m connmark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010 iptables -t nat -A POSTROUTING -m connmark --mark 0x1 -j SNAT --to-source 10.1.2.50
如果确实需要您也更改源端口,而不是让 conntrack 仅在需要时执行此操作,请将第三条规则更改为:
iptables -t nat -A POSTROUTING -p udp -m connmark --mark 0x1 -j SNAT --random-fully --to-source 10.1.2.50:32768-60999
(通常范围取自
/proc/sys/net/ipv4/ip_local_port_range
,并且--random-fully
是必需的,否则不会执行任何操作,因为原始端口已在范围内)。
您也可以更改SNAT
为MASQUERADE
(并且不必声明服务器 IP)但只有--random
可用。
更新:虽然上述规则按预期发挥作用,但通常connmark
比赛和CONNMARK
目标是与mark
和MARK
为一个如本博客所述更复杂的用法。这里简单使用时不需要它们。只需将它们全部替换为 resp。mark
和MARK
。这里 netfilter 的连接跟踪在处理第一个数据包(在 state 中创建 conntrack 条目)后已经处理了流量,而NEW
无需要求它在 conntrack 条目中标记它。只需在(第一个)数据包中放置一个标记(表nat
仅看到 state 中的数据包NEW
):
iptables -t nat -A PREROUTING -s 10.1.2.10 -p udp --dport 5005 -j MARK --set-mark 0x1
iptables -t nat -A PREROUTING -p udp -m mark --mark 0x1 -j DNAT --to-destination 10.1.2.20:5010
iptables -t nat -A POSTROUTING -m mark --mark 0x1 -j SNAT --to-source 10.1.2.50
示例捕获,包括错误(服务未运行等):
00:28:36.476453 IP 10.1.2.10.56955 > 10.1.2.50.5005: UDP, length 5
00:28:36.476487 IP 10.1.2.50.35172 > 10.1.2.20.5010: UDP, length 5
00:28:36.476516 IP 10.1.2.20 > 10.1.2.50: ICMP 10.1.2.20 udp port 5010 unreachable, length 41
00:28:36.476522 IP 10.1.2.50 > 10.1.2.10: ICMP 10.1.2.50 udp port 5005 unreachable, length 41
00:32:28.597050 IP 10.1.2.10.35443 > 10.1.2.50.5005: UDP, length 5
00:32:28.597084 IP 10.1.2.50.36842 > 10.1.2.20.5010: UDP, length 5
00:32:32.503709 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 7
00:32:32.503745 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 7
00:32:41.704371 IP 10.1.2.20.5010 > 10.1.2.50.36842: UDP, length 4
00:32:41.704404 IP 10.1.2.50.5005 > 10.1.2.10.35443: UDP, length 4
00:32:41.704427 IP 10.1.2.10 > 10.1.2.50: ICMP 10.1.2.10 udp port 35443 unreachable, length 40
00:32:41.704433 IP 10.1.2.50 > 10.1.2.20: ICMP 10.1.2.50 udp port 36842 unreachable, length 40
请注意,您可以用这条简单的 socat 行替换所有这些(并且您不会得到任何 30 秒/3 分钟超时,但您会失去 ICMP 处理):
socat UDP4-LISTEN:5005,range=10.1.2.10/32,fork UDP4:10.1.2.20:5010