NDP协议

基本内容

IPv6邻居发现(Neighbor Discovery,ND)协议使用五种类型的ICMPv6消息,实现下面一些功能:地址解析验证邻居是否可达重复地址检测路由器发现/前缀发现地址自动配置重定向等功能。 ND协议通常与ARP协议共同写成ARP/ND,因此可以从此知道,它实际上可以理解为IPV6中的ARP协议,实现了ARP的功能,此外进行扩展。

ICMPv6消息

类型号

作用

邻居请求消息NS(Neighbor Solicitation)

135

获取邻居的链路层地址

验证邻居是否可达

进行重复地址检测

邻居通告消息NA(Neighbor Advertisement)

136

对NS消息进行响应

节点在链路层变化时主动发送NA消息,向邻居节点通告本节点的变化信息

路由器请求消息RS(Router Solicitation)

133

节点启动后,通过RS消息向路由器发出请求,请求前缀和其他配置信息,用于节点的自动配置

路由器通告消息RA(Router Advertisement)

134

对RS消息进行响应

在没有抑制RA消息发布的条件下,路由器会周期性地发布RA消息,其中包括前缀信息选项和一些标志位的信息

重定向消息(Redirect)

137

当满足一定的条件时,缺省网关通过向源主机发送重定向消息,使主机重新选择正确的下一跳地址进行后续报文的发送

NS/NA报文功能

如上表中所示,NS/NA报文的功能实际上和IPv4中的ARP协议报文很类似,包括地址冲突检测、ip/mac表项生成等,并额外扩展了一个邻居可达性探测的功能。

地址解析

获取同一链路上邻居节点的链路层地址(与IPv4的ARP功能相同),通过邻居请求消息NS和邻居通告消息NA实现。以下图为例,A获取B的链路层地址过程如下:

img (1) 节点A以组播方式发送NS消息。NS消息的源地址是节点A的接口IPv6地址,目的地址是节点B的被请求节点组播地址,消息内容中包含了节点A的链路层地址和请求的目标地址

(2) 节点B收到NS消息后,判断报文的目标地址是否为自己的IPv6地址。如果是,则节点B可以学习到节点A的链路层地址,并以单播方式返回NA消息,其中包含了自己的链路层地址。

(3) 节点A从收到的NA消息中就可获取到节点B的链路层地址。

验证邻居是否可达

在获取到邻居节点的链路层地址后,通过邻居请求消息NS和邻居通告消息NA可以验证邻居节点是否可达。

(1) 节点发送NS消息,其中目的地址是邻居节点的IPv6地址。

(2) 如果收到邻居节点的确认报文,则认为邻居可达;否则,认为邻居不可达。

重复地址检测

当节点获取到一个IPv6地址后,需要使用重复地址检测功能确定该地址是否已被其他节点使用(与IPv4的免费ARP功能相似)。如图所示,通过NS和NA实现重复地址检测的过程为:

image.png

(1)  节点A发送NS消息,NS消息的源地址是未指定地址::,目的地址是待检测的IPv6地址对应的被请求节点组播地址,消息内容中包含了待检测的IPv6地址。

(2)  如果节点B已经使用这个IPv6地址,则会返回NA消息。其中包含了自己的IPv6地址。

(3)  节点A收到节点B发来的NA消息,就知道该IPv6地址已被使用。反之,则说明该地址未被使用,节点A就可使用此IPv6地址。

实验抓包分析

下面以一个实验来对NS/NA报文交互过程及其功能进行分析验证

  • 实验拓扑

image-20230925145449620

  • 报文交互过程(NA/NS)
  1. PC生成了本地链路地址,发送NS报文进行重复地址检测,目的地址为生成的本地链路地址对应的被请求节点组播地址

image-20230925150711620

  1. 同时,PC会在链路本地范围上发送NA报文,告诉链路范围上的设备自己的链路层地址,类似于免费arp

image-20230925151115204

  1. PC通过RA报文(后续会提到)获取到了地址前缀(2001:: /64),根据EUI-64生成了全球单播唯一地址(2001::353f:47d6:cabd:3f25),仍然首先进行地址冲突检测(第一、二步),接着当PC ping SW,则PC会请求SW的链路层地址

