我有一个带有多个接口的Linux系统(内核3.10.62 - 是的,我知道它很旧):
- eth0——192.168.1.110/24
- eth1——10.149.1.4/24
- eth2——10.10.0.99/16
我正在尝试发送到 eth2 接口上的多播地址 (235.0.0.37),并使用该 eth2 接口的源 IP 地址。
我有如下路由表设置:
# ip route
default via 10.10.0.99 dev eth2 scope link
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.110
10.149.1.0/24 dev eth1 proto kernel scope link src 10.149.1.4
10.10.0.0/16 dev eth2 proto kernel scope link src 10.10.0.99
224.0.0.0/4 dev eth0 scope link
235.0.0.0/24 dev eth2 scope link
我有一个测试 python(2.7.3)应用程序(真正的应用程序是 Java 语言的,但是这清楚地显示了问题,并且 Java 应用程序的行为也相同):
# cat test_mc.py
#!/usr/bin/env python
import socket
import struct
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind( ( "10.10.0.99", 0 ) )
print "bound to:", sock.getsockname()
sock.setsockopt( socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton("10.10.0.99") )
ifip = sock.getsockopt( socket.IPPROTO_IP, socket.IP_MULTICAST_IF )
print socket.inet_ntoa( struct.pack('<L', ifip) )
sock.sendto(b'hello world', ('235.0.0.37', 9006))
# python test_mc.py
bound to: ('10.10.0.99', 49908)
10.10.0.99
#
请注意,这会将套接字绑定到 eth2 地址并明确设置 IP_MULTICAST_IF。
我期望此消息从 eth2 接口 (10.10.0.99) 发出。它确实这样做了,但数据包的源地址是 eth1 接口 (10.149.1.4)。我已经使用本地主机上的 tcpdump 和外部 PC(连接到 eth2 网络)上的 wireshark 确认了这一点。
# tcpdump -X -n -i eth2 udp port 9006
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth2, link-type EN10MB (Ethernet), capture size 65535 bytes
17:58:10.915720 IP 10.149.1.4.49908 > 235.0.0.37.9006: UDP, length 11
0x0000: 4500 0027 aa66 4000 0111 d8a1 0a95 0104 E..'.f@.........
0x0010: eb00 0025 c2f4 232e 0013 f6e2 6865 6c6c ...%..#.....hell
0x0020: 6f20 776f 726c 64 o.world
有没有办法设置套接字,以便发往该多播地址的数据包看起来来自 eth2 IP(10.10.0.99)?我以为 IP_MULTICAST_IF 会做到这一点。它甚至没有选择默认多播路由(eth0)或默认路由的源地址。有没有办法做到这一点?