跳到内容

第 4 卷 / 第 13 章 / 第 2 课

13.2 ICMPv6、NDP 与地址自动配置 ​

IPv6 主机接入链路后,需要确认地址不冲突、寻找路由器、学习前缀和解析邻居的链路层地址。这些能力主要由 ICMPv6 Neighbor Discovery 承担。把 ICMPv6 一刀切地屏蔽,常常等于切断 IPv6 自己的控制回路。

NDP 不只是“IPv6 版 ARP” ​

Neighbor Discovery Protocol 使用五类 ICMPv6 消息:

消息Type主要作用
Router Solicitation, RS133主机请求路由器尽快发送 RA
Router Advertisement, RA134通告默认路由、前缀和其他链路参数
Neighbor Solicitation, NS135地址解析、邻居可达性检测、重复地址检测
Neighbor Advertisement, NA136回应 NS,或主动通告邻居信息变化
Redirect137路由器告诉主机同链路上更合适的下一跳

ICMPv6 还用 Packet Too Big、Destination Unreachable 和 Time Exceeded 分别支持 PMTUD、错误报告与路径探测。安全策略应按功能和作用域精细过滤,而不是简单丢弃所有 ICMPv6。

从单播地址得到 solicited-node multicast ​

地址解析不向所有节点广播。以支持多播的以太网接口为例,节点为分配到该接口的 unicast/anycast 地址加入对应的 solicited-node multicast group:

text
unicast:              2001:db8::1234:5678
low 24 bits:                    34:5678
solicited-node group: ff02::1:ff34:5678
Ethernet multicast:   33:33:ff:34:56:78

地址解析阶段若尚不知道目标链路层地址,发送方把 NS 发往这个多播组;已知邻居的可达性探测则可以发送单播 NS。共享相同低 24 位的节点也可能收到请求,因此接收端仍须检查 NS 中的 Target Address。

python
import ipaddress

def solicited_node(address: str) -> ipaddress.IPv6Address:
    target = int(ipaddress.IPv6Address(address))
    prefix = int(ipaddress.IPv6Address("ff02::1:ff00:0"))
    return ipaddress.IPv6Address(prefix | (target & 0xFFFFFF))

assert str(solicited_node("2001:db8::1234:5678")) == "ff02::1:ff34:5678"

Neighbor Cache 不是永久 ARP 表 ​

NDP 会维护邻居可达性状态。下面列出 Linux 常见的呈现,其中 FAILED 是实现中的失败状态:

状态含义
INCOMPLETE正在解析链路层地址
REACHABLE最近有证据表明邻居可达
STALE条目存在,但可达性证据已过新鲜期
DELAY暂缓主动探测,等待上层提供可达性确认
PROBE正在发送单播 NS 探测
FAILED解析或可达性确认失败

Linux 上查看:

bash
ip -6 neigh show

STALE 不等于故障。它表示需要使用时可能进入后续确认流程;把所有非 REACHABLE 条目当成坏邻居会制造误报。

Duplicate Address Detection ​

地址进入正常使用前,节点通常执行 Duplicate Address Detection(DAD):以 unspecified address :: 为源,对候选地址发送 NS。若收到有效 NA,或发现另一节点也在为同一候选地址发送 DAD NS,就不应启用该地址。DAD NS 不携带源链路层地址选项,不能用未确定的 IPv6 地址声称一条已确认邻居映射。

查看 Linux 地址状态:

bash
ip -6 address show

输出中的 tentative 表示 DAD 尚未完成,dadfailed 表示检测失败。DAD 降低同链路地址冲突风险,却不能提供密码学所有权证明。

RA 提供什么 ​

主机可以发送 RS 请求通告,路由器也会周期发送 RA。RA 及其选项可能包含:

  • Router Lifetime:该路由器可作为默认路由的时间;
  • Prefix Information Option:on-link 前缀和 autonomous address-configuration 标志;
  • MTU;
  • 可达时间与重传计时建议;
  • RDNSS/DNSSL:递归 DNS 服务器和搜索域;
  • Route Information Option:更具体的路由信息。

前缀选项中的 L 与 A 标志含义不同:L 指示前缀可用于 on-link 判断;A 指示可用于 SLAAC。两者不应被当成同一个开关。例如 A=1、L=0 可允许形成地址,却不凭该选项声明整个前缀 on-link;L=0 也不是“该前缀一定 off-link”的反向声明。Router Lifetime 为 0 只撤销默认路由器资格,不等于同时撤销前缀和地址,后者有自己的 lifetime。

RA 的 M/O 标志能提示有状态地址配置或其他 DHCPv6 信息,但客户端行为和操作系统策略并不能仅靠两个标志完整描述。部署时要针对目标客户端验证。

SLAAC 的完整流程 ​

普通主机的典型过程如下。路由与前缀信息都来自 RA,但学习默认路由不必等 SLAAC/DAD 完成;这些步骤是理解路径,不是严格串行协议。

