私は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
その意図は、Aからの TCPはすべて、Rのポート50000 を使用して192.0.2.1としてマスクされることです。
を使用して、Bのポート60000にTCPサービスを公開しましたnc -4l 192.0.2.8 60000
。
次に、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:Address already in use」で失敗すると予想していました。これは、2つのncを同じポートにバインドした場合に発生します。
それから私はしばらく待ったので、conntrackのマッピングは死んでしまいました。
2番目の実験は、Rのクライアントを最初に開こうとする私から成っていました。RはBとうまく話し始めます。次にAから接続を開くと、そのパケットは無視されます。AのSYNはRに到着しますが、ICMPエラーによっても応答されません。これがRがマスカレードポートを使い果たしたことがわかっているためか、Linuxが完全に混乱しているためか(技術的にはポートをマスクしていますが、すでに確立されている接続が何らかの形で干渉しているため)かどうかはわかりません。
NATの動作は間違っていると感じます。マスカレード(特に、--to-ports
iptablesルールで指定しないこと)とサービスの両方のポートを誤って構成してしまう可能性があり、カーネルが接続をサイレントにドロップします。また、このドキュメントはどこにも記載されていません。
例えば:
- AはBに通常の要求を行います。ポート50kを使用するRマスク。
- AはRに DNSクエリを作成します。ことであるTは再帰的であり、R(薄手の一致のうち、エフェメラルポート50Kを使用して)クエリ権威あるネームサーバZポート53に。
衝突が発生しました。Rは2つの個別のTCP接続にポート50kを使用しています。
通常、ルーターでサービスを公開しないためだと思います。しかし、もう一度言いますが、TCPポートプールがアクティブにマスカレードされたときに、カーネルがTCPポートプールからポートを「借りる」のは難しいのでしょうか。
エフェメラルポートをから分離できることはわかってい--to-ports
ます。ただし、これはデフォルトの動作ではないようです。NATとエフェメラルポートはどちらもデフォルトで32768〜61000であり、これは気味が悪いです。
(私は/ proc / sys / net / ipv4 / ip_local_port_rangeをクエリすることで一時的な範囲を、別の実験で多数のUDPリクエストを単純にNAT処理してNAT範囲を見つけ、サーバー側でソースポートを出力しました。見つかりませんでした。 iptablesを使用して範囲を印刷する方法。)