IPv6 主机怎么不靠 DHCP 就给自己配好地址?为什么 EUI-64 会暴露设备身份,临时地址又是什么?这篇先看本机的 SLAAC 参数和各接口地址的生成方式,再用计算演示三种接口标识符,最后看这个没有 IPv6 路由器的网络里应用看到的现象。
net.inet6.ip6.accept_rtadv = 1
net.inet6.ip6.auto_linklocal = 1
net.inet6.ip6.use_tempaddr = 1
net.inet6.ip6.temppltime = 86400
net.inet6.ip6.tempvltime = 604800
net.inet6.ip6.dad_count = 1
net.inet6.icmp6.nd6_optimistic_dad = 63
net.inet6.ip6.auto_flowlabel = 1
net.inet6.icmp6.nd6_delay = 5
net.inet6.icmp6.nd6_mmaxtries = 3
net.inet6.icmp6.nd6_umaxtries = 3
临时地址:首选寿命 24 小时、有效寿命 7 天(use_tempaddr = 1,1 表示启用隐私扩展);nd6_delay = 5 秒,就是上一篇看到的 DELAY 阶段长度;auto_flowlabel = 1,就是第 23 篇里内核自动填流标签的开关
lo0 无 MAC(隧道) 接口标识符无法与 MAC 比较
en0 有 MAC 接口标识符不是 EUI-64(地址标志 secured)
awdl0 有 MAC 接口标识符= MAC 推出的 EUI-64
llw0 有 MAC 接口标识符= MAC 推出的 EUI-64
utun0 无 MAC(隧道) 接口标识符无法与 MAC 比较
utun1 无 MAC(隧道) 接口标识符无法与 MAC 比较
utun2 无 MAC(隧道) 接口标识符无法与 MAC 比较
utun3 无 MAC(隧道) 接口标识符无法与 MAC 比较
有 MAC 的接口 3 个,其中链路本地地址是 EUI-64 的 2 个路由器通告前缀(RA),主机用前缀加自己生成的 64 位接口标识符拼出地址,再做重复地址检测(DAD)。本机参数已打开 accept_rtadv,但这条链路上听不到 RA,所以只有链路本地地址。
(示例 MAC 用 00:11:22:33:44:55,不是本机的 MAC) 1. EUI-64:接口标识符 = MAC 中间插 ff:fe 并翻转第 7 位 → 0211:22ff:fe33:4455(由 MAC 决定,在任何网络里都一样) 2. 稳定不透明:接口标识符 = 哈希(前缀, 接口名, 本机秘密值, DAD 计数)的前 64 位 → 1c7b:e47c:206a:da37;同一前缀每次算出相同:True;换一个前缀(2001:db8:9:9::/64)得到 bf28:db64:a331:f008,不同:True 3. 临时地址:每个首选寿命周期重新随机生成:2291:d8cd:c310:411e;7ec2:7378:a661:c935;187c:07e4:d563:6e9b 拼出来的地址:EUI-64 2001:db8:1:2:211:22ff:fe33:4455、稳定 2001:db8:1:2:1c7b:e47c:206a:da37、临时 2001:db8:1:2:2291:d8cd:c310:411e EUI-64 的缺点:同一个设备走到任何网络,后 64 位都不变,可以被跟踪;稳定不透明地址在一个网络内不变、换网络就变;临时地址对外连接用,定期更换 同一台机器在两个网络(前缀 2001:db8:1:2::/64 与 2001:db8:9:9::/64)里:EUI-64 地址后 64 位相同,稳定地址后 64 位不同
EUI-64 由 MAC 决定,换网络不变,可被跟踪;稳定不透明在同一前缀内不变,换前缀就变;临时地址随机并定期更换。本机 en0 的链路本地地址就是稳定不透明的(secured),而 awdl0 和 llw0 仍是 EUI-64。
120 秒共抓到 24 个 ICMPv6 报文:NS 邻居请求 12;NA 邻居通告 12 其中 NS 里:源地址是 ::(DAD 探测,有设备在检查自己要用的地址有没有人占用)0 个;目的是被请求节点组播的 0 个;单播的(NUD 探测)12 个 RA 路由器通告 0 个——120 秒内没有任何路由器通告(RA 的发送间隔通常是几分钟,但本机的 ndp -rn 也显示 en0 上没有路由器,见上一篇)
本机 use_tempaddr = 1,临时地址首选 24 小时,到期换新的;有效 7 天后才彻底作废。
经 DNS 查 example.com:A 记录 2 个、AAAA 记录 2 个(DNS 里有 IPv6 地址)
getaddrinfo(example.com, 80) 使用 默认:返回 2 项:{'IPv4': 2};第一项是 IPv4
getaddrinfo(example.com, 80) 使用 AI_ADDRCONFIG:返回 2 项:{'IPv4': 2};第一项是 IPv4
route get -inet6 到 example.com 的一个 IPv6 地址:route: writing to routing socket: not in table;接口 ?,标志 ?
connect 到该 IPv6 地址:OSError: No route to host,用时 0.1 ms——没有 IPv6 路由,内核立刻失败,不用等超时getaddrinfo 在这台机器上只返回 IPv4;若硬连 IPv6 地址,内核立刻报 No route to host。是否自动回退由应用决定。