Socat:从标准输入发送 UDP 广播,但使用 SYSTEM 处理响应

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。)

参考:

答案1

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 已经获得了所需的一切。

主要是为了其他读者的利益,我将描述所做的事情并给出一个完整的示例。


如果一个索卡特由于限制,命令无法完成工作,使用两个索卡特对于这种情况,将全双工通信通道分成两个单工通道。

一个将用于读回答案,另一个用于发送广播。再次,解决方法索卡特限制,阅读索卡特必须UDP-RECVFROMforkand一起使用-u(用于只读,因此其结果将是标准输出,而不是被发送回响应者),而不是通常自然的选择UDP-RECV:即允许为每个数据包分叉一个命令,并通过环境变量传输每个数据包的元数据。另外,正如OP所写,必须提前选择一个端口,以便它们都使用相同的端口。发送套接字也必须使用-u以避免读回答案并将其窃取到其他专用套接字的风险索卡特命令。

以下是 LAN 中的示例,其中本地系统具有 192.0.2.2/24,对等系统具有 192.0.2.3/24。

对等系统(响应者)命名同行:

$ 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不需要检索同行的地址。需要检索当地的地址,对于多宿主系统最有用,因此它知道其多个地址中的哪一个接收到数据报,或者还知道接收到的数据报是否是广播。即使没有此选项,对等方的地址信息也始终可用。 *BSD 只需要将此选项替换为ip-recvdstaddr,ip-recvif(=> IP_RECVDSTADDR+ IP_RECVIF) 即可接收相同的信息。

相关内容