![Linux下接收广播UDP数据包](https://linux22.com/image/683885/Linux%E4%B8%8B%E6%8E%A5%E6%94%B6%E5%B9%BF%E6%92%ADUDP%E6%95%B0%E6%8D%AE%E5%8C%85.png)
我遇到了类似的问题Linux 内核不传递多播 UDP 数据包仅广播而不是多播,而且我尝试过的任何方法都没有帮助。
我有一个位于 192.168.0.1 的设备,它发出广播 UDP 数据包,直接连接到 eth1(192.168.0.2)。eth0 是我真正的网络。ifconfig 告诉我,正如预期的那样,广播地址是 192.168.255.255
$ sudo ifconfig
eth0 Link encap:Ethernet HWaddr 54:04:a6:64:b5:a6
inet addr:172.16.128.1 Bcast:172.16.255.255 Mask:255.255.0.0
inet6 addr: fe80::5604:a6ff:fe64:b5a6/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1526809 errors:0 dropped:0 overruns:0 frame:0
TX packets:986480 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:807179430 (807.1 MB) TX bytes:747692150 (747.6 MB)
eth1 Link encap:Ethernet HWaddr 00:50:b6:15:6e:9a
inet addr:192.168.0.2 Bcast:192.168.255.255 Mask:255.255.0.0
inet6 addr: fe80::250:b6ff:fe15:6e9a/64 Scope:Link
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
RX packets:544315 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:572619380 (572.6 MB) TX bytes:77544 (77.5 KB)
tcpdump 确认我有数据到达端口。
$ sudo tcpdump -c 4 -l -n -i eth1 'udp and port 61440'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
09:24:51.101619 IP 192.168.0.1.0 > 255.255.255.255.61440: UDP, length 1024
09:24:51.103980 IP 192.168.0.1.0 > 255.255.255.255.61440: UDP, length 1024
09:24:51.106205 IP 192.168.0.1.0 > 255.255.255.255.61440: UDP, length 1024
09:24:51.108584 IP 192.168.0.1.0 > 255.255.255.255.61440: UDP, length 1024
4 packets captured
114 packets received by filter
0 packets dropped by kernel
但从我实际尝试获取这些数据包的任何方法来看,无论我以用户身份还是 root 身份运行它们,都没有得到任何回应。
$ nc -lu 192.168.255.255 61440
$ socat UDP4-RECV:61440,reuseaddr,bind=192.168.255.255 STDOUT,nonblock=1
还尝试编写自己的 C 和 Python。没有。所有这些中都有一些东西在窃取我的数据包。有什么想法吗?Ubuntu 14.04。
编辑以添加:没有防火墙运行。ufw 报告不活动,并且 iptables 将所有 3 个表报告为裸接受。
我还尝试让 netcat 和 socat 绑定总体广播地址 255.255.255.255,或 eth1 本地地址 192.168.0.2。任何尝试均未收到任何数据包。
路由表没有显示任何异常:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.0.1 0.0.0.0 UG 0 0 0 eth0
172.16.0.0 0.0.0.0 255.255.0.0 U 1 0 0 eth0
192.168.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth1
我知道网络接口工作正常。如果我断开此设备并连接其他类型的设备(这是尝试 DHCP) 它成功连接到 dnsmasq 实例并正确分配租约。
有趣的是,当我要求 socat 给我原始 IP 数据包时,结果显示一切正常:
$ sudo socat IP4-RECVFROM:17 STDOUT | hexdump
0000000 0000 00f0 0804 4bb1 6463 6665 6867 6a69
0000010 6c6b 6e6d 606f 6261 6463 6665 6867 6a69
*
0000408
最终编辑:
深入研究这些数据包后,我发现它们的校验和似乎不正确。我认为它们之所以没有通过 UDP 堆栈,就是因为这个原因。我也没有时间找到解决这个问题的优雅方法,因此决定通过打开原始 IP 数据包上的套接字并自行过滤来强制解决这个问题。谢谢大家的帮助。
答案1
下面是我以前使用过的用于测试 UDP 连接的 Python 脚本:
import socket
#---socket creation
connexion = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
#---Bind
try:
connexion.bind(('', 10015))
except socket.error:
print "connexion failed"
connexion.close()
sys.exit()
#---testing
while 1:
data, addr = connexion.recvfrom(1024)
print "messages : ",addr , data
可以在 shell 提示符下输入以下内容来测试发送消息
echo -n "TEST MESSAGE" >/dev/udp/127.0.0.1/10015
从本地主机到本地主机进行测试是第一步故障排除,然后从另一台计算机到有问题的计算机进行测试。
答案2
当我手动设置辅助网络接口且没有为该接口正确设置路由时,我也遇到了类似的问题。
尝试运行:route -n
并查看 eth1 的路由配置是什么。