web-dev-qa-db-ja.com

UDPを使用したnetcatの奇妙な動作

NetcatとUDPで動作する奇妙な動作に気づきました。 UDPポートで待機するnetcatのインスタンス(インスタンス1)を開始します。

nc -lu -p 10000

だから私はnetcat(インスタンス2)の別のインスタンスを起動し、私のプロセスにデータグラムを送信しようとします:

nc -u 127.0.0.1 10000

データグラムが表示されます。しかし、インスタンス2を閉じてnetcat(インスタンス3)を再起動すると、次のようになります。

nc -u 127.0.0.1 10000

インスタンス1の端末でデータグラムを表示できません。不思議なことに、オペレーティングシステムはインスタンス2に対してインスタンス3で別のUDPソースポートを割り当てており、問題があります。同じインスタンスの2ソースポート(例50000)を使用している場合:

 nc -u -p 50000 127.0.0.1 10000

再びnetcatのインスタンス1がデータグラムを受信します。 UDPはコネクションレスプロトコルなので、なぜですか?これは標準のnetcatの動作ですか?

32
MirkoBanchi

ncがUDPソケットをリッスンしているときは、受信する最初のパケットのソースポートとソースIPに「ロックオン」します。このトレースをチェックしてください:

socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(10000), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
recvfrom(3, "f\n", 2048, MSG_PEEK, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, [16]) = 2
connect(3, {sa_family=AF_INET, sin_port=htons(52832), sin_addr=inet_addr("127.0.0.1")}, 16) = 0

ここでは、UDPソケットを作成し、アドレスを再利用できるように設定し、ポート10,000にバインドしていることがわかります。最初のデータグラムを(ポート52,832から)受信するとすぐに、connectシステムコールを発行して、それを127.0.0.1:52,832に「接続」します。 UDPの場合、connectは、connectのIPとポートに一致しないすべてのパケットを拒否します。

40
David Schwartz

使用 - -kオプション:

nc -l -u -k 0.0.0.0 10000
  • -kはキープアライブを意味し、netcatは接続ごとにリッスンし続けます
  • -uはUDPを意味します
  • -lポート10000で待機
5

私のOSバージョンでnetcatをあきらめた場合、これはかなり短く、仕事が完了します。

#!/usr/bin/Ruby
# Receive UDP packets bound for a port and output them
require 'socket'
require 'yaml'

unless ARGV.count == 2
  puts "Usage: #{$0} listen_ip port_number"
  exit(1)
end
listen_ip = ARGV[0]
port = ARGV[1].to_i

u1 = UDPSocket.new
u1.bind(listen_ip, port)
while true
  mesg, addr = u1.recvfrom(100000)
  puts mesg
end
3
James Kay

受け入れられた回答が説明するように、ncatはUDPプロトコルで--keep-openをサポートしていないようです。ただし、表示されるエラーメッセージは回避策のヒントです。

Ncat: UDP mode does not support the -k or --keep-open options, except with --exec or --sh-exec. QUITTING.

--exec /bin/catを追加するだけで、--keep-openを使用できます。入力と出力の両方が/bin/catに接続されます。クライアントが送信するものはすべてコピーされて「エコーサーバー」に変換されます。

入力でより便利なことを行うには、シェルのリダイレクト演算子を使用できます(したがって、--sh-execではなく--execが必要です)。端末でデータを表示するために、これは機能します:

ncat -k -l -u -p 12345 --sh-exec "cat > /proc/$$/fd/1"

注意:上記の例では、ncatの親シェルのstdoutにデータを送信します。追加のリダイレクトと組み合わせると混乱を招く可能性があります。すべての出力をファイルに単純に追加する方が簡単です。

ncat -k -l -u -p 12345 --sh-exec "cat >> ncat.out"
0
Todd Owen