邻居发现协议NDP(Neighbour Discover Protocol)
前言
众所周知,在IPv4的通信中,地址解析协议ARP(Address Resolution Protocol)起着至关重要的作用,但是也产生了不少的安全问题,利用ARP发起相关的攻击,造成一定的危害。在IPv6中一个新的协议替代了ARP协议,邻居发现协议NDP,它定义了使用ICMPv6报文实现地址解析,邻居不可达检测(NUD),重复地址检测(DAD),路由器发现以及重定向等功能。
参考:https://blog.csdn.net/qq_38265137/article/details/80466128
https://blog.csdn.net/frank_jb/article/details/49949483?utm_source=blogxgwz0
0x00 新名词信息
在ICMPv6学习中我们了解到了四个错误报文,和两个回应报文,并且也提及了,在NDP协议中定义了五个新的报文如下:
- RS(Router Solicitation,路由请求):ICMPv6类型:Type=133
- RA(Router Advertisment,路由器公告):ICMPv6类型:Type=134
- NS(Neighbor Solicitationh,领居请求):ICMPv6类型:Type=135
- NA(Neighbor Advertisement,邻居公告):ICMPv6类型:Type=136
- Redirect(重定向报文):ICMPv6类型:Type=137
前言中说到了在NDP协议中包含了许多新的知识点,这里总括一下:
- 地址解析:在IPv6中,地址解析是让两个希望通信的节点间相互确定目的节点的链路本地地址的方法。除了解析功能外,还是用那个NUD来维持邻居节点之间的可达性状态信息。
- 无状态地址配置:有状态地址配置的时候使用DHCPv6进行分配,而无状态地址配置是NDP中特有的地址自动配置机制,包括路由发现,接口ID自动生成,重复地址检测,无状态地址配置等机制,链路上的节点可以自动获取IPv6全球单播地址。
- 重定向:直白的说就是找到了一条更好的路径去传输报文,则路由就会通知节点进行相关配置的变更。
以上涉及的一些新名词就是本篇要着重介绍的知识。
0x01 地址解析
IPv4中ARP报文直接被封装在以太网报文中,以太网协议的类型是0x0806,普遍认为ARP定位为2.5层的协议。NDP本身基于ICMPv6实现,其所使用的报文都是被封装在ICMPv6报文中,以太网协类型为0x86DD,即IPv6报文,所以一般NDP被看成第三层协议。与链路层协议无关的益处有以下几点:
1. 加强了地址解析协议与二层链路的独立性,在链路层不同的链路层协议都可以使用相同的地址解析协议。
2. 增强了安全性,利用第三层标准的安全认证机制可以防止ARP的相关攻击。
3. 使用了组播方式发送请求报文,减少了二层网路的性能压力。
在地址解析过程中所需要的ICMPv6报文为:NS以及NA,如下图所示分别是NS及NA的报文格式:
NS:Type字段值为135,Code字段值为0,在地址解析中作业可类比IPv4的ARP请求报文。校验和字段包含了ICMPv6校验和值,发送端必须将保留字段设置为0,接受段忽略此字段。
目标地址字段包含了请求目标的地址。这个字段一定不能包含多播地址
源链路层地址选项是目前为邻居请求报文定义的唯一一个选项。在多播发送邻居请求报文时,发送端必须包含其链路层地址。如果源地址是不确定地址,则必须忽略此选项。
NA:Type字段值为136,Code字段值为0,在地址解析中作业可类比IPv4的ARP应答报文。校验和字段包含了ICMPv6校验和值,发送端必须将保留字段设置为0,接受段忽略此字段
- R:”路由器(Router)标志”,当置1时候,就说明发送者是路由器,R字段由NUD(地址不可达检测)使用,用于检测改变为主机的路由器。
- S:”请求(Solicited)标志”,这个标志说明收到邻居广告报文是否是对广告目的地址指定的节点发送的请求报文的响应,但是在带有多播目的地址的邻居广告报文中必须将S标志清楚。
- O:”覆盖(Override)标志”:邻居广告报文中设置O字段时,如果缓存了发送端广告报文的链路层地址,接收端就会对这个缓存条目进行跟新。如果缓存的条目不存在,接收端就会创建包含发送端链路层地址的条目。但是不能为任播地址配置O字段。
目标地址字段中包含邻居请求报文目标地址的字段的值。
目标链路层地址选项是为邻居广告报文定义的唯一一个选项。发送端在多播发送邻居广告报文时必须包含其链路层地址。接收端必须不认识的和其他认识的选项都忽略掉。
使用网上的一个例子帮助理解一下解析的过程:
- HostA想要得知HostB的链路层地址,于是向B发送了一个NS报文,相关信息为Type=135 源地址为A的IPv6地址,目的地址为B请求节点组播地址,并在NS报文的Options字段中加入了HostA的链路层地址。
- HostBs收到了NS报文后,就回应NA报文,相关信息为Type=136,源地址为B的IPv6地址,目的地址为A的IPv6地址(使用NS报文选项字段的A的链路层地址进行单播),并在NA报文的Options字段中加入了HostB的链路层地址。
- A与B之间经过上述的包交互,便可以实现相互通信,这样就完成了一个地址解析的过程。
0x02 邻居不可达检测
NUD(Neighbour Unreachable Detection,邻居不可达检测)是一个新的机制。用来保持对邻居可达性状态的检测。
邻居缓存表中定义了6种状态:
- INCOMPLETE(未完成状态):表示对邻居链路层地址的地址解析正在进行中,但邻居链路层地址尚未确定。
- REACHABLE(可达状态):表示地址解析成功结束,该邻居可达。
- STALE(失效状态):表示可达时间耗尽,未确定邻居是否可达。
- DELAY(延迟状态):表示未确定邻居是否可达。此状态的邻居就不再认为是可达的了。
- PROBE(探测状态):节点会周期性地向处于PROBE状态的邻居持续发送NS报文。
- EMPTY(空闲状态):表示节点上没有相关邻接点的邻居缓存表项。
如上图所示,各状态之间可以实现相互转换:
- 在EMPTY状态时,如果有报文发送给邻接节点,那么就在本地邻居缓存表建立该邻接节点的表项,邻居的可达性状态变为INCOMPLETE,同时向邻接节点以组播方式发送NS报文。
- 节点接收到了邻居回应的单播NA报文后,也就意味着地址解析成功,邻居可达性状态变为REACHABLE,否则变为Empty,即为删除表项。
- 处于REACHABLE状态的表项,如果在默认(30s)时间内未接收到关于该邻居的”可达性证实信息”,则进入STALE状态。另外,如果该节点收到邻居节点发出的非S置位NA报文,并且链路层地址发生变化,也会进入STALE状态。
- 在处于STALE状态的邻居产生流量时,节点要开始进行可达性探测。节点会将探测分组的传输延时一段时间,以便给高层协议一个提供邻居可达性信息的机会。这段延迟使得邻居的可达性状态转换为DELAY状态。
- 在DELAY状态下,如果在默认(5s)时间内未收到关于该邻居的”可达性正式信息”,则该表项进入PROBE状态。
- 在PROBE状态下,发送方每隔一段时间(1s)发送单播NS,发送固定次数(3)次后,若收到应答NA,则状态变为Reachable,否则变为Empty,即为删除表项。
0x03 无状态地址分配
开头就已经提及,在IPv6下存在有状态和无状态的配置机制,前者依靠DHCPv6,后者通过NDP,在无状态地址自动配置中,主机通过接受链路上的路由器发出的RA消息,结合接口的标识符而生成一个全球单播地址。
重复地址检测(DAD)
Duplicate Address Detect是在某个接口使用IPv6单播地址之前进行的。保证地址的唯一性。尤其是在地址自动配置时显得尤为重要。避免地址重复。
一个IPv6单播地址进行DAD是称之为主机的试验地址。接口在执行DAD时还无法使用这个地址进行通信,但是仍然会加入两个组播组:ALL-NODES组播组和试验地址对用的Solicited-Node组播组。
如上所示就是DAD的大致过程,A的IPv6地址FC00::1是新配置的地址,所以向FC00::1的组播组发送一个请求,由于FC00::1并未正式指定,所以NS报文的src只能是未指定状态。当B接收到NS报文后会给以回复:
- B的试验地址也包含FC00::1,则B会放弃使用该地址为接口地址,并且不会发送NA报文。
- B发现FC00::1是一个正常使用的地址,则会发送NA报文通知A改地址已被使用,A上该试验地址不生效,被标志位duplicated(被复制)状态
路由发现
路由发现主要通过以下RA以及RS两种报文进行交互,以下是两种报文的格式:
- RS(路由请求报文)的类型字段值为133,代码字段值为0,校验和字段包含了ICMPv6校验和值。发送端必须将保留字段设置为0,接收端忽略此字段。
- 有一个唯一的选项是源链路层地址选项,如果发送端知道他的链路层地址,就会在路由器请求报文中包含带有这条信息的源链路层地址选项。如果源地址是不确定地址则忽略此选项。
- 同时接收端要忽略那些不认识的和其他认识的选项,在这儿不产生任何错误报文,只会对报文继续进行处理。
- RA(路由广告报文)的类型字段值为134,代码字段值为0,校验和字段包含了ICMPv6校验和值。发送端必须将保留字段设置为0,接收端忽略此字段。
- 当前的跳数限制字段包含的是要放入所有输出分组的IPv6首部的跳数限制字段的默认值。如果值为0则说明路由器没有说明跳数限制的配置。
- M字段为”管理的地址配置”标志。M的取值标志着地址配置是否可以使用DHCPv6。
- O字段为”其他有状态配置”标志。O的取值标志着是否可以使用DHCPv6的无状态子集来获取不与特定地址相关的配置信息,例如DNS递归名字服务器的IPv6地址。
- 路由器寿命字段是一个16比特的无符号整数,说明了路由器要当多久的默认路由。这个值是以秒为单位,最大值为18.2小时。值为0说明传输路由器不是默认路由。这种情况下不会把路由器作为向链外目的地发送分组的下一跳候选者。
- 可达时间字段是一个32比特的无符号整数,说明了下一个节点从与通信的邻居收到可达性证实之后,认为这个邻居在多长时间内是可达的。这个值以毫秒为单位。当可达时间到期,但却没有收到相关可达性证实,节点就开始进行NUD。值为0说明广告路由没有指定这个参数。
- 重传定时器字段是一个32比特的无符号整数,以毫秒为单位,说明了NUD以及地址解析算法中分组传输的间隔。值为0说明广告路由没有指定这个参数。
- 一共存在有三个选项:源链路层地址选项,MTU选项以及前缀信息。源链路层地址:路由器可在选项中设置发送接口的链路层地址,这样接受主机在通过路由器发送分组时候就无需执行链路层地址解析了。MTU:通过MTU选项为那些缺乏良好定义的MTU长度的链路提供统一的MTU值。
注:当主机所在的链路中存在多个设备时,需要根据报文的目的地址选择转发设备。在这种情况下设备通过发布默认路由优先级和特定路由信息给主机。
如上图所示,是优化过的RA报文,其中H字段是为了支持IPv6移动性定义的。
优先字段为一个2比特的路由器优先字段,说明了默认路由间的优先级情况:
编码 | 优先级 |
---|---|
01 | 高 |
00 | 中 |
11 | 低 |
10 | 保留 |
当主机收到上述的RA报文后,会跟新自己的默认路由表,优先选择链路上优先级最高的设备发送报文,如果设备故障,继续根据优先级选择其他设备。但是如果接受到RA报文中显示路由的寿命为0,那么直接忽略优先级。
地址自动配置
NDP进行无状态自动配置包含两个阶段:链路本地地址的配置以及全球单播地址的配置。
当一个接口启用时,主机会首先根据本地前缀FE80::/64和EUI-64接口标识符,为该接口生成一个链路本地地址,如果在后续的DAD中发现地址冲突,则必须对接口手动配置本地链路地址,否则接口不能使用。而且,一个链路本地地址的优先时间和有效时间是无限的。
对于主机全球单播地址的配置有如下几步:
- 主机配置有链路本地地址后,发送RS报文请求发现路由。
- 路由器接收到RS后发送单播RA,RA中包含有无状态地址配置的前缀信息,同时路由器也会周期性地发送组播RA报文。
- 主机节点收到RA后,根据前缀信息和配置信息生成一个临时的全球淡泊地址。同时使用DAD发送NS以确保地址唯一性。
- 链路上其他节点接收DAD的NS报文后若无用户使用改地址则丢弃报文,否则应答NS发送NA报文。
- 节点没有收到回应报文,则说明地址唯一,则使用该临时地址初始化接口,地址有效化。
- 地址自动配置完成,路由器可自动进行NUD以周期性发送NS方法确定可达性。
重定向
当网关设备发现其他更优网关设备来转发报文,它就会发送重定向保卫通知报文的发送者,让报文发送者选择另一个网关设备。重定向报文也是封装ICMPv6报文中的,其报文格式如下图所示:
- 重定向报文的类型字段值为137,代码字段值为0,校验和字段包含了ICMPv6校验和值。发送端必须将保留字段设置为0,接收端忽略此字段。
- 如果有更好的第一跳路由器,或者目的地是一个在链的邻居,路由器就会发送重定向报文。在第一种情况下,目标地址字段中包含了更好的第一跳路由器的链路本地地址:在第二种情况下,目标地址字段的值与目的地址字段的值相同。
- 目的地址字段中包含了分组最终目的地的地址。
- 重定向报文有两种可能的选项,这两个选项是目标链路层地址选项和重定向首部选项。目标链路层地址选项中包含了目标地址的链路层地址。重定向首部选项在整个重定向分组不超过最小链路MTU的前提下,包含了尽可能多的触发重定向的那个原始IPv6分组。
如上图所示例子,HostA想与HostB通信,A的默认网关设备为RouterA,当HostA将报文发送给HostB时会被送到RouterA,RouterA接受到报文经过检测后会发现,HostA将报文直接发送给RouterB会更好,于是便发送重定位报文,报文的中指定更好的下一跳地址为RouterB,目标地址为HostB。HostA接收到重定向报文后会在路由表中加上RouterB为主机路由,发送给HostB的报文就直接发送给RouterB而不再经过RouterA。
注:只有如下情况,设备会向报文发送者发送重定向报文:
- 报文目的地址不是一个组播地址。
- 报文并非通过路由转发给设备
- 经过路由计算后,路由的下一跳接口是接受报文的接口。
- 设备发现报文的最佳下一跳IP地址和报文的源IP地址处于同一网段。
- 设备检查报文的源地址,发现自身的邻居表项中有用该地址作为全球单播地址或链路本地地址的邻居存在。