image-20230925153214194

PC发送NS报文请求SW地址(2001::1)的链路层地址,其中报文源IP为PC生成的IPv6全球单播地址,目的IP为2001::1对应的组播地址ff02::1:ff00:1,并且报文中携带Target Address(2001::1),避免不同ipv6地址对应同一个组播地址的问题。

  1. SW收到NS报文后,会首先检查Target Address字段是否是自己的IPv6地址,如果是,则接收并单播回应NA报文。如果该字段的地址不是自己的IPv6地址,则丢弃。

image-20230925153722257

  1. 对于H3C设备,可以使用display ipv6 neighbors all查看ipv6邻居状态,在邻居状态变化时(如由Reachable–>Stale–>Probe)会发送NS/NA报文,对邻居可达性进行探测

image-20230925155325043

< admonition note “NA/NS报文字段含义” false >}}

NA报文:

字段长度含义
Type1字节消息类型,此处值为136。
Code1字节该ICMPv6差错报文的始发者必须将该字段置为0,且接收端忽略该字段。
Checksum2字节用来在ICMPv6报文中检验数据和部分IPv6首部的完整性。
R1比特路由器标记。当置1时,R位指出发送者是路由器。R位由Neighbor Unreachability Detection使用,用于检测改变为主机的路由器。
S1比特请求标记。当置1时,S位指出通告被发送以响应来自目的地地址的Neighbor Solicitation。S位用作Neighbor Unreachability Detection的可达性确认。在多播通告和非请求单播通告中置0。
O1比特替代标记。替代标志,1表示通告中的信息替代缓存,如更新链路层地址时,对于任播的回应则不应置位。在针对任播地址的请求通告中,以及在请求的前缀通告中它不能被置1。在其他请求通告中和在非请求通告中它应当被置1。
Reserved29比特29位未使用字段。它必须由发送者初始化为0,接收者必须忽略它。
Target Address16字节对于请求的通告,是在Neighbor Solicitation消息(该消息催促这个通告)中的Target Address字段。对于非请求通告,是其链路层地址已经改变的地址。Target Address必须不是多播地址。
Options可变选项: Target link-layer address: 目标的链路层地址,即,通告发送者。当响应多播请求时,在有地址的链路层上必须包括此选项。当响应单播Neighbor Solicitation时应当包括此选项。 当对端节点由于没有缓存条目从而不能返回一个Neighbor Advertisements消息时,为了避免无休止的Neighbor Solicitation“递归”,对于多播请求必须包括 此选项。当响应单播请求时,可忽略此选项,因为请求的发送者有正确的链路层地址;其他情况,此选项不能在第一位置发送单播请求。然而,在此情况,包括链路层地址仅增加了少许开销,却消除了潜在的竞争条件,那里在收到对先前的请求的响应之前,发送者删除缓存的链路层地址。 为TLV格式: Type: =2,字段长度为1字节。 Length: 1字节,表示选项的长度(包括类型字段和长度字段),以8字节为单位计算。例如,IEEE802 地址的长度是1。 Link-Layer Address: 可变长度的链路层地址。此字段的内容和形式(包括字节和比特顺序)一般由描述IPv6在不同链路层上如何运行的特定文件中规定。

NS报文:

字段长度含义
Type1字节消息类型,此处值为135。
Code1字节该ICMPv6差错报文的始发者必须将该字段置为0,且接收端忽略该字段。
Checksum2字节用来在ICMPv6报文中检验数据和部分IPv6首部的完整性。
Reserved4字节此字段不使用。它必须由发送者初始化为0,接收者必须忽略它。
Target Address16字节请求的目标的IP地址。它必须不是多播地址。
Options可变选项: Source link-layer address源链路层地址:发送者的链路层地址,如果知道。如果Source Address是未指定地址,必须不包括在内。否则,有地址的链路层上应当包括源链路层地址。 为TLV格式: Type: 1字节,取值为1。 Length: 1字节,表示选项的长度(包括类型字段和长度字段),以8字节为单位计算。例如,IEEE802 地址的长度是1。 Link-Layer Address: 可变长度的链路层地址。此字段的内容和形式(包括字节和比特顺序)一般由描述IPv6在不同链路层上如何运行的特定文件中规定。

