IPv6 地址分配----理论
IPv6 地址分配----理论
本文介绍了现今IPv6环境下的地址获取方式以及相关概念,主要侧重于理论介绍,相关实验参见另一篇文章。
在一个部署 IPv6 的广播域中,相比 IPv4 一个最明显的区别就是 IPv6 路由通告;在 IPv4 时代,一个广播域中的 ipv4 网段并没有显式说明,或者说并没有一个 ipv4 网段宣称占据了这个广播域,仅使用这个广播域的广播/组播能力,多个ipv4网段共用一个广播域的情况也不鲜见;而在ipv6中,运行ipv6协议的路由器会主动发送名为路由通告 Router Advertisement的 ICMPv6 报文,在广播域中宣告/广播*此 ipv6 网段占据了该广播域;
*(准确的讲应该是组播,IPv6 已经没有广播概念了,这里使用广播这个说法为了说明是公开发送的,在一个广播域中,广播和组播达成的功能类似,且在低端交换机中,广播和组播的转发方式是一致的)
RA(路由通告 Router Advertisement)使用 ICMPv6 报文(type 134),属于 NDP 协议的一部分 ;
ICMPv6
IPv6 时代的ip层控制协议(类比ipv4中的arp、icmp等)均使用icmpv6报文,取消了IP层的广播,转而广泛使用组播。ICMPv6 中的 type 133 ~ 137 报文由NDP协议使用,用于发现网关、邻居、地址配置等等。
NDP
NDP协议(Neighbor Discovery Protocol,邻居发现协议) 可以视为 ICMPv6 的子协议,其功能主要是“邻居发现”和“路由器发现”;NDP 有五种报文:
- RA:由路由器周期性发送,也可以响应 RS 发送,用于宣告本广播域中 IPv6 相关信息。比如前缀、网关、DNS等等;
- RS:通常由终端主动发送,用于在未收到周期性 RA 的情况下,请求 RA;
- NS:请求邻居,和 IPv4 的 ARP request 功能一致;
- NA:用于回复 NS ,和 IPv4 的 ARP reply功能一致;
- Redirect:重定向,类似于 IPv4 的icmp redirect功能;
RS/RA
RS/RA 是IPv6 环境下独有的控制信令,此信令明确了一个广播域中各节点所代表的角色。
- 广播域中发送RA的为路由器
- 广播域中可以存在多个路由器
- RA 组播周期性发送
- RS 用于在未收到 RA 情况下请求 RA
- RA 中的
Flags
表明当前广播域中 IPv6 地址的配置方式
主要Flags
RA 中有几个重要的 flag
控制终端 IPv6 地址的配置方式;
如上图,这些 Flags 分布在两个位置----ICMPv6 报头和 prefix option,后者称为 PIO(Prefix Information Option) flag。
- M(Managed address configuration):位于报头,M=1 表明终端应该使用 DHCPv6 协议配置地址和其他网络参数;如果M=1,则忽略 O Flag;此flag用于 DHCPv6 有状态模式。
- O(Other configuration):位于报头,O=1且M=0 表明终端应该使用 DHCPv6 设置除了 IPv6 地址之外的其他(dns/ntp等),此 flag 用于 DHCPv6 无状态模式。
- A(Autononous address-configuration flag):位于PIO中,A=1 表明终端应该使用 SLAAC 配置 IPv6 地址;PIO可以包含多个 Prefix,这也就意味着一个广播域中可以存在多个 IPv6 网段。
这几种flag是可以复合使用的,以满足不同场景需求,除了手动静态配置ipv6地址,动态/自动配置或者半自动配置ipv6地址的方式都需要从ndp协议的 RA 开始,就好像 RA 引导了IPv6自动配置的开始;RA中的不同flag叠加影响地址自动配置;
其实从这几个 flag 分布方式可以看出,slaac 和 dhcpv6 是相互独立的,从设计阶段开始,slaac 就被当作是最基础的地址生成方式,而且具有不错的隐私性。DHCPv6 作为地址配置的增强方式出现,不过某些终端并不支持,好像也并不打算支持 DHCPv6,本文发布的时候 Android 终端仍然不支持 DHCPv6。
在一个广播域中可以组合使用 SLAAC 和 DHCPv6 以满足不同终端的需求。
常见的设置方式:
- DHCPv6 有状态模式,无 SLAAC: M=1 A=0
- SLAAC(不使用DHCPv6): M=0 O=0 A=1
- SLAAC + DHCPv6 无状态: M=0 O=1 A=1
- SLAAC + DHCPv6 有状态: M=1 A=1
协议/技术 | 地址 | 前缀 | 网关 | DNS | FLAG |
---|---|---|---|---|---|
NDP_RA | X | V | V | V | N/A |
SLAAC | V | X | X | X | A=1 |
有状态DHCPv6 | V | V | V | V | M=1 |
无状态DHCPv6 | X | X | X | V | M=0 O=1 |
RA 推送 DNS,即 Recursive DNS Server 选项,是在 RFC5006 中才提出,后被 RFC6106 替代,最新的标准是 RFC8106。由于此种方式出现的较晚,一些稍微老旧的终端/软件可能并不支持 RA 方式获取 dns。
表中,RA 并不是独立的一种技术,而是一个 IPv6 的广播域必需的,此处之所以这样展示是为了体现出不同参数的获取来源。
其他flags
- L flag(On-Link):位于PIO中,L=0 表示该前缀不应该被视为本地链路上的有效前缀;主要路由转发(作为下一跳地址使用)、隧道;例如路由器的互联地址只用于下一跳使用,很少需要被访问;这个L flag一般场景少见;
- R flag(Router Address Flag):,位于PIO中; 当 R=1 时候,表明通告的prefix不是一个前缀而是一个完整的IPv6地址,即路由器接口的地址;这样,前缀信息不仅是告知主机该子网的前缀,还告知路由器的具体地址(不是link-local),用于使用全局地址和该路由器通信,一般用于移动IPv6环境下。R flag 是独立解释的不和其他 flag 冲突,由于前缀处理只关注前 Prefix Length 位,因此将完整地址放入前缀字段不会影响常规的前缀通告和地址自动配置流程。这保证了兼容性,使得网络中的设备可以正确处理该信息,无论它们是否支持额外的功能。
- Prf(Default Router Preference):位于报头中,默认值是medium(0);用于指示路由器的优先级别,存在多个默认路由器时,终端应选择prf最高的做默认路由,优先级相同则生成两条默认路由,不过并不推荐这样做。
- P flag(ND Proxy):位于报头中,用于指示当前的 RA 消息是由一个代理发送的,多用于移动 IPv6 三层漫游情况(即,离开原网络后仍然使用原网络IPv6地址通信)。
- H flag(Home Agent):位于报头中,在移动IPv6情况,当终端三层漫游后,收到 RA 后用表示该路由器是否可以作为归属代理节点。
- P flag(PD only flag):位于PIO中 ,这个标志位和上面的P flag不同,位于PIO(prefix information Option)中,目前仍属于草案,未被实施,用于PD-only场景。
MLD 协议
由于IPv6环境下取消了广播,从二层数据包角度来看,也就是不会出现以太网二层帧头中的DMAC字段和Type字段是ff:ff:ff:ff:ff:ff加0x86dd这种组合。
IPv6环境广泛使用组播以替代广播的作用,MLD 是v6环境下的组播控制协议。
MLD 协议简单来讲就是 IPv6 环境下的 IGMP,终端设备使用MLD 协议查询加入的组播组或宣称要加入某个组播组。
MLD协议目前有两个版本,都使用ICMPv6报文,所以MLDv1和v2可以理解为ICMPv6的子协议,MLDv1 使用 type 130 ~ 132报文,分别对应:
- 130 为查询报文
- 131 为成员报告报文,即报告要加入某个组播组
- 132 为程院离开报文,即离开某个组播组
MLDv2 使用 type 130 和 143:
- 130 和v1共用,用于查询
- 143 用于通报加组和离开
SLAAC
IPv6 SLAAC(Stateless Address Autoconfiguration,无状态地址自动配置)是一种用于在IPv6网络中自动分配IP地址的方法。它允许设备在连接到网络时自动生成其IPv6地址,而无需借助DHCP服务器来管理和分配地址。
SLAAC 是IPv6自动配置最基础的方式,所需要的外部信息仅为路由器发出的RA,配合EUI64算法就可以完成自身网卡的IPv6地址配置(使用EUI64算法生成地址并不是强制的,系统可以采用自己的方式生成地址,更有甚者有的系统会生成多个地址用于不同目的)。一般而言支持IPv6设备首先需要支持的就是SLAAC。
主要特点:
-
无状态:设备自行生成和管理IP地址,网络不需要维护和记录地址的状态信息。
-
前缀通告:网络路由器通过定期发送Router Advertisement (RA) 消息,告知网络设备可用的网络前缀。设备根据这个前缀和自身的MAC地址或随机生成的接口标识符来自动生成完整的IPv6地址。
-
无需配置:设备能够在没有手动配置的情况下,自动获取一个全局唯一的IPv6地址。
DHCPv6
DHCPv6作为地址配置的增强方式,分为有状态自动分配和无状态自动分配两种方式,这里的无状态方式和SLAAC中的无状态并无关联;DHCPv6 独立于 SLAAC 存在,可以独立于 SLAAC 运行。
-
DHCPv6有状态自动分配。DHCPv6服务器自动配置IPv6地址/前缀,同时分配DNS、NTP服务器等网络配置参数。
-
DHCPv6无状态自动分配。DHCP服务器只分配除IPv6地址以外的配置参数,包括DNS、NIS、SNTP服务器地址等参数。
无论那种方式,IPv6 的自动配置都是从NDP中的 RA 开始,RA 中的FLAG M 或 O 置位代表后续IPv6的自动配置需要使用DHCPv6进行;
DHCP-PD
DHCP-PD 技术最早在RFC3633中提出,经过几次更新目前最新的是RFC8415,其主要思想是把DHCPv6的地址分配方式划分为多层,dhcp client不再是仅仅获取地址用于终端通信,而是可以作为次级路由器身份把地址层层分配下去;
这样的好处是便于快速和统一部署大量地址,尤其是在大规模动态地址的情况下,此种地址分配方式在家庭宽带中已经大量部署;光猫从其上级获取一段地址用于本地网络终端的地址分配,甚至从光猫拿到的地址还能再往下一层分配。
PD-only(草案)
IPv6环境下,终端一般会持有多个IPv6地址,link-local地址、稳定地址、多个临时地址等,这样网关需要维护大量邻居表,无形中增加了设备的开销。下图源自这里 Page 6;
从图中得知,右侧的手机由于有多个IPv6地址,网关/路由器需要维护多个邻居表项,但仅用于和一个终端通信;此时这个 MAC 地址对应多个ip地址,这看起来和路由器间的三层转发通信很像了,PD-Only 则把每个终端设备看成一个IPv6地址池,使用 DHCP-PD 的方式获取一段IPv6 地址而不是一个或几个/128的主机地址。
由此我们把多条邻居表转换为一条邻居表
加一条路由表
(图中router框蓝色条目)。同时也带来了其他优势:
- Security:避免了邻居表项被有意或无意的耗尽,不同设备之间的邻居仅限于link-local地址;
- Accountability:PD是有状态的,DHCPv6 server能获得更多信息
- Fate Sharing:同一终端的不同地址命运共享原则,便于排查故障
- Network Extensibility:便于层级扩展
也带来有坏处----每个终端均需要消耗一个/64地址段,造成大量地址浪费。
当然这个提案目前仅是草案,还没有实施,设想一下如果所有终端均使用该草案实施方式分配的话,IPv6的地址空间将被从128砍成64位,虽说现在IPv6的使用方式已经非常豪放了,但这种方式使用方式未免过于浪费了。所以就算草案以后变成标准,也只是在某些大型网络场景下使用,不会以排他形式部署。
刚刚只谈及了右侧的手机终端,现在看一下左侧的虚拟化环境,此种情况使用这种PD方式拆分了router的ND表项,把部分ND 表项压力交给了虚拟化环境的虚拟交换机,同样的把多条ND条目转换为一条link-local的ND和一条路由条目。不过对于虚拟化环境下DHCP的使用场景还有待商榷,毕竟虚拟化环境目前用的多的还是服务器,服务器明显不适用动态地址。
PD-only方式取消了常规方式的下一跳,仅使用link-local作为下一跳
草案中给PD-only 在 PIO 中预留了一个P flag用于标记。
基于策略的地址配置
前面提过,RA的周期性发送使用的是组播方式,但是针对 RS 的回复使用什么方式呢? 答案是组播和单播两者均可;如果 RA 都是以组播方式发送,那么同一个广播域下的所有终端势必都可以收到,这样就无法为某一个或几个终端提供特殊的策略。
如果关闭周期性的RA ,同时只使用单播响应 RS ,这样就可以为不同终端提供不同网络配置参数。
一终端多IPv6地址
IPv6 环境下,终端一般会持有多个 IPv6 地址,甚至是一整个网段。这就是为什么经常看到 Windows 电脑上有很多 IPv6 地址,这主要有以下几个原因:
- Windows 系统针对同一个前缀,至少生成2个地址,其中一个被称为“稳定地址”,用于从外部访问主机;一个被称为“临时地址”,用于本机发起到外部的连接。
- Windows 默认启用了隐私扩展,生成的临时地址会有一个较短的生命周期。在临时地址的生命周期到期后,地址会变为废止状态,并生成新的临时地址。但此时若有应用程序仍在使用被废止的地址,则该地址不会被删除。
上述两个原因导致启用IPv6的Windows系统在运行一段时间后,会看到有很多IPv6地址。其他系统的终端也会有类似的行为。
link-local
对比IPv4环境,IPv6 地址有所谓的 link-local 地址而且充当比较重要作用;由于一个接口可以配置很多IPv6地址,当这些地址作为下一跳使用的时候会出现混乱,这样不利于管理也不利于设备性能开销,使用Link Local地址唯一标识链路上的一个节点就避免了这个问题。而且在网络重新编址过程中,Link Local并不会发生变化,更利于快速更改编址。
DAD(Duplicate Address Detection)
终端在使用RA中宣告的前缀生成完整的IPv6地址之后,需要先对该地址进行重复地址检测(DAD Duplicate Address Detection),检测通过确认无冲突后,才能使用该地址。
DAD的原理也很简单,发送待 DAD 检测的地址的 NS ,即自己解析自己,若无其他终端响应就可以视为通过了DAD。
在检测完成前,该地址被称为“临时地址”或“候选地址”(tentative address)。IPv6 地址在使用之前均需要通过 DAD 才可进行后续操作。
IPv6 邻居状态
邻居表,在IPv4环境下就是ARP表,系统维护Arp表内容由系统自己决定,比如端口、更新时间等;
到了IPv6环境,ND表代替了arp表,而且协议规定了5种邻居状态,IPv6 邻居状态,分别是:
Incomplete、Reachable、Stale、Delay、Probe,其中只有 Stale 状态是稳定状态。
- Incomplete (未完成状态):表⽰正在解 析地址,但邻居链路层地址尚未确定。
- Reachable (可达状态):表⽰地址解析 成功,该邻居可达。
- Stale(失效状态):表⽰可达时间耗尽,未确定邻居是否可达。
- Delay(延迟状态):表⽰未确定邻居是否可达。Delay 状态不是⼀个稳定的状态,⽽是⼀个延时等待状态。
- Probe (探测状态):节点会向处于 Probe 状态的邻居持续发送 NS 报⽂。
不同状态之间迁移如下图:(此图仅供参考,不通系统实现可能略有不同)
地址撤销
IPv4 环境下的 DHCP 一旦终端获取了IP地址后,服务器没有一种方式对已经分配的地址进行变更、撤销等操作,这在动态地址环境中可能造成一些不便;IPv6 由于有 RA 的存在某种程度上解决了此种不便。
比如使用 DHCP-PD 获取的并分配的地址段(例如家庭宽带的地址),长期运行后可能会生地址变动。如果终端地址仍然使用原来的地址势必会导致通信终端,解决办法一般来说需要重启系统或者手动执行命令使终端网卡重新获取地址。这显然十分不便。
这时候撤销原先的地址前缀就显得十分有必要了,具体实现方式为路由器发送 RA 消息,在 PIO 中将过期前缀的 Valid Lifetime 设置为0。主机收到此类RA之后,会立即将前缀列表中对应的条目设置为超时(RFC4861第6.3.5节)。
参考
https://datatracker.ietf.org/meeting/116/materials/slides-116-v6ops-using-dhcp-pd-to-allocate-64-per-host-in-broadcast-networks
https://www.ietf.org/proceedings/83/slides/slides-83-v6ops-3.pdf
https://www.zte.com.cn/content/dam/zte-site/res-www-zte-com-cn/mediares/magazine/publication/com_cn/article/202201/12.pdf
https://datatracker.ietf.org/doc/html/rfc8425
https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xhtml
https://www.cnblogs.com/bluntwu2022/p/18364956
https://www.rfc-editor.org/rfc/rfc6603
https://www.rfc-editor.org/rfc/rfc8415
https://www.chiphell.com/thread-2552932-1-1.html
https://support.huawei.com/enterprise/zh/doc/EDOC1100033729/329fa152#dc_fd_dhcpv6_0006