Socat:從標準輸入發送 UDP 廣播,但使用 SYSTEM 處理響應
我正在嘗試使用
socat
. 發現是通過將 UDP 廣播發送到具有小負載的明確定義的埠來完成的,然後偵聽來自我網路上這些設備的“回复”。如果我使用雙向
socat
並且“響應”轉到標準輸出,則此方法有效:echo -ne "\x00\x01\x00\xF6" | socat -t5 - udp-datagram:255.255.255.255:30718,broadcast |xxd -p
來自本地網路上一些設備的範例響應(每行是來自不同設備的響應):
000000f70020300258366d112c15000062a71b21ff0000000080a3d2ded9 000000f70020300258366d112c15000062a71b21ff0000000080a3a40670 000000f70020300258366d112c15000062a71b21ff0000000080a3b94ca0 000000f70020300258366d112c15000062a71b21ff0000000080a3a4046b
有效載荷是我所期望的,但是我缺少的是發件人元數據,特別是如果我使用
ip-pktinfo,fork SYSTEM:
. 所以我想要的是從標準輸入發送初始廣播,但用於SYSTEM
處理返回的結果數據包。我嘗試了一些
-u
單向模式的變體,但我似乎沒有在我的監聽器上接收到數據:# Listener: socat -u udp-recvfrom:30222,reuseaddr,ip-pktinfo,fork SYSTEM:./test.sh & # Broadcast: echo -ne "\x00\x01\x00\xF6" | socat -u - udp-datagram:255.255.255.255:30222,sourceport=30222,broadcast,reuseaddr
請注意“此端”源埠可能是隨機的,因此我明確選擇
30222
,以便我的廣播源埠與我的響應偵聽器匹配。例如,如果廣播來自埠 9987,客戶端會將其單播響應發送回埠 9987。如果我以這種方式執行單向廣播,我偶爾會收到響應;我有一種感覺,這取決於廣播過程退出的速度。(我打算接下來檢查數據包擷取;我正在遠端機器上進行測試,我必須先刷新我的記憶
tcpdump
。)參考:
OP 提到
ip-pktinfo
這通常是 Linux 套接字選項(用於IP_PKTINFO
)。我將在下面假設 Linux(但請參閱 *BSD 末尾的註釋)。這個選項實際上是不需要的(另見最後的註釋),但可以添加以獲取更多資訊。關鍵部分是使用
reuseport
切換SO_REUSEPORT
套接字選項的選項:
SO_REUSEPORT
(自 Linux 3.9 起)允許將多個 AF_INET 或 AF_INET6 套接字綁定到相同的套接字地址。在對套接字呼叫 bind(2) 之前,必須在每個套接字(包括第一個套接字)上設置此選項。為防止埠劫持,綁定到同一地址的所有程序必須具有相同的有效 UID。此選項可用於 TCP 和 UDP 套接字。
除了這個缺失的選項,OP 已經得到了所有需要的東西。
主要是為了其他讀者的利益,我將描述所做的事情並給出一個完整的例子。
如果一個socat命令由於限制無法完成工作,則使用兩個socat,將全雙工通信通道分成兩個單工通道,適用於這種情況。
一個用於回讀答案,另一個用於發送廣播。同樣,為了解決socat限制,讀取socat必須使用
UDP-RECVFROM
andfork
(-u
對於只讀,因此其結果將發送到stdout,而不是被發送迴響應者)而不是通常自然的選擇UDP-RECV
: 這是允許每個數據包派生一個命令,並通過環境變數傳輸每個數據包的元數據。同樣正如 OP 所寫,必須提前選擇一個埠才能讓它們都使用相同的埠。發送套接字也必須使用-u
以避免冒險讀回答案並將其竊取給其他專用socat命令。這是區域網路中的一個範例,本地系統具有 192.0.2.2/24,對等系統具有 192.0.2.3/24。
名為peer 的對等系統(響應者):
$ socat udp4-recvfrom:30718,fork system:hostname
本地系統的 term1 (也可以選擇使用
,ip-pktinfo
):$ socat -u udp4-recvfrom:30222,reuseport,fork system:'cat; printenv|grep -E \"SOCAT_.*(ADDR|PORT)\"'
本地系統的術語2:
$ echo dummyprobe | socat -u - udp-datagram:255.255.255.255:30718,bind=:30222,reuseport,broadcast
在第 1 學期收到的回复:
peer SOCAT_PEERADDR=192.0.2.3 SOCAT_PEERPORT=30718
筆記
- FreeBSD 有類似的描述
SO_REUSEPORT
(或者更確切地說,Linux 最近與 *BSD 對齊):
SO_REUSEPORT
如果它們在綁定埠之前都設置了 SO_REUSEPORT,則允許多個程序完全重複綁定。此選項允許程序的多個實例分別接收發往綁定埠的 UDP/IP 多播或廣播數據報。
ip-pktinfo
不需要檢索peer的地址。它需要檢索本地地址,並且對於多宿主系統非常有用,因此它知道它的多個地址中的哪個地址接收到數據報,或者還知道接收到的數據報是否是廣播。即使沒有此選項,對等方的地址資訊也始終可用。*BSD 只需將此選項替換為ip-recvdstaddr,ip-recvif
(=>IP_RECVDSTADDR
+IP_RECVIF
) 即可接收相同的資訊。