3. IPv6基础协议与双栈主机配置
IPv6 主机要真正“上网”,第一步不是配路由协议,而是把地址、前缀、网关和 DNS 这些基础参数拿到手。与 IPv4 依赖 ARP、手工地址和 DHCP 不同,IPv6 把地址解析、邻居发现、路由器发现、地址自动配置整合进了一套 ICMPv6 报文体系,这就是 NDP(Neighbor Discovery Protocol,邻居发现协议)。理解 NDP、SLAAC 与 DHCPv6 三者的分工,是双栈主机配置的核心。
一、NDP:IPv6 的“控制面底座”
NDP 定义在 RFC 4861,运行在 ICMPv6 之上,使用五类关键报文:
- RS(Router Solicitation,类型 133):主机启动或链路变化时,向
ff02::2(所有路由器)组播,请求路由器立即通告前缀信息。 - RA(Router Advertisement,类型 134):路由器周期性或响应 RS 时,向
ff02::1(所有节点)组播,携带前缀、前缀长度、默认网关、M/O 标志、跳数限制、MTU 等。 - NS(Neighbor Solicitation,类型 135):用于地址解析(替代 ARP)和重复地址检测(DAD),目的地址为被请求节点的 solicited-node 组播地址
ff02::1:ffXX:XXXX。 - NA(Neighbor Advertisement,类型 136):对 NS 的应答,携带目标链路层地址和 R/S/O 标志。
- Redirect(类型 137):路由器告知主机存在更优的下一跳。
其中 RA 报文中的两个标志位决定了主机如何获取地址:M 位(Managed Address Configuration)置 1 表示地址通过 DHCPv6 获取;O 位(Other Configuration)置 1 表示 DNS、域名等其他参数通过 DHCPv6 获取。这两个标志的组合,直接决定了 SLAAC 与 DHCPv6 的协作方式。
二、SLAAC:无状态地址自动配置
SLAAC(Stateless Address Autoconfiguration,RFC 4862)让主机无需服务器即可生成全球单播地址。流程分三步:
- 生成链路本地地址:接口启用 IPv6 后,主机用
fe80::/64前缀加上接口标识(EUI-64 或稳定隐私地址 RFC 7217)生成链路本地地址。 - DAD 重复地址检测:主机向该地址对应的 solicited-node 组播地址发送 NS,若在约 1 秒内未收到 NA,则认为地址唯一,可以启用。
- 接收 RA 生成全球地址:主机收到 RA 后,取 RA 中的前缀(如
2001:db8:1::/64)与接口标识拼接,再次 DAD 后启用。默认网关即 RA 的源地址(链路本地地址)。
以 EUI-64 为例,MAC 地址 00:1A:2B:3C:4D:5E 先插入 FF:FE 变为 00:1A:2B:FF:FE:3C:4D:5E,再将第一字节的 U/L 位取反(00 → 02),得到接口标识 021A:2BFF:FE3C:4D5E,最终地址为 2001:db8:1::021a:2bff:fe3c:4d5e/64。实际工程中更推荐启用稳定隐私地址,避免暴露 MAC 信息。
三、DHCPv6:有状态配置
当 RA 中 M 位置 1 时,主机通过 DHCPv6 获取地址。DHCPv6 使用 UDP:客户端 546,服务器 547,通过组播 ff02::1:2 发现服务器。典型四步交互为 Solicit → Advertise → Request → Reply;若客户端已有服务器信息,可简化为 Request → Reply 两步。DHCPv6 还支持前缀委派(PD),用于给下游路由器分配 /56 或 /60 前缀。
需要区分两种模式:有状态 DHCPv6 分配地址和参数;无状态 DHCPv6 只分配 DNS、域名等参数,地址仍由 SLAAC 生成。工程中常见组合是“SLAAC 地址 + 无状态 DHCPv6 下发 DNS”,即 M=0、O=1。
四、双栈主机配置实战
下面以 Linux 主机为例,演示自动配置与手工配置两种方式。假设路由器接口为 2001:db8:1::1/64,DNS 为 2001:db8:1::53。
自动配置(SLAAC + 无状态 DHCPv6):
# 启用 IPv6 并接受 RA
sysctl -w net.ipv6.conf.eth0.accept_ra=1
sysctl -w net.ipv6.conf.eth0.autoconf=1
# 查看自动生成的地址
ip -6 addr show dev eth0
# inet6 2001:db8:1::021a:2bff:fe3c:4d5e/64 scope global dynamic
# inet6 fe80::21a:2bff:fe3c:4d5e/64 scope link
# 查看默认路由(来自 RA)
ip -6 route show default
# default via fe80::1 dev eth0 proto ra metric 1024
# 若 O=1,用 dhclient 获取 DNS
dhclient -6 -S eth0
cat /etc/resolv.conf
# nameserver 2001:db8:1::53
手工配置(静态地址):
ip -6 addr add 2001:db8:1::100/64 dev eth0
ip -6 route add default via 2001:db8:1::1 dev eth0
echo "nameserver 2001:db8:1::53" >> /etc/resolv.conf
# 验证连通性
ping6 -c 3 2001:db8:1::1
ping6 -c 3 2001:db8:1::53
配置完成后,用 ip -6 neigh show 查看邻居缓存,用 ping6 验证网关和 DNS 可达性。若地址显示 tentative,说明 DAD 未完成或检测到冲突;若 dadfailed,则地址重复,需要更换接口标识或排查是否有其他主机占用。
sysctl net.ipv6.conf.eth0.disable_ipv6 应为 0);② 是否收到 RA(tcpdump -i eth0 icmp6 and ip6[40]==134);③ RA 的 M/O 标志是否符合预期;④ DHCPv6 服务器是否可达(ff02::1:2 组播是否被阻断);⑤ 防火墙是否放行 ICMPv6 类型 133-137 和 UDP 546/547。
总结来看,NDP 提供邻居发现和路由器发现能力,SLAAC 负责无状态地址生成,DHCPv6 负责有状态地址或参数下发。双栈主机配置时,先确认 RA 的 M/O 标志,再选择自动或手工方式,最后通过 ip -6 addr、ip -6 route 和 ping6 验证地址、网关与 DNS 是否全部就绪,才算完成一个可用的 IPv6 主机接入。