netfilter が送信元ポートを自動的に変更するのを防ぐ方法

netfilter が送信元ポートを自動的に変更するのを防ぐ方法

conntrack モジュールで接続が確立されると、netfilter が送信元ポートを変更することがわかりました。この動作を防ぐ必要があります。

問題を再現するために私が行ったことは次のとおりです。

  1. ポート2002から2003へのDNATを実行するネットフィルタールールを作成します

sudo iptables -w -t nat -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001 --dport 2002 -j DNAT --to-destination :2003

  1. 次に、192.168.30.1:2001 (私のコンピュータ) から 192.168.30.1:2003 への接続をシミュレートする conntrack エントリを作成します。

sudo /sbin/conntrack -I -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 --timeout 100000

  1. 最終的に、送信元ポート 2001 を使用してコンピューターから 192.168.30.1:2002 への接続を実行します。

sudo nc -u -p 2001 192.168.30.1 2002

netfilter DNAT ルールにより、出力パケットの宛先ポートが 2003、送信元ポートが 2001 であると予想しました。しかし、Wireshark で、送信元ポートがランダムな番号に変更されているのを確認しました。これは、コンピューターがポート 2001 に既存の接続があると見なし (conntrack エントリによる)、送信元ポートが 2001 にならないようにしているためだと思います (そうですよね?)。しかし、この動作は望ましくありません。ポート番号 2001 の使用を強制するにはどうすればよいでしょうか?

答え1

DNAT が機能するには (つまり、 のプログラムが応答を認識できるようにするには)、応答トラフィックの送信元ポートを から192.168.30.1( へ192.168.30.3:2001) から に2003変更する「リバース NAT」2002を実行する必要があります。

ただし、conntrack の観点から DNAT の結果ではないトラフィックが から に送信される場合には192.168.30.1:2003(192.168.30.3:2001作成された conntrack エントリに従って、ホストが接続を開始したものではないため)、リバース NAT は不適切になります。

したがって、netfilter は、DNAT ルールに一致するトラフィックに対しても SNAT を実行するように「強制」され、応答トラフィック (これも からのトラフィック192.168.30.1:2003) を宛先 によって区別できるようになります192.168.30.3:$random

私の推測では、netfilter は、SNAT のリバース NAT (SNAT です) の前に DNAT のリバース NAT (SNAT です) を実行するか、SNAT のリバース NAT (つまり192.168.30.3:$random) の前の宛先を DNAT のリバース NAT のマッチングとして使用するか、どちらかを行うでしょう。そうしないと、強制 SNAT は無意味になります。(ただし、非リバーサル ケースでは、私の知る限り、どちらも当てはまりません。DNAT は、INPUT の SNAT の前に PREROUTING で実行され、SNAT ルールの宛先マッチング (存在する場合) では、DNAT の結果の値が使用されます)


問題は、上記の話や質問の「問題」は、実際にはほとんど意味をなさないということです。2 ホストの Wireguard VPN を例に挙げてみましょう。Endpoint=両方のホストで設定し (どちらかが通信を開始できるように)、強制 SNAT (実際にトリガーされる可能性があると仮定) によって値が予期せず「更新」されないようにしたいとします。この場合、実行すべきことは、単に DNAT を「補完」する、または予備 NAT に相当する「常時オン」の SNAT です。

iptables -t nat -A INPUT -s 192.168.30.1 -d 192.168.30.3 -p udp --sport 2003 --dport 2001 -j SNAT --to-source :2002

DNAT の自動リバース NAT のため、クライアント サーバー モデルでは通常、これは必要ありません。

PSただし、192.168.30.1:2003で到達することはまだ想定されていません192.168.30.1:2003。そうしないと、前の conntrack エントリがドロップされる前に で再度到達した場合にも、強制ソース NAT が発生します192.168.30.1:2002。INPUT の追加の SNAT ルールによって、余分な問題が発生することはありません。

答え2

通常は衝突する2つのフローを設定できます。接続トラックルックアップテーブル(通常は衝突を避けるために新しいフローの送信元ポートの書き換えをトリガーする)が異なるconntrackゾーンこの追加のゾーンプロパティにより、接続トラック別の conntrack ゾーン内の既存のフローと一致/衝突しません。送信元ポートの書き換えは行われません。

具体的な例として、衝突を防ぎ、送信元ポートの書き換えを防ぐ具体的なルールを次に示します。

iptables -t raw -A OUTPUT -s 192.168.30.3 -d 192.168.30.1 -p udp --sport 2001  --dport 2002 -j CT --zone-orig 1

通常、ユースケースに応じて、より適切なセレクタが使用されます。これは、ルーティング時にセレクタとして着信インターフェイスを使用する PREROUTING チェーンでよく使用され、多くの場合、マーク値に関連付けられるため、ルーティングにも影響が及ぶ可能性があります。


このオプションが登場した元々の使用例は、接続トラック同じネットワークスタック(追加のネットワーク名前空間なし)上で複雑なルーティング設定(例:同じIPアドレスを使用する4つの異なるプライベートLAN間のルーティング。例:192.168.1.0/24 eth0 <-> eth1 10.1.0.0/24間、およびまた192.168.1.0/24 eth2 <-> 10.1.0.0/24 eth3)は、同じアドレス/ポートを持つ2つの無関係なフローを見ることができます。ネットフィルターそして接続トラックルーティングについて何も知らない(接続トラックルックアップテーブルにアドレスのみが含まれている場合、ルーティングトポロジに手動で関連付けられたゾーンプロパティを追加して、これらのフローを個別に考慮するように教える必要があります。接続トラックルックアップテーブル。

(ここにLWNリンク(この機能が最初に提案されたとき。)

答え3

NAT はポート競合のリスクを軽減するために送信元ポートを変更しますが、NAT マシンで sport 2002 がすでにビジー状態の場合はどうなるでしょうか?

特定のポートに特定の要件がある場合は、SNATそのための特定のルールを追加できますが、複数の内部クライアントが同じ送信元ポートを使用しようとした場合はどうなるでしょうか?

ここで、NAT はパブリック IP アドレスの不足の問題を軽減するために作成されたハックであることを認識する必要があります。ここでの本当の解決策は、すべての人が NAT 以外のパブリック IP を持つことです。

最近NATについて話すとき、私たちはほとんどの場合、1つのIPの背後にあるプライベートIPアドレスを意味します。これらのケースでは、実際にはナプト 1つのそれに関連する同様の質問MASQUERADE私はターゲットについて考えていましたが、DNAT

関連情報