题 Linux内核不通过组播UDP数据包


最近我设置了一个新的Ubuntu Server 10.04并注意到我的UDP服务器不再能够了 即使加入组播组后,也可以看到发送到接口的任何组播数据。我在其他两台Ubuntu 8.04.4 LTS机器上完成了相同的设置,加入同一个组播组后接收数据没有问题。

以太网卡是Broadcom netXtreme II BCM5709,使用的驱动程序是:

b $ ethtool -i eth1
driver: bnx2
version: 2.0.2
firmware-version: 5.0.11 NCSI 2.0.5
bus-info: 0000:01:00.1

我正在使用smcroute来管理我的多播注册。

b$ smcroute -d
b$ smcroute -j eth1 233.37.54.71

加入组后,ip maddr显示新添加的注册。

b$ ip maddr

    1:  lo
        inet  224.0.0.1
        inet6 ff02::1
    2:  eth0
        link  33:33:ff:40:c6:ad
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6ad
        inet6 ff02::1
    3:  eth1
        link  01:00:5e:25:36:47
        link  01:00:5e:25:36:3e
        link  01:00:5e:25:36:3d
        link  33:33:ff:40:c6:af
        link  01:00:5e:00:00:01
        link  33:33:00:00:00:01
        inet  233.37.54.71 <------- McastGroup.
        inet  224.0.0.1
        inet6 ff02::1:ff40:c6af
        inet6 ff02::1

到目前为止一切顺利,我可以看到我正在接收该多播组的数据。

b$ sudo tcpdump -i eth1 -s 65534 host 233.37.54.71
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65534 bytes
09:30:09.924337 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:09.947547 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
09:30:10.108378 IP 192.164.1.120.58866 > 233.37.54.71.15574: UDP, length 268
09:30:10.196841 IP 192.164.1.120.58848 > 233.37.54.71.15572: UDP, length 212
...

我还可以确认接口正在接收mcast数据包。

b $ ethtool -S eth1 | grep mcast_pack
rx_mcast_packets: 103998
tx_mcast_packets: 33

现在这是问题所在。当我尝试使用简单的ruby UDP服务器捕获流量时,我收到零数据!这是一个简单的服务器,读取端口15572上发送的数据并打印 前两个字符。这适用于两个8.04.4 Ubuntu服务器,但不适用于10.04服务器。

require 'socket'
s = UDPSocket.new
s.bind("", 15572)
5.times do
  text, sender = s.recvfrom(2)
  puts text
end

如果我将以ruby制作的UDP数据包发送到localhost,服务器会收到它并打印出前两个字符。所以我知道上面的服务器工作正常。

irb(main):001:0> require 'socket'
=> true
irb(main):002:0> s = UDPSocket.new
=> #<UDPSocket:0x7f3ccd6615f0>
irb(main):003:0> s.send("I2 XXX", 0, 'localhost', 15572)

当我查看协议统计信息时,我发现InMcastPkts没有增加。在上 在同一网络上的其他8.04服务器在10秒内收到了几千个数据包。

b $ netstat -sgu ; sleep 10 ; netstat -sgu
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4654 <--------- Same as below
    OutMcastPkts: 3426
    InBcastPkts: 9854
    InOctets: -1691733021
    OutOctets: 51187936
    InMcastOctets: 145207
    OutMcastOctets: 109680
    InBcastOctets: 1246341
IcmpMsg:
    InType3: 11
    OutType3: 11
Udp:
    446 packets received
    4 packets to unknown port received.
    0 packet receive errors
    461 packets sent
UdpLite:
IpExt:
    InMcastPkts: 4656  <-------------- Same as above
    OutMcastPkts: 3427
    InBcastPkts: 9854
    InOctets: -1690886265
    OutOctets: 51188788
    InMcastOctets: 145267
    OutMcastOctets: 109712
    InBcastOctets: 1246341

如果我尝试强制接口进入promisc模式,则没有任何变化。

此时我被困住了。我已经确认内核配置已启用多播。也许我应该检查其他配置选项?

b $ grep CONFIG_IP_MULTICAST /boot/config-2.6.32-23-server
CONFIG_IP_MULTICAST=y

关于从哪里去的任何想法?


32
2017-07-23 01:00




