儘管程序正在偵聽,但 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 之間的相同測試會產生相同的結果。
如何解釋這種行為?
由於 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
如您所見,發送方的源埠發生了變化,但如果我強制它重用相同的埠,它就可以工作。