IPv6 地址自动获取(自动配置):从概念、报文流程、关键字段,到抓包/排错
- 先把结论放前面:IPv6“自动获取地址”到底有哪些路子?
IPv6 客户端(主机)能“自动拿到地址”,主要靠这三套机制(经常组合使用):
- SLAAC(Stateless Address Autoconfiguration,无状态自动配置)
通过路由器发的 RA(Router Advertisement),主机自己拼地址(前缀 + 接口标识 IID),并做 DAD 冲突检测。 DHCPv6(有状态/无状态)
- 有状态:服务器直接分配地址(像 IPv4 DHCP 一样)。
- 无状态:地址仍由 SLAAC 生成,但 DHCPv6 只下发 DNS、域名等“其他参数”。
- Link-Local 地址(链路本地地址)
主机会立刻生成 fe80::/64,不需要路由器/服务器。它是后续与路由器交互(比如收 RA)的基础。
判断你网络里主机最终“怎么拿地址”,关键看 RA 里的两个标志位:
- M=1(Managed):用 DHCPv6 有状态拿地址
- O=1(Other):用 DHCPv6 无状态拿 DNS 等“其他配置”
- A=1(Prefix Information Option 的 Autonomous flag):允许 SLAAC 用该前缀自动拼地址
- IPv6 自动配置的核心角色与报文
1.1 主机上电后,第一件事:生成 Link-Local
它会基于网卡生成一个 fe80::xxxx 地址(IID 可能来自 EUI-64 / 随机 / 稳定隐私)。
Linux 查看:
ip -6 addr show dev eth0
1.2 然后:用 ICMPv6 跟网络“打招呼”
涉及 ICMPv6 / NDP(Neighbor Discovery Protocol)的一些关键报文类型:
- RS(Router Solicitation,类型 133)
- RA(Router Advertisement,类型 134)
- NS/NA(Neighbor Solicitation/Advertisement,类型 135/136)
- Redirect(类型 137)
抓包:
sudo tcpdump -i eth0 -n -vv icmp6
- SLAAC(无状态自动配置)详细流程
2.1 主机发送 RS
目的地址:ff02::2(All Routers)
2.2 路由器回复 RA
包含:
- 默认路由
- 前缀(Prefix Information Option)
- M/O 标志
- RDNSS(可选)
2.3 主机拼全球单播地址
IPv6地址 = 前缀(64bit) + IID(64bit)
IID 可能来自:
- EUI-64
- 临时隐私地址(RFC 4941)
- 稳定隐私地址(RFC 7217)
Linux 查看隐私策略:
cat /proc/sys/net/ipv6/conf/all/use_tempaddr
2.4 DAD(重复地址检测)
使用 NS 报文,若收到 NA 表示冲突。
- DHCPv6:有状态 vs 无状态
RA 决定方式:
- M=1:DHCPv6 有状态
- M=0, O=1:DHCPv6 无状态
- M=0, O=0:纯 SLAAC
抓包 DHCPv6:
sudo tcpdump -i eth0 -n -vv udp port 546 or udp port 547
- RA 里常见字段
查看 RA:
rdisc6 eth0
字段:
- Router Lifetime
- MTU Option
- Prefix Information Option(PIO)
- RDNSS
- DNSSL
- 不同系统表现
Linux:
ip -6 route
ip -6 addr show
resolvectl status
Windows:
ipconfig /all
netsh interface ipv6 show addresses
netsh interface ipv6 show route
- 常见排错点
- ICMPv6 被拦
- A=0
- 前缀不是 /64
- 没有默认路由
- DNS 缺失
- 实验环境示例
7.1 路由器开启转发
sysctl -w net.ipv6.conf.all.forwarding=1
7.2 radvd 配置
/etc/radvd.conf:
interface eth1
{
AdvSendAdvert on;
AdvManagedFlag off;
AdvOtherConfigFlag on;
prefix 2001:db8:1234:1::/64
{
AdvOnLink on;
AdvAutonomous on;};
RDNSS 2001:4860:4860::8888 {};
};
启动:
systemctl enable --now radvd
7.3 客户端验证
ip -6 addr show
ip -6 route
ping -6 2001:db8:1234:1::1
- Python 示例:监听 RA(Scapy)
pip install scapy
sniff_ra.py:
from scapy.all import sniff
from scapy.layers.inet6 import IPv6, ICMPv6ND_RA
def handle(pkt):
if pkt.haslayer(ICMPv6ND_RA):
ra = pkt[ICMPv6ND_RA]
print("RA M=", ra.M, "O=", ra.O)
sniff(filter="icmp6", prn=handle)
- 速查总结
- 有 PIO + A=1 → SLAAC
- M=1 → DHCPv6 有状态
- O=1 → DHCPv6 无状态
- prefix=/64 最安全
- DNS 来自 RDNSS 或 DHCPv6