< /admonition >}}

邻居状态变化

在前面的抓包分析中,提到了ipv6邻居状态,共有五种状态,下图是邻居状态机迁移过程

image-20230925171815932

  1. A先发送NS报文,并生成缓存条目,此时,邻居状态为Incomplete。

  2. 若B回复NA报文,则邻居状态由Incomplete变为Reachable,否则固定时间后邻居状态由Incomplete变为Empty,即删除表项。

  3. 经过邻居可达时间,邻居状态由Reachable(H3C中邻居可达状态时间默认为1200000ms,即20min)变为Stale,即未知是否可达。

    邻居可达状态时间修改
    H3C设备中,可用ipv6 nd nud reachable-time time,取值范围为1~3600000,单位为毫秒。

  4. 如果在Reachable状态,A收到B的非请求NA报文(MAC地址修改),且报文中携带的B的链路层地址和表项中不同,则邻居状态马上变为Stale。

  5. 在Stale状态若A要向B发送数据,则邻居状态由Stale变为Delay,并发送NS请求。若无发送数据的需求,则会在Stale状态超时后(H3C中默认为240min),进入Delay状态

    邻居可达状态时间修改

    H3C设备中,分为系统视图下配置和接口视图下配置,接口视图下的配置优先级高于系统视图下的配置。 系统视图

    ipv6 neighbor stale-aging { aging-minutes | second aging-seconds } 缺省情况下,STALE状态ND表项的老化时间为240分钟。

    接口视图

    ipv6 neighbor timer stale-aging { aging-minutes | second aging-seconds }

  6. 在经过一段固定时间后,邻居状态由Delay(默认5s)变为Probe(每隔1s发送一次NS报文,连续发送3次),其间若有NA应答,则邻居状态由Delay变为Reachable。

  7. 在Probe状态,A每隔一定时间间隔z(1s)发送单播NS,发送固定次数(3)后,有应答则邻居状态变为Reachable,否则邻居状态变为Empty,即删除表项。

下图是Reach–>Stale–>Delay–>Probe–>Reach的过程(已经将Stale状态超时时间改为60s)

image-20230925172420779

image-20230925172517270

image-20230925172602470

RS/RA报文功能

在NS/NA实验中,提到RS/RA获取地址前缀,接口根据该前缀生成全球唯一单播地址,这个功能即IPv6的无状态自动配置功能。RS/RA报文实现的功能是路由器发现/前缀发现及地址无状态自动配置、重定向功能。

无状态自动配置

路由器发现/前缀发现是指节点从收到的RA消息中获取邻居路由器及所在网络的前缀,以及其他配置参数。

地址无状态自动配置是指节点根据路由器发现/前缀发现所获取的信息,自动配置IPv6地址。

路由器发现/前缀发现通过路由器请求消息RS和路由器通告消息RA来实现,具体过程如下:

(1) 节点启动时,通过RS消息向路由器发出请求,请求前缀和其他配置信息,以便用于节点的配置。

(2) 路由器返回RA消息,其中包括前缀信息选项(路由器也会周期性地发布RA消息)。

(3) 节点利用路由器返回的RA消息中的地址前缀及其他配置参数,自动配置接口的IPv6地址及其他信息。

前缀信息选项中不仅包括地址前缀的信息,还包括该地址前缀的首选生命期(preferred lifetime)和有效生命期(valid lifetime)。节点收到周期性发送的RA消息后,会根据该消息更新前缀的首选生命期和有效生命期。

· 有效生命期:表示前缀有效期。在有效生命期内,通过该前缀自动生成的地址可以正常使用;有效生命期过期后,通过该前缀自动生成的地址变为无效,将被删除。

