私は2つの実験をしました。これは両方のネットワークです。
[private network] [public network]
A -------------------- R ----------------- B
192.168.0.5 192.168.0.1|192.0.2.1 192.0.2.8
[〜#〜] a [〜#〜]のデフォルトゲートウェイは[〜#〜] r [〜#〜]です。 [〜#〜] r [〜#〜] IPv4転送がアクティブであり、次のiptablesルールがあります。
iptables -t nat -A POSTROUTING -p TCP -j MASQUERADE --to-ports 50000
意図は、TCP from [〜#〜] a [〜#〜]は[〜#〜 ] r [〜#〜]のポート50000。
nc -4l 192.0.2.8 60000
を使用して、TCPサービスをポート60000で[〜#〜] b [〜#〜]に公開しました。
次に、[〜#〜] a [〜#〜]:nc -4 192.0.2.8 60000
から接続を開きました
[〜#〜] a [〜#〜]次のようなパケットの送信を開始しました:
192.168.0.5:53269 -> 192.0.2.8:60000
[〜#〜] r [〜#〜]それをに翻訳
192.0.2.1:50000 -> 192.0.2.8:60000
ここまでは順調ですね。
次に、次のクライアントを[〜#〜] r [〜#〜]:nc -4 192.0.2.8 60000 -p 50000
で開こうとしました。メッセージを送信しましたが、何も起こりません。 [〜#〜] r [〜#〜]のtcpdumpにパケットが表示されません。
マスカレードルールが存在するため、または少なくともアクティブであるため、[〜#〜] r [〜#〜]のncがエラーメッセージ「nc:アドレスはすでにあります」で失敗すると予想していました。 「use」。これは、2つのNCを同じポートにバインドした場合に発生します。
それからしばらく待ったので、conntrackのマッピングは死にました。
2番目の実験は、私が最初に[〜#〜] r [〜#〜]のクライアントを開こうとしたことで構成されました。 [〜#〜] r [〜#〜]会話を開始します[〜#〜] b [〜#〜]問題ありません。その後、[〜#〜] a [〜#〜]から接続を開くと、そのパケットは無視されます。 [〜#〜] a [〜#〜]のSYNは[〜#〜] r [〜#〜]に到達しますが、応答されません。 ICMPエラーでも。これが[〜#〜] r [〜#〜]マスカレードポートが不足していることを知っているためか、Linuxが完全に混乱しているためかはわかりません(技術的にはポートをマスクしますが、すでに確立されている接続が何らかの形で干渉します)。
NATの振る舞いが間違っているように感じます。マスカレード(特に、iptablesルールで--to-ports
を指定しないことにより)とサービスの両方のポートを誤って構成する可能性があり、カーネルは接続をサイレントにドロップします。また、この文書はどこにも見当たりません。
例えば:
衝突が発生しました。 [〜#〜] r [〜#〜]は、2つの別々のTCP接続にポート50kを使用しています。
通常はルーターでサービスを公開していないからだと思います。しかし、繰り返しになりますが、アクティブにマスカレードされたときにTCPポートプールからポートを「借用」することはカーネルを傷つけますか?
エフェメラルポートを--to-ports
から分離できることを知っています。ただし、これはデフォルトの動作ではないようです。 NATとエフェメラルポートのデフォルトは32768-61000で、これは不気味です。
(/ proc/sys/net/ipv4/ip_local_port_rangeをクエリして一時的な範囲を見つけ、別の実験で大量のUDPリクエストをNATするだけで、NAT範囲を見つけました。サーバー側。iptablesを使用して範囲を出力する方法が見つかりませんでした。)
カーネルがアクティブにマスカレードされたときに、TCPポートプールからポートを「借用」することは、カーネルを傷つけますか?
答えは「いいえ、でも大した問題ではない」だと思います。
[〜#〜] r [〜#〜]は、応答パケットの宛先トランスポートアドレスのみを使用して、に向かっているかどうかを判断すると誤って想定しました。 [〜#〜] a [〜#〜]またはそれ自体。実際には、送信元と宛先のトランスポートアドレスタプル全体を使用して接続を識別しているようです。したがって、NATが同じ([〜#〜] r [〜#〜]所有)ポートを使用して複数の接続を作成することは実際には正常です;混乱を招くことはありません。したがって、TCP/UDPポートプールは重要ではありません。
私がそれについて考えることは今ではかなり明白です。
次に、[〜#〜] r [〜#〜]で次のクライアントを開こうとしました:
nc -4 192.0.2.8 60000 -p 50000
。メッセージを送信しましたが、何も起こりません。 [〜#〜] r [〜#〜]のtcpdumpにパケットが表示されません。
これは私が台無しにした実験の一部です。
送信元アドレスが同じであるという理由だけでなく、送信元および宛先トランスポートアドレスが同じであるために失敗が発生します。
たとえば、nc -4 192.0.2.8 60001 -p 50000
を実行すると、実際に機能します。 NATマスクと同じポートを使用している場合でも。
NATの振る舞いが間違っているように感じます。マスカレード(特に、iptablesルールで
--to-ports
を指定しないことにより)とサービスの両方のポートを誤って構成する可能性があり、カーネルは接続をサイレントにドロップします。
マスクされた接続と[〜#〜] r [〜#〜]-開始された接続の宛先は異なる可能性が高いため、そうではありません。
マスカレードルールが存在するため、または少なくともアクティブであるため、[〜#〜] r [〜#〜]のncがエラーメッセージ "で失敗することを期待していました。 nc:アドレスはすでに使用されています」。これは、2つのncを同じポートにバインドした場合に発生します。
私はまだこれに対する防弾の答えを探していますが、すべてが「それがどのように実装されているかという悪影響であり、私たちがそれと一緒に暮らすことをいとわないほど小さい」ことを示しているようです。