如何防止 netfilter 自动更改源端口

如何防止 netfilter 自动更改源端口

我观察到,在 conntrack 模块中建立连接时,netfilter 会更改源端口。我需要阻止此行为。

以下是我为重现我的问题所做的事情:

  1. 我创建了一个 netfilter 规则,将从端口 2002 到 2003 执行 DNAT

sudo iptables -w -t nat -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j DNAT --to-destination :2003

  1. 然后我创建一个 conntrack 条目来模拟从 192.168.30.1:2001(我的电脑)到 192.168.30.1:2003 的连接

sudo /sbin/conntrack -I -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 --timeout 100000

  1. 最后,我从我的电脑使用源端口 2001 连接到 192.168.30.1:2002:

sudo nc -u -p 2001 192.168.30.1 2002

由于 netfilter DNAT 规则,我预期输出数据包的目标端口为 2003,源端口为 2001。然而,在 wireshark 上,我发现源端口已更改为随机数。我猜这是因为我的计算机认为端口 2001 上存在现有连接(由于 conntrack 条目),然后阻止源端口为 2001(对吗?)。但我不想要这种行为?我该如何强制使用端口号 2001?

答案1

为了使 DNAT 正常工作(即,使 上的程序能够识别回复),需要执行“反向 NAT”,将回复流量的源端口从192.168.30.1(到192.168.30.3:2001)更改2003为。2002

然而,当有流量来自192.168.30.1:2003某个192.168.30.3:2001主机,而从 conntrack 的角度来看,这些流量不是 DNAT 的结果(因为根据创建的 conntrack 条目,主机不是发起连接的主机),则反向 NAT 将不合适。

192.168.30.1:2003因此,netfilter 被“强制”对符合 DNAT 规则的流量也执行 SNAT,以便它可以根据目标区分回复流量(也是来自的) 192.168.30.3:$random

我假设 netfilter 要么在执行 SNAT 的反向 NAT(即 DNAT)之前执行 DNAT 的反向 NAT(即 SNAT),要么设法使用 SNAT 的反向 NAT 之前的目标(即192.168.30.3:$random)作为 DNAT 的反向 NAT 的匹配,否则强制 SNAT 将毫无意义。(然而,在非逆转情况下,据我所知,这两种情况都不成立:DNAT 将在 INPUT 中的 SNAT 之前在 PREROUTING 中执行,并且 SNAT 规则中的目标匹配(如果有)将使用 DNAT 中的结果值)


问题是,上面的故事/你问题中的“问题”在现实中几乎没有任何意义。以双主机 wireguard VPN 为例:假设你想Endpoint=在两台主机上都进行设置(以便它们中的任何一台都可以发起通信)并且不希望由于强制 SNAT(假设实际上可以触发)而意外“更新”值,你应该做的只是一个“始终在线”的 SNAT,它“补充”DNAT/相当于保留 NAT:

iptables -t nat -A INPUT -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 -j SNAT --to-source :2002

由于 DNAT 的自动反向 NAT,这在客户端-服务器模型中通常不是必需的。

PS 不过你仍然不应该192.168.30.1:2003通过它到达192.168.30.1:2003,否则如果你在前者的 conntrack 条目被删除之前再次通过它到达,也会出现强制源 NAT。INPUT192.168.30.1:2002中的附加 SNAT 规则也不会给你带来额外的麻烦。

答案2

您可以设置两个通常会在连接跟踪查找表(因此通常会触发新流上的源端口重写以避免冲突)位于不同的连接跟踪区域. 此附加区域属性使得连接跟踪与不同 conntrack 区域中的现有流不匹配/冲突:不会发生源端口重写。

对于您的具体示例,这里有一条特定的规则,可以防止冲突,从而防止源端口重写:

iptables -t raw -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001  --dport 2002 -j CT --zone-orig 1

通常根据用例使用更合理的选择器。它通常在 PREROUTING 链中使用,在路由时使用传入接口作为选择器,并且通常与标记值相关联,因此路由也会受到影响。


导致此选项出现的原始用例是连接跟踪在同一网络堆栈上(没有额外的网络命名空间),具有复杂的路由设置(例如:使用相同的 IP 地址在 4 个不同的私有 LAN 之间进行路由。例如 192.168.1.0/24 eth0 <-> eth1 10.1.0.0/24 之间,以及再次192.168.1.0/24 eth2 <-> 10.1.0.0/24 eth3) 可以看到两个具有相同地址/端口的不相关流。网络过滤器连接跟踪对路由一无所知(连接跟踪查找表仅包含地址),必须教会他们通过添加与路由拓扑手动绑定的区域属性来分别考虑这些流连接跟踪查找表。

(这是一个LWN 链接当该功能最初被提出时。

答案3

NAT 改变源端口以降低端口冲突的风险,如果该运动 2002 在 NAT 机器上已经很忙,会发生什么情况?

如果您对特定端口有特定要求,那么您可以SNAT为其添加特定规则,但是,如果多个内部客户端尝试使用相同的源端口怎么办?

这里我们应该回过头来承认 NAT 是一种黑客手段,旨在减少公共 IP 地址不足的问题。真正的解决办法是让每个人都拥有非 NAT 公共 IP。

如今,当我们谈论 NAT 时,我们通常指的是一个 IP 后面的私有 IP 地址,在这些情况下,它实际上是神经性皮炎 A与此相关的类似问题,我在想MASQUERADE目标,而不是DNAT

相关内容