Netcat

儘管程序正在偵聽,但 UDP 埠無法訪問

  • August 21, 2018

我正在嘗試通過 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 之間的相同測試會產生相同的結果。

如何解釋這種行為?

由於 UDP“連接”的工作方式,這是預期的行為。這nc6(1)手冊頁socat(“UDP”)中進行了討論,但也適用於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

如您所見,發送方的源埠發生了變化,但如果我強制它重用相同的埠,它就可以工作。

引用自:https://unix.stackexchange.com/questions/420570