web-dev-qa-db-ja.com

NATマシンのTCPおよびUDPポートプールからポートを予約しないのはなぜですか?

私は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を指定しないことにより)とサービスの両方のポートを誤って構成する可能性があり、カーネルは接続をサイレントにドロップします。また、この文書はどこにも見当たりません。

例えば:

  • [〜#〜] a [〜#〜][〜#〜] b [〜#〜]に通常のリクエストを行います。 [〜#〜] r [〜#〜]ポート50kを使用してマスクします。
  • [〜#〜] a [〜#〜][〜#〜] r [〜#〜]にDNSクエリを実行します。 [〜#〜] t [〜#〜]は再帰的であるため、[〜#〜] r [〜#〜](使用、偶然の一致から、一時的ポート50k)は、信頼できるネームサーバーを照会します[〜#〜] z [〜#〜]ポート53で。

衝突が発生しました。 [〜#〜] r [〜#〜]は、2つの別々のTCP接続にポート50kを使用しています。

通常はルーターでサービスを公開していないからだと思います。しかし、繰り返しになりますが、アクティブにマスカレードされたときにTCPポートプールからポートを「借用」することはカーネルを傷つけますか?

エフェメラルポートを--to-portsから分離できることを知っています。ただし、これはデフォルトの動作ではないようです。 NATとエフェメラルポートのデフォルトは32768-61000で、これは不気味です。

(/ proc/sys/net/ipv4/ip_local_port_rangeをクエリして一時的な範囲を見つけ、別の実験で大量のUDPリクエストをNATするだけで、NAT範囲を見つけました。サーバー側。iptablesを使用して範囲を出力する方法が見つかりませんでした。)

8
Yd Ahhrk

カーネルがアクティブにマスカレードされたときに、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を同じポートにバインドした場合に発生します。

私はまだこれに対する防弾の答えを探していますが、すべてが「それがどのように実装されているかという悪影響であり、私たちがそれと一緒に暮らすことをいとわないほど小さい」ことを示しているようです。

2
Yd Ahhrk