転送されたIPv4パケットの不要なデフラグ

転送されたIPv4パケットの不要なデフラグ

私はユーザースペースでIPフラグメントを処理したいと思い、iptables NF_QUEUEを使用してパケットをユーザースペースに転送しています。

問題は、IPv4パケットが常に個々のフラグメントではなく1つのパケットに再組み立てされて転送されることです。 IPv6の場合、フラグメントは期待通りに渡されます。

私はconntrackerがこの問題を引き起こす可能性があると思い、rawiptablesテーブルで無効にしましたが、元のテーブルに到達したときにパケットがすでに再構築されていることがわかりました。

# 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ダイアグラムの作業順序を理解してください。

おすすめ記事