· 首选生命期:表示首选通过该前缀无状态自动配置地址的时间。首选生命期过期后,节点通过该前缀自动配置的地址将被废止。节点不能使用被废止的地址建立新的连接,但是仍可以接收目的地址为被废止地址的报文。首选生命期必须小于或等于有效生命期。

抓包分析

image-20230925201517412

  1. 发送RS请求
  2. 配置了非抑制RA报文的交换机发送RA报文回应,报文中包含了几个option字段,如该报文中,包含了交换机的mac地址、ipv6地址前缀、MTU
若有多个交换机发送RA
主机根据接收到的RA消息中的路由器优先级(可在交换机上配置,分为high、low和medium,默认为medium),可以选择优先级最高的路由器作为默认网关。在路由器的优先级相同的情况下,遵循“先来先用”的原则,优先选择先接收到的RA消息对应的发送路由器作为默认网关
RS/RA报文字段含义

RS报文:

字段长度含义
Type1字节消息类型,此处值为133。
Code1字节该ICMPv6差错报文的始发者必须将该字段置为0,且接收端忽略该字段。
Checksum2字节用来在ICMPv6报文中检验数据和部分IPv6首部的完整性。
Reserved4字节此字段不使用。它必须由发送者初始化为0,接收者必须忽略它。
Options可变选项 源链路层地址:发送者的链路层地址,如果知道。如果Source Address是未指定地址,必须不 包括在内。否则,有地址的链路层上应当包括源链路层地址。 为TLV格式,各字段含义如下: Type: = 1,长度是1字节。 Length: 1字节,标识选项的长度(包括类型字段和长度字段)以8字节为单位计算。例如,IEEE802 地址的长度是1。Length值最少为1,0为非法值,须丢弃。 Link-Layer Address: 可变长度的链路层地址。此字段的内容和形式(包括字节和比特顺序)一般由描述IPv6在不同链路层上如何运行的特定文件中规定。

RA报文:

