IPv6地址生成
发现很多人的信息还停留在 1998 年的 RFC 2464 定义的 EUI64
,由于其潜在安全风险,2014 年的 RFC 7217 定义了生成用于 SLAAC 的接口 ID 的算法。目前就我所了解的主流操作系统,iOS 12 已经支持这个标准,Android 7 尚不支持、同时也不支持 DHCPv6,Windows 10 1803 虽然没有遵守 RFC 7217,但也没有使用 EUI64,并且还支持随机 MAC 地址。
每个节点都会自动生成一个本地链接地址,但是:
- 该地址可能不是以RFC 2464中指定的EUI-64格式生成的。IPv6地址也可以是加密生成的地址(RFC 3972),临时隐私地址(RFC 4941),或者在现代操作系统中,可以是稳定的隐私地址(RFC 7217)。
- 由于管理员的明确配置,看起来像具有EUI-64接口ID的地址实际上可能与指示的MAC地址不对应。
由于不能只是将地址“转换回”为MAC地址,因此必须发送邻居请求来确定MAC地址。
还有其他一些原因也使得必须进行邻居征集。其中一些是:
- 重复地址检测(RFC 4862)。其他主机可能(正确或错误)声称了该主机要使用的地址。
- 邻居不可达检测。缺乏对邻居请求的响应是邻居无法到达的一个指标。
RFC 7217 IPv6 更新指定了算法来生成 IPv6 接口标识符(以及 IPv6 地址),在相同网络内稳定,但随着节点从一个网络移动到另一个网络而发生变化。该算法可用以下表达式来总结和体现:
IPv6_IID = Hash(Net_Prefix, Net_ID, Net_Iface_ID, Secret_Key)
其中:
Hash():加密安全哈希函数
Net_Prefix:本地路由器发布的 IPv6 前缀
Net_ID:可选网络标识符,例如 WiFi 网络的服务集标识符
Net_Iface_ID:底层网络接口的标识符(例如网络接口名称)
Secret_Key:秘密值,通常在系统安装期间作为随机值初始化,并在重新启动时保持不变
基本上来说,IPv6 接口标识符是通过对多个参数连接计算安全散列来获得,最常见的是本地路由器( Net_Prefix )和秘密密钥( Secret_Key )公布的网络前缀。
只要节点保持在相同网络,它将维护和配置相同的 IPv6 地址,这是因为散列函数的所有参数保持不变。另一方面,由于网络前缀会改变,所以一旦节点连接到不同的网络,IPv6 接口标识符将会改变。同时,如果节点返回到之前连接的网络,它将配置与之前相同的 IPv6 地址,因为用于计算该 IPv6 接口标识符的所有参数都将与原来情况相同。