text
1. 形成 link-local address
2. 对候选地址执行 DAD
3. 发送 RS,或等待 RA
4. 从带 A 标志的 prefix information 形成地址
5. 对新地址执行 DAD
6. 独立处理 RA 中的 default router、on-link prefix、MTU 等
7. 按 preferred/valid lifetime 管理地址生命周期

地址超过 preferred lifetime 后会成为 deprecated,现有连接可继续使用,但新连接通常避免选择它作为源地址。超过 valid lifetime 后,地址不再有效。

Interface ID 不应再默认为暴露 MAC 的 EUI-64 ​

早期教材常用 modified EUI-64 从 MAC 生成 64 位 interface identifier。这便于讲位结构,却会让地址跨网络可关联,并暴露链路层标识。

现代主机通常结合两类机制:

  • RFC 7217:为每个前缀生成稳定但不暴露 MAC 的 opaque interface identifier;
  • RFC 8981:生成有生命周期的 temporary address,降低跨时间跟踪能力。

具体默认值由操作系统决定。同一接口可以同时拥有 link-local、稳定地址、temporary address 和 DHCPv6 地址;应用不应假设“一个网卡只有一个 IP”。

SLAAC 与 DHCPv6 不是二选一 ​

能力RA/SLAACDHCPv6
默认路由由 RA 提供DHCPv6 通常不替代 RA 提供默认路由
地址SLAAC 可形成stateful DHCPv6 可租用
DNS 信息RA 的 RDNSS/DNSSL 可提供DHCPv6 也可提供
额外配置RA 选项有限DHCPv6 可承载更多配置
下游前缀委派SLAAC 为接口形成地址DHCPv6-PD 可给路由器委派前缀,供其下游分子网

常见部署包括 SLAAC-only、SLAAC + stateless DHCPv6,以及 RA + stateful DHCPv6。客户端支持情况很重要,例如部分终端平台对 DHCPv6 地址配置的支持策略与桌面系统不同。

观察而不是伪造 NDP ​

学习阶段优先观察操作系统生成的包,不要在真实局域网中用 Scapy 伪造 RA/NA。错误或恶意 RA 可能改变同链路主机的默认路由和 DNS。

bash
# 地址、路由与邻居状态
ip -6 address show
ip -6 route show
ip -6 neigh show

# 只观察当前接口上的 NDP
sudo tcpdump -i eth0 -nn 'icmp6 && ip6[40] >= 133 && ip6[40] <= 137'

固定用 ip6[40] 读取类型只适合“ICMPv6 紧跟基本首部、没有扩展首部”的包。更稳妥的离线分析应让协议解析器遍历 Next Header 链,或使用 Wireshark 的 icmpv6.type display filter。

安全边界 ​

NDP 默认不认证,面临伪造 RA、NA 欺骗和邻居缓存耗尽等同链路攻击。合法 NDP 消息还要满足 Hop Limit=255 等校验;RA 的源地址应是 link-local。这能限制跨路由伪造,却不能认证同链路发送者。SEND 定义了密码学保护机制,但现实部署并不普遍,不能写成“NDP 天生安全”。

常见防护包括:

  • 交换网络中的 RA Guard 与可信端口策略;
  • DHCPv6 Guard、控制平面限速和邻居表容量保护;
  • 无线接入隔离、802.1X 与二层安全控制;
  • 监控异常 RA、前缀、默认路由与邻居状态变化。

RA Guard 自身也需要支持扩展首部感知等正确实现,不能只配置一个开关就宣称攻击面消失。

排障清单 ​

当“有 IPv6 地址但访问失败”时,按证据检查:

  1. 地址是否仍是 tentative 或已 dadfailed;
  2. 是否存在 link-local 地址与有效 default route;
  3. 默认路由对应的 RA lifetime 是否过期;
  4. 目标是 on-link 还是经路由器,neighbor entry 状态如何;
  5. 防火墙是否允许必要 ICMPv6,尤其 Packet Too Big 与 NDP;
  6. 源地址选择是否选中了不合适或已 deprecated 的地址;
  7. 容器/namespace 是否收到 RA,或是否由平台静态配置路由。

本课小结 ​

NDP 把地址解析、路由器发现、DAD 和邻居可达性确认放进 ICMPv6。SLAAC 负责根据通告生成和维护地址,RA 仍是默认路由的核心来源;DHCPv6 可以补充或接管部分配置,但不能简单替代 RA。

下一课讨论这些机制进入真实应用后的问题:DNS、地址选择、Happy Eyeballs、IPv6-only 与 NAT64。

规范入口 ​

  • RFC 4861:Neighbor Discovery for IPv6;
  • RFC 4862:IPv6 Stateless Address Autoconfiguration;
  • RFC 7217:Stable and Opaque Interface Identifiers;
  • RFC 8981:Temporary Address Extensions;
  • RFC 8106:IPv6 Router Advertisement Options for DNS Configuration;
  • RFC 9915:DHCP for IPv6(取代 RFC 8415)。

Built with VitePress | Software Systems Atlas