字段长度含义
Type1字节消息类型,此处值为134。
Code1字节该ICMPv6差错报文的始发者必须将该字段置为0,且接收端忽略该字段。
Checksum2字节用来在ICMPv6报文中检验数据和部分IPv6首部的完整性。
Cur Hop Limit1字节8位无符号整数。默认值应当放置在发出IP分组的IP首部的Hop Count字段中。 取0值意味着未(由该路由器)规定。
M1比特1位“管理地址配置”标记。当置1时,它指出地址可通过Dynamic Host Configuration协议获得。 如果M标记置1,则O标记为冗余,可以忽略,因为DHCPv6将返回所有可用配置信息。
O1比特1位“其他配置”标记。 当M=0且O=1时,指示其他配置信息可通过DHCPv6获得。例如,这类信息包括DNS相关信息或关于网络内其他服务器的信息。 如果M=0且O=0,指示没有信息可通过DHCPv6获得。
Reserved6比特6位未使用字段。它必须由发送者初始化为0,接收者必须忽略它。
Router Lifetime2字节16位无符号整数。与默认路由器关联的生存期,以秒为单位。最大值18.2小时。取0值的Lifetime指出路由器不是默认路由器并且不应当出现在默认路由器列表中。Router Lifetime仅适用于作为默认路由器的路由器应用;对包括在其他消息字段或选项中的信息不适用。需要对它们的信息规定时间限制的选项有它们自己的生存期字段。
Reachable Time4字节32位无符号整数。此时间以毫秒计,在收到可达性确认后节点假定该邻居是可到达的。它由Neighbor Unreachability Detection算法使用(参阅第7-3节)。此值为0意味着没有(由此路由器)作出规定。
Retrans Timer4字节32位无符号整数。重发的Neighbor Solicitation消息间隔时间,以毫秒计。由地址解析和Neighbor Unreachability Detection算法使用。此值为0意味着没有(由此路由器)作出规定。
Options可变选项
- Source link-layer address:源链路层地址,发出Router Advertisement的接口的链路层地址。仅在有地址的链路层上使用。路由器可以忽略此选项,以便能够使入境负载跨多个链路层地址共享。
为TLV格式,各字段含义如下:
- Type: = 1,长度是1字节。
- Length: 1字节,选项的长度(包括类型字段和长度字段),以8字节为单位计算。例如,IEEE802 地址的长度是1。
- Link-Layer Address: 可变长度的链路层地址。此字段的内容和形式(包括字节和比特顺序)一般由描述IPv6在不同链路层上如何运行的特定文件中规定。
- MTU:在有可变MTU的链路上应当按此发送流量(正如在描述特定链路类型上如何 运行IP的文件中规定的)。可以按此在其他链路上发送流量。
MTU格式:
image-20230925202435965
- Type = 5
- Length = 1
- Reserved: 此字段未使用。它必须被发送者初始化为0,接收者必须忽略它。
- MTU: 32位无符号整数。是为此链路推荐的MTU。
- Prefix Information:这些选项规定了前缀,这些前缀是on-link的,和/或被用于地址自动配置。路由器应当包括所有它的on-link前缀(链路本地前缀除外),所以多归属第主机有完整的前缀信息,这些前缀是关于主机们附着的链路的on-link目的地的。如果缺乏完整信息,当发送流量到它的邻居们时,多归属地主机或许不能够选择正确的出接口。 格式如下:
image-20230925202638508
- Type: = 3
- Length: = 4
- Prefix Length: 8位无符号整数。在合法前缀中领先比特的数目。其值范围是0到128。前缀长度字段为on-link确定提供必须的信息(当与前缀信息选项中L标记相结合时)。它也帮助实现地址自动配置,对此存在更多关于前缀长度的限制。
- L: 1位on-link标记。当置1时,指出此前缀可用于on-link确定。当没有置1时,通告对此前缀的on-link或off-link性质没有说明。换句话讲,如果L标记没有置1,主机不能推断出从该前缀引申出的地址是off-link。即,主机不能更新先前关于地址是on-link的指示。
- A: 1位自动地址配置标记。当置1时,指出此前缀可用于无状态地址自动配置
- Reserved1: 6位未使用字段。必须被发送者初始化为0,接收者必须忽略它。
- Valid Lifetime: 32位无符号整数。时间长度以秒为单位(相对于分组被发送的时间),在此时间内此前缀对于on-link确定来说是合法的。全1比特值(0xffffffff)表示无限。
- Preferred Lifetime: 32位无符号整数。时间长度以秒为单位(相对于分组被发送的时间)。在此时间 内经无状态地址自动配置,根据此前缀生成的地址保有优先权[ADDRCONF]。全1比特值(0xffffffff)表示无限。注意,此字段的值不能超过Valid Lifetime字段的值,以避免优先的地址不再合法。
- Reserved2: 此字段未使用。它必须被发送者初始化为0,接收者必须忽略它。
- Prefix: IP地址或IP地址的前缀。Prefix Length字段包含此前缀中有效领先比特的数目。在前缀中,在前缀长度之后的这些位被保留,并且必须被发送者初始化为0,接收者必须忽略它们。路由器不应当发送链路本地前缀的前缀选项,主机应当忽略这种前缀选项。

重定向

当主机启动时,它的路由表中可能只有一条到缺省网关的缺省路由。当满足一定的条件时,缺省网关会向源主机发送ICMPv6重定向消息,通知主机选择更好的下一跳进行后续报文的发送(与IPv4的ICMP重定向消息的功能相同)。重定向报文也承载在ICMPv6报文中,其Type字段值为137.

同时满足下列条件时,设备会发送ICMPv6重定向报文:

· 接收和转发数据报文的接口是同一接口;

· 被选择的路由本身没有被ICMPv6重定向报文创建或修改过;

· 被选择的路由不是设备的缺省路由;

· 被转发的IPv6数据报文中不包含路由扩展头。

参考文章

https://www.h3c.com/cn/d_201905/1185794_30005_0.htm#_Toc8828150

https://cshihong.github.io/2018/01/29/IPv6%E9%82%BB%E5%B1%85%E5%8F%91%E7%8E%B0%E5%8D%8F%E8%AE%AE/