web-dev-qa-db-ja.com

プロセスはリッスンしていますが、UDPポートに到達できません

UDPポート6666を介した通信を実験しています(netconsoleのリスナーを設定することを目標としていますが、ここではあまり関係ありません)。

リスニング側では、nc -luv 6666。送信側では、nc -uv LISTENER_IP 6666。私は送受信でき、人生は良いです。

リスナーを実行したままにしますが、送信者を強制終了して、別の送信者を開始します。すぐに終了します。ネットワークトレースにより、受信サーバーがICMP Port Unreachableを送信していることがわかります。ただし、リスナーは引き続き待機します。

$ Sudo ss -nlup|grep 6666
UNCONN     0      0           :::6666                    :::*                   users:(("nc",pid=3417,fd=3))

私は受信機を殺して、新しいものを走らせます。私が送信者を殺すまで、すべては以前のように機能します。

送信側と受信側は同じネットワーク上の物理マシンです。物理マシンとその上で実行しているVMの間で同じテストを実行すると、同じ結果が得られます。

この動作はどのように説明できますか?

2
berndbausch

UDP「接続」が機能する方法により、これは予想される動作です。これについては nc6(1)のマニュアルページ ( "UDP")で説明しますが、socatおよびncにも適用できます。

Netcat6のUDPサポートは、接続モードと待機モードの両方で非常にうまく機能します。リッスンモードでUDPを使用する場合、netcat6は、指定されたオプションのアドレスやポート(指定されている場合)に一致する任意のソースからのUDPパケットを受け入れます。ただし、最初のパケットが受信されると、netcat6は将来そのクライアントからのパケットのみを受信します。これは、UDPソケットを「接続済み」状態にすることによって行われます(udp(4)およびconnect(2)を参照)。他のソースからのパケットはカーネルによって破棄され、ICMP到達不能応答が送信されます。

UDPを使用してリモートホストに接続する場合、nc6は、リモートサーバーがリッスンしているかどうかに関係なく、接続が開いていることを報告します。これは、UDPがコネクションレス型プロトコルであるため、実際には接続の確立が必要ないためです。ただし、データの最初のパケットを送信した後、サーバーがICMP到達不能応答で応答し、nc6が「接続拒否」エラーメッセージで終了する場合があります。

送信側から接続すると、ランダムなUDPソースポートが選択されます。次に、レシーバーはその特定のHost:portペアにバインドし、それ以降は他の接続をリッスンしません。これを解決するには、送信者が常に同じポートを使用するように強制する必要があります。この例ではsocatを使用しました。

リスナー:

# socat -d -d UDP-LISTEN:6666 stdout
2018/01/29 22:02:02 socat[20969] N listening on UDP AF=2 0.0.0.0:6666
2018/01/29 22:02:07 socat[20969] N accepting UDP connection from AF=2 10.100.0.5:39000
2018/01/29 22:02:07 socat[20969] N using stdout for reading and writing
2018/01/29 22:02:07 socat[20969] N starting data transfer loop with FDs [5,5] and [1,1]
hello
bye
hello1
bye1

送信者:

# socat -d -d stdin UDP:listener-Host:6666
2018/01/29 22:01:56 socat[8237] N using stdin for reading and writing
2018/01/29 22:01:56 socat[8237] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:01:56 socat[8237] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:01:56 socat[8237] N starting data transfer loop with FDs [0,0] and [5,5]
hello
bye
2018/01/29 22:02:10 socat[8237] N socket 1 (fd 0) is at EOF    
2018/01/29 22:02:10 socat[8237] N exiting with status 0

# socat -d -d stdin UDP:listener-Host:6666
2018/01/29 22:02:13 socat[8238] N using stdin for reading and writing
2018/01/29 22:02:13 socat[8238] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:02:13 socat[8238] N successfully connected from local address AF=2 10.100.0.5:57125
2018/01/29 22:02:13 socat[8238] N starting data transfer loop with FDs [0,0] and [5,5]
hello
2018/01/29 22:02:16 socat[8238] E read(5, 0x5619f9b09330, 8192): Connection refused
2018/01/29 22:02:16 socat[8238] N exit(1)

# socat -d -d stdin UDP:listener-Host:6666,sourceport=39000
2018/01/29 22:05:17 socat[8280] N using stdin for reading and writing
2018/01/29 22:05:17 socat[8280] N opening connection to AF=2 10.100.0.3:6666
2018/01/29 22:05:17 socat[8280] N successfully connected from local address AF=2 10.100.0.5:39000
2018/01/29 22:05:17 socat[8280] N starting data transfer loop with FDs [0,0] and [5,5]
hello1
bye1
2018/01/29 22:05:23 socat[8280] N socket 1 (fd 0) is at EOF
2018/01/29 22:05:24 socat[8280] N exiting with status 0

ご覧のように、送信元で送信元ポートが変更されましたが、同じポートを再利用するように強制すると、機能しました。

3
ErikF