同一个包发给“一个人”“网段所有人”“一组人”,在网线上有什么不同?目的 MAC 怎么由 IP 地址决定?谁会收到?广播 ping 为什么会放大流量?这篇用抓包和一组本机套接字实验一一验证。
目的 以太网目的 MAC MAC 类型 IP 目的地址 单播(发给默认网关) 70:85:6c:xx:xx:xx 单播 <网关> 帧长 50 子网定向广播(网段最后一个地址) ff:ff:ff:ff:ff:ff 广播 <网段广播> 帧长 50 受限广播 255.255.255.255 ff:ff:ff:ff:ff:ff 广播 255.255.255.255 帧长 50 组播 239.1.2.3 01:00:5e:xx:xx:xx 组播 239.1.2.3 帧长 50 组播 239.1.2.3 的 MAC = 01:00:5e + IP 的低 23 位 = 01:00:5e:01:02:03:239.1.2.3 低 23 位是 0x010203 → 01:02:03;注意高位被丢掉,所以 239.129.2.3 也映射到同一个 MAC
目的 IP 决定目的 MAC:单播用下一跳的 MAC,广播用 ff:ff:ff:ff:ff:ff,组播用 01:00:5e 加 IP 低 23 位。
发 3 个数据报到 单播 127.0.0.1:接收者 A、B 各收到 [3, 0] 个 发 3 个数据报到 受限广播 255.255.255.255:接收者 A、B 各收到 [3, 3] 个 发 3 个数据报到 组播 224.9.9.9(两个都加入了组):接收者 A、B 各收到 [3, 3] 个 单播只会交给其中一个套接字;广播和组播会交给所有符合条件的套接字——这是它们和单播的本质区别
单播只交给一个套接字,广播交给所有套接字,组播交给所有加入了该组的套接字。
sysctl net.inet.icmp.bmcastecho = 1(本机是 1 = 会回应目的地址为广播 / 组播的 ICMP echo;0 = 不回应) ping 输出末几行: --- <网段广播> ping statistics --- | 2 packets transmitted, 2 packets received, +50 duplicates, 0.0% packet loss | round-trip min/avg/max/stddev = 0.165/127.667/1103.209/150.887 ms 抓到发往网段广播地址的 ICMP 请求帧 2 个,其中目的 MAC 是 ff:ff:ff:ff:ff:ff 的 2 个——网络层的“广播地址”对应链路层的“广播 MAC” 路由器不转发子网定向广播 / 受限广播:受限广播 255.255.255.255 的 TTL 虽然是 64,但它只在本链路上有效,第一台路由器就会丢掉它(路由器的行为本机无法实验,这是规范 / 经验,不是实测)
目的地址是子网广播地址的 ping 会让网段里所有愿意回应的主机都回一个应答,2 个请求得到了 52 个应答,这是放大攻击的原理。
单播:6406 个帧,共 4849737 字节(78.9% 的帧) 广播:789 个帧,共 417779 字节(9.7% 的帧) 组播:926 个帧,共 512821 字节(11.4% 的帧) 广播 + 组播 1715 个帧 ≈ 每秒 57.2 个——网段里每台主机的网卡都要收下并交给 CPU 看一眼;这就是为什么广播域不能无限大
每个广播和组播帧都会被网段里每台主机的网卡收下,所以广播域越大,无关流量越多。