为什么 iptables 拒绝允许的数据包的第二个和后续片段?

为什么 iptables 拒绝允许的数据包的第二个和后续片段?

我有两台主机试图建立 IPSec 连接。为此,它们必须在 UDP 端口 500 和 4500 上进行通信,因此我在两端的防火墙中都打开了它们(如相关部分所示):

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m udp -p udp --dport 500 -j ACCEPT
-A INPUT -m udp -p udp --dport 4500 -j ACCEPT
#.....
-A INPUT -j REJECT --reject-with icmp6-port-unreachable

然而,密钥交换从未成功。双方不断尝试重新传输 UDP 数据包,却从未收到任何响应,直到最终放弃。

tcpdump从一端开始,发现 UDP 数据包被分段,并且第二个分段进入后返回 ICMP 端口不可达信息。

此类失败交换的一个示例(为保护您的安全已进行净化):

04:00:43.311572 IP6 (hlim 51, next-header Fragment (44) payload length: 1240) 2001:db8::be6b:d879 > 2001:db8:f:608::2: frag (0x5efa507c:0|1232) ipsec-nat-t > ipsec-nat-t: NONESP-encap: isakmp 2.0 msgid 00000001 cookie 55fa7f39522011ef->f8259707aad5f995: child_sa  ikev2_auth[I]: [|v2e] (len mismatch: isakmp 1596/ip 1220)
04:00:43.311597 IP6 (hlim 51, next-header Fragment (44) payload length: 384) 2001:db8::be6b:d879 > 2001:db8:f:608::2: frag (0x5efa507c:1232|376)
04:00:43.311722 IP6 (hlim 64, next-header ICMPv6 (58) payload length: 432) 2001:db8:f:608::2 > 2001:db8::be6b:d879: [icmp6 sum ok] ICMP6, destination unreachable, length 432, unreachable port[|icmp6]

防火墙记录了该数据包的以下内容:

Aug 26 04:00:43 grummle kernel: iptables: REJECT IN=eth0 OUT= MAC=############### SRC=2001:0db8:0000:0000:0000:0000:be6b:d879 DST=2001:0db8:000f:0608:0000:0000:0000:0002 LEN=424 TC=0 HOPLIMIT=51 FLOWLBL=0 OPT ( FRAG:1232 ID:5efa507c ) PROTO=UDP

我的印象是 Linux 会自动重组片段,然后再将它们传递给数据包过滤器。那么为什么这些片段没有被重组,因此第二个片段随后被拒绝?

答案1

netfilter 代码仅在数据包过滤之前为您重新组装片段如果您的防火墙规则使用连接跟踪(即防火墙规则是有状态的,并使用-m conntrack或已弃用的-m state)或 NAT。否则,所有片段都会被单独处理,您会遇到类似这样的问题。

这使得解决问题变得简单而明显(无论如何,事后看来)。只需将连接跟踪添加到相关防火墙规则中即可。

-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m conntrack --ctstate NEW -m udp -p udp --dport 500 -j ACCEPT
-A INPUT -m conntrack --ctstate NEW -m udp -p udp --dport 4500 -j ACCEPT

或者对于较旧的 Linux 系统(例如 RHEL 5 及更早版本):

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 500 -j ACCEPT
-A INPUT -m state --state NEW -m udp -p udp --dport 4500 -j ACCEPT

相关内容