私はユーザースペースでIPフラグメントを処理したいと思い、iptables NF_QUEUEを使用してパケットをユーザースペースに転送しています。
問題は、IPv4パケットが常に個々のフラグメントではなく1つのパケットに再組み立てされて転送されることです。 IPv6の場合、フラグメントは期待通りに渡されます。
私はconntrackerがこの問題を引き起こす可能性があると思い、raw
iptablesテーブルで無効にしましたが、元のテーブルに到達したときにパケットがすでに再構築されていることがわかりました。
# iptables -t raw -nvL
Chain PREROUTING (policy ACCEPT 58 packets, 62981 bytes)
pkts bytes target prot opt in out source destination
1 30028 CT all -- * * 0.0.0.0/0 10.0.0.0/24 NOTRACK
これは、IPv4を介して30000バイトUDPパケットを送信したときに発生する現象です。 IPv6に対応:
# ip6tables -t raw -nvL
Chain PREROUTING (policy ACCEPT 46 packets, 62304 bytes)
pkts bytes target prot opt in out source destination
21 31016 CT all * * ::/0 1000:: NOTRACK
これは、virtioネットワークデバイスmtu = 1500を持つ仮想環境kvm / qemuにあります。 tcpdump -ni eth2 host 10.0.0.0
.
だから私の質問は、LinuxカーネルでIPv4パケットがnetfilterチェーンの前に再組み立てられるように強制できることですかraw/PREROUTING
?
AF_PACKET(tcpdump) と raw/PREROUTING チェーンの間にあるため、 "ingress/qdisc" が疑われますが、問題が見つかりません。
パケットフロー方向:https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg
答え1
いつでもつながる使用中は主に次の目的で使用されます。
- ステートフルファイアウォール(
-m conntrack ...
) - ネットワークアドレス変換(
-t nat ...
)
nf_defrag_ipv4
カーネルモジュールが提供する追加の隠し機能をロードしますnf_defrag_ipv6
。施設は優先順位-400でネットワーク事前ルーティングに接続されます。iptables '元のテーブルは優先順位-300に固定されています。パケットが通過した後、nf_defrag_ipv[46]
フラグメントは存在しません。パケットは事前に再組み立てされます。目的は、NetfilterとiptablesのさまざまなプロトコルチェッカーがUDP宛先ポートを含むすべてのパケットコンテンツを取得できることです。この情報は最初のフラグメントにのみ表示されます。
したがって、このような状況を回避するには、元のテーブルの(で使用されていない)だけでは-j NOTRACK
不十分です。-j CT --notrack
一つは数:
絶対に使用しないでくださいつながる直接(ステータスルール)または間接的に(NAT)、
または新しいネットワーク名前空間を作成する
トラフィックを直接処理します(通常、盗まれた物理インターフェイスを使用するか、マクエバーランドインターフェイスまたはブリッジしかし、ルーティングされていませんホストによって)この名前空間でステートフルルールが発生しないことを確認してください。強制的に実行しない限り、デフラグツールはネットワーク名前空間に接続されません(そしておそらくより新しいカーネルを使用するかもしれません)。
または、優先順位-400より前に接続されたチェーンがあります。これは実際に最近のカーネルで可能です:
~のためiptables - 旧バージョン~からカーネル(おそらく) >= 4.16
# modinfo -p iptable_raw raw_before_defrag:Enable raw table before defrag (bool)
元のテーブルを更新し、モジュールをアンロードしてから再ロード(および調整
/etc/modprobe.d/
)します。modprobe iptable_raw raw_before_defrag=1
~のためnftables
たとえば、-400より低い優先順位でチェーンを作成します。
nft add table ip handlefrag nft add chain ip handlefrag predefrag '{ type filter hook prerouting priority -450; policy accept; }' nft add rule ip handlefrag predefrag ip 'frag-off & 0x3fff != 0' notrack
(最初の部分ではなく、次の部分だけが処理され
0x3fff
ます0x1fff
。IPv6の場合、アプローチは異なります。フラグメントヘッダーは次のとおりです。いいえ次のタイトル。しかし、NFFTman は、
exthdr frag exists
フラグメントに属するパケットを検出する簡単な表現を提供します。何も存在しないiptables-nftAPI(Debianなどの多くのディストリビューションのデフォルト):このモジュールは使用しません。iptable_raw実際のオプションは生成されません。nftables優先順位が-450のチェーンです。
したがって、コマンドの出力が次のような場合:
# iptables -V iptables v1.8.7 (nf_tables)
これだけでは使えませんつながる。次に戻す必要があります。iptables - 旧バージョンまたはに切り替えNFFT、または...
まだできることは混ぜることnftables(上記のルール)パケットを次のように表示します。追跡しないデフラグしてから続行する前にiptables残りを処理するため。使用に問題はありませんnftablesそしてiptablesその間、OPに接続されたNetfilterダイアグラムの作業順序を理解してください。
答え2
iptables
(IPv4の場合)このフラグがあります-f
。追加すると動作します。また、チェーンを確認してくださいINPUT
。
[!] -f, --fragment
つまり、ルールは、フラグメント化されたパケットの2番目以降のIPv4フラグメントにのみ適用されます。これらのパケット(またはICMPタイプ)の送信元ポートまたは宛先ポートは不明であるため、パケットはそれを指定するルールと一致しません。いつ。 。 。 「!」引数が「-f」フラグの前にある場合、ルールはヘッダーフラグメントまたはフラグメント化されていないパケットとのみ一致します。このオプションはIPv4に固有のものであり、ip6tablesでは使用できません。