目录
文章目录
IPv6 的地址配置方式
IPv4 的地址配置方式主要有 2 种,手动配置、和基于 DHCP 协议的自动分配。在 IPv4 中,主机之间的通信是建立在 IP 协议和 ARP 协议之上的,主机通过 ARP 广播得知 IP 地址所对应的主机网卡的 MAC 地址,进而在子网中进行数据报文的传送。
不过,IPv6 是没有广播寻址模式的,所以 ARP 在 IPv6 中已被弃用。代而替之的,IPv6 支持 3 种地址配置方式:
- 手动配置。
- 基于 ICMPv6 NDP 协议的自动配置。
- 基于 DHCPv6 协议的自动配置。
本文主要关心 IPv6 的自动配置方式,IPv6 支持 3 种自动配置模式:
-
ICMPv6 NDP(Stateless,Careless):IETF RFC 4862。又称为 SLAAC(Stateless Auto Address Configuration,全称无状态地址自动配置)。如果管理员对主机地址不关心(Careless),只要地址是唯一的、可正确路由的,建议选择 NDP/Stateless 方式。Stateless 的优点是省事,可以实现 IPv6 的 “即插即用”(Plug and Play)特性。路由器配置减少到最低程度,而主机什么都不用做。同时,Stateless 不需要额外的服务器 。
-
DHCPv6(Stateful,Careful):IETF RFC 3315。如果管理员需求完全掌控主机地址状态(Careful),建议选择 DHCPv6,DHCPv6 Server 上具有 IP 地址的 State 信息。Stateful 的优点是可控,但网络需要部署 DHCP 服务器才可为主机(DHCP 客户端)分配地址和发送配置选项。
-
混合模式:Stateless 和 Stateful 并不完全冲突,可以同时部署,协同使用。利用 NDP 下发网关和子网前缀等信息,主机根据子网前缀自动生成 IPv6 地址。同时,利用 DHCPv6 配置 DNS Server 和域名等其他信息。
ICMPv6 NDP 协议
IPv6 引入了 ICMPv6 NDP(Neighbor Discovery Protocol,邻居发现协议)来替代 IPv4 的 ARP(Address Resolution Protocol,地址解析协议)。
ARP 报文封装在 L2 报文中,可视为 2.5 层协议。而 NDP 基于 ICMPv6(Internet Control Message Protocol Version 6,网络控制消息协议第六版)实现,ICMPv6 报文(作为 IPv6 扩展头部)封装在 L3 报文中,可视为 3 层协议。
NDP 在 L3 实现的优点是:
- 可利用 L3 安全特性;
- 可对不同介质的 L2 使用同一种地址解析协议;
- 可使用组播替代广播,减轻 L2 网络压力。
NDP 控制了 IPv6 本地链路上的以下主要活动:
- 邻居发现(Router Discovery):帮助节点确定相邻节点的链路本地地址(如果只给定目标的 IP 地址)。
- 前缀发现(Prefix Discovery):使节点能够搜索已分配给链路的已知子网前缀。节点通过子网前缀来区分位于本地链路上的目标、以及其他链路上的目标(需要通过路由器来访问)。
- 路由器发现:帮助主机查找本地链路上的路由器。
- 参数(Parameter Discovery):节点能够发现所在链路的参数,像链路的 MTU 和跳数限制等。
- 地址自动配置(Address Auto Configuration):使节点能够为其接口自动配置 IPv6 地址。
- 邻居状态跟踪(可达性)。
- 地址解析(Address Resolution):节点不需要通过 ARP 就能够获取链路上其它节点的 MAC 地址。
- 确定下一跳(Next-Hop Determination):能够确定到达目的节点的下一跳链路层节点,或者所在链路的目的节点,或是到达目的节点的路由器。
- 邻居不可达检测(Neighbor Unreachability Detection):节点上能够检测到链路上的邻居何时不可达,邻居有可能是主机,也可能是路由器。
- 重复地址检测(Duplicate Address Detection):使节点能够确定其要使用的地址是否尚未被使用。
- 路由重定向(Redirect):使路由器能够通知主机要用于到达特定目标的较好(优选)的下一个跃点节点。
ICMPv6 NDP 协议的消息类型
NDP 定义了 5 种 ICMPv6 消息,一旦主机获得了 IPv6 地址,它就加入了多个组播组。NDP 使用下列类型的 ICMPv6 消息在链路上的节点之间进行通信:
-
NS msg(Neighbor Solicitation,邻居请求):通过 DHCPv6 自动获取或 ICMPv6 手动配置 IPv6 地址之后,主机向其所有 IPv6 地址的 FF02 :: 1/16 多播地址发送邻居请求消息,以此来确定没有 IPv6 地址冲突。类型字段值是 135 。
-
NA msg(Neighbor Advertisement,邻居通告):在将 IPv6 地址分配给其接口并使其启动和运行后,主机再次发出邻居通告消息,通知该段上的所有其他主机,它已分配这些 IPv6 地址其接口,其他的主机就不要再继续重复分配了。类型字段值是 136 。
一旦主机完成了其 IPv6 地址的配置,它会执行以下操作:
-
RS msg(Router Solicitation,路由器请求):主机在其段上发送路由器请求 FF02 :: 2/16 组播数据包,以了解此段上所有存在的路由器。它帮助主机将路由器配置为其默认网关。如果其默认网关路由器关闭,主机可以切换到新的路由器,并使其成为默认网关。类型字段值是 133 。
-
RA msg(Router Advertisement,路由器通告):当路由器接收到路由器请求消息时,它回应主机,通告它在该链路上的存在。类型字段值是 134 。
-
Redirect msg(重定向):路由器收到了主机发出的路由器请求,但它知道自己并不是该主机的最佳网关。在这种情况下,路由器会响应一个重定向消息,告诉主机有一个更好的 “下一跳” 路由器可用。类型字段值是 137 。
ICMP NDP 协议的地址配置流程
在 ICMP NDP 地址自动配置的流程中,主机将执行以下操作:
- 为每个接口创建链路本地地址,并检验链路本地地址在链路上是否唯一,该操作不要求链路上有路由器。
- 确定全局唯一地址是应通过 Stateless 机制、Stateful 机制、还有这混合两种机制来获取,该操作要求链路上有路由器。
主机将 RA 和自身生成的信息合并,就可得到全球唯一地址。具体的说,分为三步:
- 生成接口 ID 和链路本地地址;
- 从路由器通告获得前缀;
- 将前缀和接口 ID 组合为全球唯一地址,执行重复地址检测(Duplicate Address Detection),确认地址唯一后再分配给接口。
IPv6 主机可以通过 interface 的 MAC 地址转换得到 interface ID(MAC-to-EUI-64),再通过 interface ID 构成链路本地地址(fe80:: + 接口 ID)。在此过程中,主机需要进行重复地址检测,确认同一链路上没有其他接口使用同一地址,再将这个地址分配给接口。因为并不是所有类型的 L2 地址(链路层地址)都可提取出全球唯一的标识,重复地址检测是必要的。
1、路由器发现
路由器在所在的链路上周期性发送 RA ,告知它的存在和配置的所有参数。未收到请求的 RA 的源地址是路由器接口的链路本地 IPv6 地址,目的地址是所有节点的组播地址(FF02::1)。
刚接入到链路的主机,需要等待一个 RA,用来发现链路上的路由器和链路参数。默认等待 200 秒的时间太长。所以,主机激活时,就会发送一个 RS,这个报文的源地址可以是未指定地址(::),也可以是主机的链路本地 IPv6 地址。目的地址就是所有路由器的组播地址(FF02::2),请求链路本地路由器为主机提供一些信息。
只有路由器才会监听链路本地路由器组播地址,当路由器收到 RS 时,就会发送一条 RA 作为响应。如果收到报文的源地址是链路本地地址,那么使用链路本地地址单播发送。如果源地址是未指定地址(::),那么会以组播方式发送给所有节点(FF02::1)。
当主机收到 RS 时,会把路由器的链路本地地址作为默认路由地址,添加到自己的路由表中。如果路由器列表有多条默认路由器条目,那么主机要给出选定默认路由器的方法。要么是整个默认路由器列表依次轮询,要么选择单台路由器作为默认路由。
2、自动生成链路本地地址
具体地说,IPv6 主机使用 NDP 从 RA 中获取到子网前缀(站点前缀 + SubnetID)。主机通过合并子网前缀以及 interface ID 来自动生成 IPv6 地址。如果没有路由器的话,那么主机可以只生成链路本地地址。链路本地地址只能用于和同一链路上的节点进行通信。
另外,NDP 还允许接口自动生成一个临时地址,但是,与自动配置的标准 IPv6 地址不同,临时地址由站点前缀和一个随机生成的 64 位数字组成。这个随机数将成为 IPv6 地址的 interface ID 部分。临时地址作为 interface ID 时,不会生成链路本地地址。
子网前缀从路由器来。即使主机不主动找路由器,路由器也会周期性发送 RA 报文,向链路上所有节点通告子网前缀,这称为 Unsolicited RA。如果主机不想等,也可主动发送 RS 报文,催促路由器发送 RA 报文,这称为 Solicited RA。即使发送 RS 报文前就收到 RA 报文,主机也应至少发送一次 RS 报文,因为 Solicited RA 可能比 Unsolicited RA 报文包含更丰富的信息。
为了避免造成网络拥塞,主机不会在获得链路本地地址后立即发送 RS 报文,而是延迟一段随机时间后再发送,在大面积故障恢复(如停电结束)后链路不会同时涌入大量 RS 报文。同样道理,路由器的周期性 RA 报文也不是严格按照周期发送的,避免同一链路上的多个路由器同时发送 RA 报文。
假设主机链路本地地址为 IP A,路由器链路本地地址为 IP B。主机向同一链路所有路由器发送 RS 报文,请求路由器发送 RA 报文:源地址为 IP A,目的地址为 ff02::2,即同一链路所有路由器的组播地址,ICMP 报文类型为 133。
路由器收到 RS 报文后,向同一链路所有节点发送 RA 报文:源地址为 IP B,目的地址为 IP A(如果是 Unsolicited 通告则目的地址为 ff02::1,即同一链路所有节点的组播地址),ICMP 报文类型为 134。
RA 报文除了包含前缀(Prefix),还包含 MTU(最大传输单元)、Hop Limit(最大跳数)、Route(路由)、Router Lifetime(路由器生存期)、ReachableTime(可达性确认时间)和 RetransTimer(NS 重发时间间隔)等。路由器还会告诉主机使用 NDP 还是 DHCPv6 获得全球唯一地址,以及如果使用 NDP,上述其他信息是否通过 DHCPv6 获得。
经过第二步,接口 ID 有了,前缀也有了,主机将前缀和接口 ID 组合,就获得全球唯一地址。全球唯一地址是单播地址,主机应先进行重复地址检测,再将这个地址分配给接口。实际上,不管地址是通过 Stateless 配置的,还是通过 DHCPv6 配置的,甚至是手工配置的,都应进行重复地址检测。(某些厂家只检测链路本地地址,不检测全球唯一地址,是基于两者由相同接口 ID 构成的前提。实际上,这个前提并不成立,同一接口的多个单播地址不一定使用相同的接口 ID 构成)。
如果一台主机只需要和所在链路上的设备通信,那么它自动配置的链路本地地址就已经满足了。但是如果主机需要和链路之外的设备通信,那么它就需要一个更大范围的地址,通常是一个全球 IPv6 地址。有两种途径获取这类地址:有状态或无状态的地址自动配置。
使用 DHCPv6 服务器来分配 IPv6 地址,称为有状态地址自动配置。主机要么根据预先的配置查找 DHCPv6 服务器,要么收到字段 M 置位的路由器通告报文来获取 DHCPv6 服务器。
无状态地址自动配置(Stateless Address Autoconfiguration ,SLAAC),不依赖服务器、不需要手动配置。这个过程非常简单,当一台 IPv6 设备接入网络时,会发送 RS 来查询网络中是否存在路由器。RA 有一个字段可以告诉 IPv6 设备使用哪种方式配置自己的 IPv6 地址,这个字段称为 M 位。如果 M 位置位,值为 1 时,表示设备通过 DHCPv6 协议动态配置 IPv6 地址;如果 M 位不置位,值为 0 时,则表示设备通过 SLAAC 来配置 IPv6 地址。
IPv6 设备从收到的 RA 中获取一个或多个链路前缀,再加上之前确定的接口 ID,就得到了一个全球唯一的 IPv6 地址。IPv6 设备执行 SLAAC 的过程,不需要人工干预,也没有 DHCP 服务器参与,设备自行完成配置。也就是说,这种机制为 IPv6 网络提供了即插即用功能。
3、重复地址检测
主机在生成链路本地地址过程中,会进行重复地址检查,若通过,则为主机分配 IPv6 地址;若不通过主机则只好停止 Stateless 自动配置,转为手工配置。
无论哪种单播地址,在将 IP 占为己有之前,主机应将其标记为 Tentative(临时)状态,重复地址检测通过后再标记为 Valid(合法)状态。如果主机正在请求某个 IP(Tentative 状态),同时收到了其他主机对同一 IP 的 NS 请求,或已使用同一 IP 的 NA 通告,主机应放弃这个 IP。极端情况是,每个请求主机都收到其他主机的请求而同时放弃这个 IP。
4、邻居发现(邻居地址解析)
主机如果想和同一链路的其他节点通信,需先获得对方的链路本地地址,然后进行地址解析,以获得对方的 L2 链路层 MAC 地址。
地址解析和重复地址检测过程有些相似,不同的是,NS 报文中询问的目标地址是别人的地址(而不是自己的地址),收到 NS 报文的节点应查看 Option 包含的目标地址,如果和自身地址相同,应返回 NA 报文通告自己的链路层地址。
简单的说,重复地址检测 NS 报文询问目标是自己的地址,不希望收到 NA 报文;地址解析 NS 报文询问目标是别人的地址,希望收到 NA 报文。
NS 和 NA 报文都包含发送方的 IP 地址和链路层地址,通过上述过程双方均获得对方 IP 地址和 MAC 地址的绑定关系,并记录到邻居表中并进行维护。邻居状态包括:Empty、Incomplete、Reachable、Stale、Delay 和 Probe。
IPv4 通过 ARP 获取 MAC 地址,然而 ARP 协议无法照搬到 IPv6 环境中,IPv6 没有定义广播地址。为了解决查询目的设备的 MAC 地址问题, IPv6 通过 NDP 获取 MAC 地址。IPv6 设备使用 NS 和 NA 来实现 MAC 地址的查询和响应。IPv6 使用目的节点组播地址作为 NS 的目的地址。
目的节点的组播地址的前 104 位固定是 FF02::1:FF ,后 24 位使用目的单播 IPv6 地址接口 ID 的后 24 位。当接口获取一个单播或任意播 IPv6 地址时,就会同时监听发送给这个单播地址对于的目的节点组播地址。
如果目的节点是链路之外的节点,那么可以通过路由器通告报文,获取默认路由器的 MAC 地址。如果目的节点在链路内,那么节点会先查找邻居缓存看一下是否已经学到这个地址。IPv6 的邻居缓存和 IPv4 的 ARP 缓存相似,记录 IP 地址和 MAC 地址的对应关系。
如果地址不在邻居缓存中,节点会发送一个 NS 。目的节点收到报文后,就知道源节点的 MAC 地址,并回复邻居通告报文。
如果目的节点存在并且收到了 NS ,那么它会回复一个 NA 。这个 NA 的目的地址就是源节点的源地址。收到响应的 NA 后,源节点就把目的节点的 MAC 地址添加到邻居缓存的条目中。
NDP 的 NA 还有另一种用法,当 IPv6 节点的 MAC 地址发生变化时,也可以在未收到 NS 的情况下,直接向本地链路发生一条 NA ,向本地链路上其它设备通告新的 IPv6 地址和 MAC 地址的对应关系。因为目的是通告给链路中所有设备,而不是某一台设备,所有 NA 的目的地址就是链路本地所有节点组播地址(FF02::1)。