‘为什么收不到广播包’,听到的答案都是被路由丢弃了,其实这只是一种情况,而这种情况是比较好理解,一般都会规避,往往实际情况不是这样,比如:

  • 同一个路由器下,两台设备的广播包到不了
  • 两台设备网线直连,广播包到不了

本文将为大家一一介绍其中的缘由.

1. 概念

广播包,即发给所有本地主机的包,分为:

  • 受限广播包(255.255.255.255)- 不被转发
  • 子网广播包(netid.1)- 往所有子网广播
  • 主机广播包(netid.subnetid.1)- 往指定子网广播

这里有一点需要强调:广播包是基于 UDP ,TCP 是没有广播包的说法

2. 用途

广播包的用途自然就不用说,ARP、DHCP等一些非常重要的协议都是基于广播包。当然也不能滥用,否则会影响网络及主机性能,就好比你天天都在小区大喊,谁也受不了。

3. 阻碍因子

广播包既然可以发给所有主机,按理说所有主机都需要处理它,那有哪些因素会阻碍『收广播包』?

3.1. 路由器

为了保证网络的干净,路由器一般不转发广播包,于是这里大家常常误解,以为只要广播包一接入路由器,都有可能被路由器丢弃;于是往往有个答案『你的广播包被路由器丢弃』,其实只有经过 WAN口的广播包才会丢弃。因此如果是2个 LAN 口间的广播包是不会丢弃的,即使两个主机 IP 不一样。

比如:192.168.1.88与192.168.2.88两台主机连到192.168.2.1路由上照样可以正常收发广播包。

3.2. 多网卡(发送方)

默认是不会往所有网卡发送广播包,广播包跟其他数据包一样,也是通过本地路由表来决策该往哪个网卡发送,比如有一台双网卡,分别是61和161网段,有如下路由表:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
...
0.0.0.0         192.168.161.1   0.0.0.0         UG    0      0        0 em1
0.0.0.0         192.168.61.1    0.0.0.0         UG    0      0        0 em2

广播包是往 em1发送,而不会往 em0发送(优先匹配前面规则),当然你也可以指定往哪个网卡发送

srcaddr.sin_addr.s_addr=inet_addr("192.168.61.223");

实测 window 系统,也是如此.

因此,如果是双网卡,请确保是否发对网卡。

3.3. 系统内核过滤(接收方)

还有一种情况,比如 linux 系统增加了一种 Reverse Path Filter,即会对来源 IP 合法性进行判断,即是否本该从该网卡发过来,若不符合,则丢弃。简单地判断就是验证是否可以往相应网口向该 IP 发送数据。

比如你的路由表如下:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.161.0   192.168.161.1   255.255.255.0   UG    0      0        0 em1
192.168.161.0   0.0.0.0         255.255.255.0   U     0      0        0 em1
192.168.61.0    0.0.0.0         255.255.255.0   U     0      0        0 em2

则以下情况都是不合法来源

  • 在网口 em1,收到了192.168.61.xx的数据包(应该在 em2上收到)
  • 网卡 em1或 em2收到10.10.xx.xx的数据包

该机制是为防止恶意攻击,具体各位可以去了解下。那么是否可以关闭该特性,肯定是可以.

vim /etc/sysctl.conf

net.ipv4.conf.default.rp_filter = 0

即可,当然也可以增加路由表来解决。

该特性只在 linux 上,window系统就不得而知了。

3.4 VLAN

为了防止大量广播消耗网络资源,有些大型局域网会使用VLAN技术,将交换机下的某些口组成一个单独的 LAN,这样广播包只会在该 LAN,而不会发到其他端口上.

4. 总结

当你遇到广播包收不到问题,可以基于如下思路排查:

  • 确认物理连接是否属于统一网段(注意是物理连接,而不是说IP)
  • 确认发送发是否发对网卡
  • 如果是接收方是 linux,确认系统是否开启 rpfilter