iptablesが許可されたパケットの2番目以降のフラグメントを拒否するのはなぜですか?


9

相互にIPSec接続をセットアップしようとしている2つのホストがあります。このため、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パケットがフラグメント化されていて、2番目のフラグメントが入った後に到達不能な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はフラグメントをパケットフィルターに渡す前にフラグメントを自動的に再構成するという印象を受けました。それでは、なぜこれらのフラグメントが再構成されないため、2番目のフラグメントが拒否されたのでしょうか。


注意点として、IMEは、あなたはまた、ESPできるようにする必要があります:iptables -A INPUT -p esp -j ACCEPT
fukawi2

@ fukawi2はい、しかしそれはこの質問には関係ありません。
マイケルハンプトン

回答:


14

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.