为什么需要 Solicited-Node 组播
IPv6 取消了广播,但邻居发现仍然要问“这个地址是谁的”。如果向全链路所有节点发问,规模一大就会变成噪声。解决办法是给每个单播地址算出一个专属组播组:取地址低 24 位拼到 ff02::1:ff00:0/104 之后,节点只加入与自己地址相关的组,于是单播查询只会打扰极少数节点。
基本信息
| 组播前缀 | ff02::1:ff00:0/104,固定前 13 个字节 |
|---|---|
| 构造方式 | ff02::1:ff + 目标单播地址的低 24 位 |
| 组播 MAC | 33:33:ff 加上地址低 24 位,与 IP 层组播一一对应 |
| 用途一 | 邻居请求 NS 与邻居通告 NA 的询问通道 |
| 用途二 | 重复地址检测 DAD 探测地址是否已被占用 |
| 加入方式 | 节点在配置单播地址时自动加入对应组,无需手工操作 |
构造与验证
构造与验证
python - <<'PY'
import ipaddress as ipa
a = int(ipa.IPv6Address('2001:db8::1'))
g = (0xff02 << 112) | (0x0001 << 32) | (0xff00 << 16) | (a & 0xffffff)
print(ipa.IPv6Address(g)) # ff02::1:ff00:1
PY
# 抓包看 NS/NA:目标应是 solicited-node 组播
# tcpdump -ni eth0 'icmp6 and ip6[40] == 135'地址对应关系
| 目标单播地址 | solicited-node 组播 |
|---|---|
| 2001:db8::1 | ff02::1:ff00:1 |
| 2001:db8::abcd | ff02::1:ff00:abcd |
| fe80::021a:2bff:fe3c:4d5e | ff02::1:ff3c:4d5e |
| 2001:db8:1:1::ff:fe00:1 | ff02::1:ff00:1 |
典型使用场景
- 排查邻居不通:先确认网卡是否加入了目标地址对应的 solicited-node 组,没有加入就收不到 NS
- 理解 DAD:新地址启用前向自己的 solicited-node 组发探测,若有人应答说明地址已被占用
- 抓包分析时按组播前缀过滤,能快速把 NDP 交互从其他流量里摘出来
- 编写防火墙策略时需放行 ff02::1:ff00:0/104,禁掉它等于禁掉邻居发现,整段 IPv6 会莫名其妙不通
- 核对地址冲突告警:同一组播组被两个节点加入且地址相同,就是典型地址冲突
低 24 位相同不代表地址相同:不同地址可能落到同一个 solicited-node 组,收到别人的 NS 属于正常现象,节点会用完整地址比对后决定是否应答。
该前缀长度是 104 位而不是 128 位:前 13 字节固定,只有最后 3 字节随目标地址变化,因此一个链路上最多有 2^24 个这样的组,实际使用中不会成为瓶颈。