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

我有两台主机试图build立一个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] 

防火墙针对这个数据包logging了以下内容:

 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在将它们传递给数据包filter之前会自动重新组合碎片。 那么为什么这些碎片没有被重新组装,因此第二个碎片随后被拒绝?

如果您的防火墙规则使用连接跟踪 (即防火墙规则是有状态的并且使用-m conntrack或不赞成的-m state )或NAT,则netfilter代码只会在数据包筛选之前为您重新组装碎片。 否则,所有的碎片都会被分别处理,你会得到像这样的问题。

这使得解决这个问题变得简单明了(无论如何回顾)。 只需将连接跟踪添加到有问题的防火墙规则。

 -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