Por que o iptables está rejeitando o segundo e os fragmentos subsequentes de um pacote permitido?

9

Eu tenho dois hosts que estão tentando configurar uma conexão IPSec entre si. Para isso, eles precisam se comunicar nas portas UDP 500 e 4500, então eu as abri nos firewalls nas duas extremidades (mostradas na parte relevante):

-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

No entanto, a troca de chaves nunca é bem-sucedida. Cada lado continua tentando retransmitir os pacotes UDP repetidamente, nunca ouvindo uma resposta, até que eles finalmente desistem.

Comecei tcpdumppor um lado e observei que o pacote UDP estava sendo fragmentado e que uma porta ICMP inacessível estava sendo retornada após a chegada do segundo fragmento.

Um exemplo de uma troca com falha (higienizada para sua proteção):

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]

O firewall registrou o seguinte em relação a este pacote:

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

Fiquei com a impressão de que o Linux remontou fragmentos automaticamente antes de passá-los para o filtro de pacotes. Então, por que esses fragmentos não estão sendo remontados e, portanto, o segundo fragmento é posteriormente rejeitado?

Michael Hampton
fonte
Como uma nota lateral, IME você também precisa permitir ESP:iptables -A INPUT -p esp -j ACCEPT
fukawi2
@ fukawi2 Sim, mas isso não é relevante para esta questão.
Michael Hampton

Respostas:

14

O código netfilter remonta apenas fragmentos para você antes da filtragem de pacotes se as regras do firewall usarem rastreamento de conexão (ou seja, a regra do firewall é válida e usa -m conntrackou é obsoleta -m state) ou NAT. Caso contrário, todos os fragmentos serão processados ​​separadamente e você terá problemas como este.

Isso torna a solução do problema fácil e óbvia (em retrospecto, pelo menos). Basta adicionar o rastreamento de conexão às regras de firewall em questão.

-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

Ou para sistemas Linux mais antigos (por exemplo, RHEL 5 e versões anteriores):

-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
Michael Hampton
fonte