广播数据包不通过 Linux veth 隧道传播
Broadcast packets do not propagate through a Linux veth tunnel
我正在开发一个依赖子网广播的网络应用程序。我决定使用虚拟以太网接口 (veth
) 在我的本地计算机上设置一个用于测试和开发目的的受控环境。设置很简单:
ip link add veth0 type veth peer name veth1
ifconfig veth0 192.168.241.1 netmask 255.255.255.0 up
ifconfig veth1 192.168.241.2 netmask 255.255.255.0 up
ip link
确认接口已启动并且广播标志已设置:
8: veth1@veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 46:29:76:81:27:af brd ff:ff:ff:ff:ff:ff
9: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 3a:ad:f9:cb:28:a8 brd ff:ff:ff:ff:ff:ff
Python REPL 中的一个简单测试表明接口可以正常工作。这是接收器:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.bind(('192.168.241.2', 48469))
>>> s.recvfrom(1000)
(b'abc', ('192.168.241.1', 45560))
这是发件人:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.connect(('192.168.241.2', 48469))
>>> s.send(b'abc')
3
适用于单播数据包。然而,广播数据包似乎被悄无声息地丢弃了。以下发件人端 REPL 可用于重现该问题:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
>>> s.connect(('192.168.241.255', 48469))
>>> s.send(b'abc')
3
>>> s # For diagnostic purposes
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('192.168.241.1', 48065), raddr=('192.168.241.255', 48469)>
套接字配置成功,但发出的广播数据包从未到达隧道的另一端。这不是我预期的行为,特别是考虑到接口标志表明接口支持广播。我正在 运行 这些测试 Linux Mint 18 与股票内核。我错过了什么?
隧道没问题
问题是 Linux 丢弃所有传入的广播流量,除非套接字绑定到 INADDR_ANY
。如果 receiver-side REPL 更新如下,一切正常:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.bind(('', 48469)) # Bind to INADDR_ANY to accept broadcast packets
>>> s.recvfrom(1000)
(b'abc', ('192.168.241.1', 45560))
在 Windows 上,行为有所不同(与隧道无关):将套接字绑定到特定接口不会拒绝广播流量。
Man 7 IP 表示应该设置 SO_BROADCAST
以接收广播数据报;但是,我在接收方观察到的行为似乎与描述不符:
Datagrams to broadcast addresses can be sent or received only when the SO_BROADCAST socket flag is set.
广播数据报总是可以用INADDR_ANY
接收;如果套接字绑定到特定接口,则从不。无论s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
.
如何,这两个陈述都成立
我正在开发一个依赖子网广播的网络应用程序。我决定使用虚拟以太网接口 (veth
) 在我的本地计算机上设置一个用于测试和开发目的的受控环境。设置很简单:
ip link add veth0 type veth peer name veth1
ifconfig veth0 192.168.241.1 netmask 255.255.255.0 up
ifconfig veth1 192.168.241.2 netmask 255.255.255.0 up
ip link
确认接口已启动并且广播标志已设置:
8: veth1@veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 46:29:76:81:27:af brd ff:ff:ff:ff:ff:ff
9: veth0@veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 3a:ad:f9:cb:28:a8 brd ff:ff:ff:ff:ff:ff
Python REPL 中的一个简单测试表明接口可以正常工作。这是接收器:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.bind(('192.168.241.2', 48469))
>>> s.recvfrom(1000)
(b'abc', ('192.168.241.1', 45560))
这是发件人:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.connect(('192.168.241.2', 48469))
>>> s.send(b'abc')
3
适用于单播数据包。然而,广播数据包似乎被悄无声息地丢弃了。以下发件人端 REPL 可用于重现该问题:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
>>> s.connect(('192.168.241.255', 48469))
>>> s.send(b'abc')
3
>>> s # For diagnostic purposes
<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_DGRAM, proto=0, laddr=('192.168.241.1', 48065), raddr=('192.168.241.255', 48469)>
套接字配置成功,但发出的广播数据包从未到达隧道的另一端。这不是我预期的行为,特别是考虑到接口标志表明接口支持广播。我正在 运行 这些测试 Linux Mint 18 与股票内核。我错过了什么?
隧道没问题
问题是 Linux 丢弃所有传入的广播流量,除非套接字绑定到 INADDR_ANY
。如果 receiver-side REPL 更新如下,一切正常:
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
>>> s.bind(('', 48469)) # Bind to INADDR_ANY to accept broadcast packets
>>> s.recvfrom(1000)
(b'abc', ('192.168.241.1', 45560))
在 Windows 上,行为有所不同(与隧道无关):将套接字绑定到特定接口不会拒绝广播流量。
Man 7 IP 表示应该设置 SO_BROADCAST
以接收广播数据报;但是,我在接收方观察到的行为似乎与描述不符:
Datagrams to broadcast addresses can be sent or received only when the SO_BROADCAST socket flag is set.
广播数据报总是可以用INADDR_ANY
接收;如果套接字绑定到特定接口,则从不。无论s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
.