去搞清楚。我去输入一个新问题,相关的算法很高兴地告诉我这个问题存在,但它没有有意义的答案。嘘:(。 - VxJasonxV
我不确定我将如何奖励赏金。一位同事发现了这个问题,我想知道为什么会发生这种情况。我非常愿意接受如何奖励赏金的建议。 - VxJasonxV
你还在吗?我有一些问题要问你。 - VxJasonxV
我也有这个问题。亲爱的buecking,你解决了吗?
对于遇到此问题的其他人 - 请阅读此问题的所有答案,因为需要修复2-3个操作系统设置。我们通过改变解决了这个问题 rp_filter 和 /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts 然后它开始工作了。 - Sam Goldberg


答案:


在我们的实例中,我们的问题是通过sysctl参数解决的,一个与Maciej不同的参数。

请注意,我不代表OP(buecking),由于问题与基本细节相关(用户区中没有多播流量),我在这篇文章中提到了。

我们有一个应用程序,它从一个(通常)直接连接到接收服务器上的接口的设备读取发送到四个多播地址的数据和每个多播地址的唯一端口。

我们试图在客户网站上部署这个软件,当它神秘地失败时,没有任何已知原因。试图调试这个软件导致检查每个系统调用,最终他们都告诉我们同样的事情:

我们的软件要求提供数据,操作系统从不提供任何数据。

多播数据包计数器递增,tcpdump显示流量到达盒子/特定接口,但我们无法对它做任何事情。 SELinux被禁用,iptables正在运行,但在任何表中都没有规则。

难倒,我们是。

在随机浏览中,我们开始考虑sysctl处理的内核参数,但没有任何记录的功能特别相关,或者如果它们与多播流量有关,则它们已启用。哦,ifconfig确实在功能行中列出了“MULTICAST”(向上,广播,运行,多播)。出于好奇,我们看了看 /etc/sysctl.conf。 “瞧,这个顾客的基本形象在底部添加了几条额外的线条。

在我们的例子中,客户已经设定 net.ipv4.all.rp_filter = 1。 rp_filter是路径路径过滤器,它(据我所知)拒绝所有可能无法到达此框的流量。网络子网跳跃,以为源IP被欺骗。

好吧,这台服务器位于192.168.1 / 24子网上,设备的组播流量源IP地址位于10. *网络中。因此,过滤器阻止服务器对流量做任何有意义的事情。

经过客户批准的一些调整; net.ipv4.eth0.rp_filter = 1 和 net.ipv4.eth1.rp_filter = 0 我们快乐地跑着。


31
2017-12-27 22:50



这有效!该 rp_filter 我们的10 Gb网络接口正在转储我们所有的UDP组播数据包。关闭过滤器让一切都流过。 - chrisaycock
我们在通过Ubuntu接收器上的tun设备上通过AMT多播设置流时遇到问题,我们可以看到数据包通过tcpdump传送到设备,但应用程序只是不想流。这篇文章救了我们! - software engineer


TL / DR 还要确保您的多播不是来自vlan。 tcpdump -e 将有助于确定他们是否这样做。

平心而论,有人应该构建一个页面,其中包含可以阻止多播到达用户空间的事项清单。几天来我一直在努力解决这个问题,当然我在网络上找不到任何帮助。

我不仅可以看到数据包中的数据包 tcpdump,我可以在其他生产者身上接收其他组播数据包。我最终用于测试是否可以接收多播的命令是:

$ GRP=224.x.x.x # set me to the group
$ PORT=yyyy # set me to the receiving port
$ IFACE=mmmm # set me to the name or IP address of the interface
$ strace -f socat -  UDP4-DATAGRAM:$GRP:$PORT,ip-add-membership=$GRP:$IFACE,bind=0.0.0.0:$PORT,multicast-loop=0

的原因 strace 这是我实际上无法做到的 socat 将数据包打印到stdout,但是在 strace 输出你可以清楚地看到 socat 从绑定的套接字接收实际数据(否则在初始几次之后它将静音 select 呼叫)

  • rp_filter sysctl - 不适用,系统在同一个IP网络上(我将它们设置为 0 一切都一样,似乎 1 现在是默认设置,至少对于Ubuntu而言。
  • 防火墙/等等 - 接收系统是防火墙免费的(我不认为如果它们被防火墙,数据包将显示在tcpdump中,但我想如果防火墙很有趣可能)
  • IP /多播路由和多个接口 - 我明确地在正确的接口上加入了组
  • 古怪的网络硬件 - 这是我的最后一招,但将一些笔记本电脑更换为英特尔NUC并没有帮助。这是关于我开始咀嚼肘部并将其发布到SE的地方。
  • 我的问题是由生成这些组播数据包的专用硬件使用VLAN。要查看这是否是您的问题,请务必加入 -e 国旗 tcpdump,并检查vlan标签。在userland能够获取这些数据包之前,需要将接口配置到正确的vlan中。实际上我的赠品是多播生产者不会ping,但甚至不会进入ARP缓存,尽管我可以清楚地看到ARP回复。

让它与VLAN一起运行 这个链接 可能有助于配置组播路由。 (可悲的是我是新手,所以声望不允许我添加答案。因此这个编辑。)

这是我做的(如果需要,使用sudo):

ip link add link eth0 name eth0_100 type vlan id 100
ip addr add 192.168.100.2/24 brd 192.168.100.255 dev eth0_100
ip link set dev eth0_100 up
ip maddr add 01:00:5e:01:01:01 dev eth0_100
route -n add -net 224.0.0.0 netmask 240.0.0.0 dev eth0_100

这样,如果为vlan id为100的vlan流量创建了一个额外的接口.vlan ip可能是不必要的。然后为新接口配置组播地址(01:00:5e:01:01:01是239.1.1.1的链路层地址),所有传入的组播流量都绑定到eth0_100。我也在上面的答案中做了所有可能的步骤(检查iptables,rp_filter等)。


3
2017-07-08 08:10



@Gero:添加组播路由设置 传出 多播,而不是传入多播。您不应该直接将多播IP地址绑定到接口,除非您正在做一些时髦的事情,它通常是应用程序的工作。 - Pawel Veselov


您可能想尝试查看以下设置:

PROC

echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts

sysctl.conf的

sed -i -e 's|^net.ipv4.icmp_echo_ignore_broadcasts =.*|net.ipv4.icmp_echo_ignore_broadcasts = 0|g' /etc/sysctl.conf

这些已用于在RHEL中启用多播。

您可能希望确保防火墙允许多变量流量;再次使用RHEL我启用了以下内容:

# allow anything in on multicast addresses
-A INPUT -s 224.0.0.0/4 -j ACCEPT
-A INPUT -p igmp -d 224.0.0.0/4 -j ACCEPT
# needed for multicast ping responses
-A INPUT -p icmp --icmp-type 0 -j ACCEPT

2
2017-12-21 00:27



“广播”选项也适用于“多播”吗? - Raedwald


您使用的是托管交换机吗?有些人可以选择防止“广播风暴”或其他多播问题,这会导致他们阻止某些类型的数据包。我建议你看看你的交换机文档。


0
2017-12-21 02:54





s.bind("", 15572)

肯定 ””?为什么不使用多播IP地址绑定?


0
2018-01-31 18:19



空主机地址通常表示“所有接口”。 - VxJasonxV