简介

ICMPv6是IPv6的基础协议之一,协议类型号(即IPv6 Next Header)为58。
除了提供基本的检测网络连通性功能外,还提供了邻居发现(NDP)、无状态地址配置(SLAAC)、
重复地址检测(DAD)、PMTU等新功能。

IPv6邻居发现协议 - NDP概述

所使用的ICMPv6报文

RS (Router Solicitation) 路由器请求报文
RA (Router Advertisement) 路由器通告报文
NS(Neighbor Solicitation) 邻居请求报文
NA (Neighbor Advertisement) 邻居通告报文

地址解析

IPv6的地址解析,不再使用ARP。也不再使用广播发送报文。

地址解析在网络层完成,这样可以针对不同的链路层协议采用相同的地址解析协议。(然而现在是以太网的天下)通过ICMPv6(类型135的NS及类型136的NA报文)来实现地址解析。

NS报文发送使用组播的方式,报文的目的IPv6地址为被请求的IPv6地址对应的“被请求节点组播地址”,报文的目的MAC地址为组播MAC。(交换机对于组播MAC地址也会泛洪。)

采用组播的方式发送NS消息相比于广播的方式更加的高效,也减少了对其他节点的影响和对二层网络的性能压力。(网卡会过滤不需要的组播帧,减少上一层的负担)

可以使用三层的安全机制进行认证(例如IPSec),避免地址解析攻击。(一般默认不开启)

NS和NA报文

地址解析过程中使用了两种ICMPv6报文:邻居请求(Neighbor Solicitation)和邻居通告(Neighbor Advertisement)。

  • 邻居请求 Neighbor Solicitation
    • ICMP的Type为135,Code为0;
    • Target Address是需要解析的IPv6地址,因此该处不准出现组播地址。
    • 邻居请求发送者的链路层地址会被放在Options字段中。(感觉没有必要,因为源MAC地址已经是NS发送者的。)
  • 邻居通告 Neighbor Advertisement
    • ICMP Type为136,Code为0;
    • R标志(Router flag)表示发送者是否为路由器,如果1则表示是;
    • S标志(Solicited flag)表示发送邻居通告是否是响应某个邻居请求,如果1则表示是;
    • O标志(Overide flag)表示邻居通告中的消息是否覆盖已有的条目信息,如果1则表示是;
    • Traget Address表示所携带的链路层地址对应的IPv6地址。
    • 被请求的链路层地址被放在Options字段中,其格式仍然采用TLV格式,具体可以参考RFC2463。

地址解析过程

如上图

  • 假设PC想要解析R1的2001::2这个地址对应的MAC地址,详细过程如下:
    • PC将发送一个NS报文达到这个目的。这个NS报文的源地址是2001::1,目的地址则是2001::2对应的被请求节点组播地址。

    • R1收到此NS报文之后,获取其中的源IPv6地址R1接收此NS报文,根据报文内的源IPv6地址和源MAC,记录下PC这个邻居,同时根据自身的IPv6和MAC,回复单播NA报文。和源MAC。这样双方都可以建立一条关于对方的邻居信息表项。

邻居状态机

通过邻居或到达邻居的通信,会因各种原因而中断,包括硬件故障、接口卡的热插入等。如果目的地失效,则恢复是不可能的,通信失败;如果路径失效,则恢复是可能的。 因此节点需要维护一张邻居表,每个邻居都有相应的状态,状态之间可以迁移。(IPv4 的ARP仅靠倒计时去维护)

RFC中定义了5种邻居状态,分别是:未完成(Incomplete)、可达(Reachable)、陈旧(Stale)、延迟(Delay)、探查(Probe)。

• R1先发送NS报文,并生成缓存条目,此时,邻居状态为Incomplete。
• 若收到R2回复的NA报文,则邻居状态由Incomplete变为Reachable,
否则固定时间后邻居状态由Incomplete变为Empty。
• 经过邻居可达时间(默认30s),邻居状态由Reachable变为Stale,即
未知是否可达。
• 如果在Reachable状态,R1收到R2的非请求NA报文,且其中携带的R2的链路
层地址和表项中不同,则邻居状态马上变为Stale。
• 在Stale状态若R1要向R2发送数据,则邻居状态由Stale变为Delay,并
发送NS请求。
• 在经过一段固定时间后,邻居状态由Delay变为Probe,其间若有NA应
答,则邻居状态由Delay变为Reachable。
• 在Probe状态,R1每隔一定时间间隔(默认1s)发送单播NS,发送固定
次数后,有应答则邻居状态变为Reachable,否则邻居状态变为Empty。

重复地址检测DAD

当设备获取到IPv6地址后,一定会使用ICMPv6报文进行DAD。且当DAD通过之后,才会使用该地址。(无论通过那种方法获取)

  • 假设R1为已在线设备,IPv6地址为2001::FFFF/64。PC上线之后,也配置了相同的IPv6地址,在正式使用这个地址之前,PC会对此地址做DAD,过程如下:
    • PC向链路上以组播的方式发送一个NS报文,该NS的源IPv6地址为“::”,目的IPv6地址为要进行DAD的2001::FFFF对应的被请求节点组播地址,也就是FF02::1:FF00:FFFF。这个NS里包含着要做DAD的目标地址2001::FFFF。
    • 链路上的节点都会收到这个组播的NS报文,没有配置2001::FFFF的节点接口由于没有加入该地址对应的被请求节点组播组,因此在收到这个NS的时候默默丢弃。而R1在收到这个NS后,由于它的接口配置了2001::FFFF地址,因此接口会加入组播组FF02::1:FF00:FFFF,而此刻所收到的报文又是以该地址为目的地址,因此它会解析该报文,它发现对方进行DAD的目标地址与自己本地接口地址相同,于是立即回送一个NA报文,该报文的目的地址是FF02::1,也就是所有节点组播地址,同时在报文内写入目标地址2001::FFFF,以及自己接口的MAC地址。
    • 当PC收到这个NA后,它就知道2001::FFFF在链路上已经有人在用了,因此将该地址标记为Duplicate(重复的),该地址将不能用于通信。若未收到NA报文,则PC判断这个IPv6地址可以用,DAD机制有点类似于IPv4中的免费ARP检测重复地址。

IPv6的无状态地址配置

主机根据RA中的地址前缀,并结合本地生成的64 bit接口标识(例如EUI-64),生成单播地址。
仅可以获得IPv6地址信息,(较新标准可以获取DNS)无法获得NIS、SNTP服务器等参数,需要配合DHCPv6或者手工配置来获取其他配置信息。

Path MTU

在IPv4中,报文如果过大,必须要分片进行发送,所以在每个节点发送报文之前,设备都会根据发送接口的最大传输单元MTU(Maximum Transmission Unit)来对报文进行分片。但是在IPv6中,为了减少中间转发设备的处理压力,中间转发设备不对IPv6报文进行分片,报文的分片将在源节点进行。当中间转发设备的接口收到一个报文后,如果发现报文长度比转发接口的MTU值大,则会将其丢弃;同时将转发接口的MTU值通过ICMPv6报文的“Packet Too Big”消息发给源端主机,源端主机以该值重新发送IPv6报文,这样带来了额外流量开销。PMTU发现协议可以动态发现整条传输路径上各链路的MTU值,减少由于重传带来的额外流量开销。

PMTU协议是通过ICMPv6的Packet Too Big报文来完成的。首先源节点假设PMTU就是其出接口的MTU,发出一个试探性的报文,当转发路径上存在一个小于当前假设的PMTU时,转发设备就会向源节点发送Packet Too Big报文,并且携带自己的MTU值,此后源节点将PMTU的假设值更改为新收到的MTU值继续发送报文。如此反复,直到报文到达目的地之后,源节点就能知道到达目的地的PMTU了。

如上图,整条传输路径需要通过4条链路,每条链路的MTU分别是1500、1500、1400、1300,当源节点发送一个分片报文的时候,首先按照PMTU为1500进行分片并发送分片报文,当到达MTU为1400的出接口时,设备返回Packet Too Big错误,同时携带MTU值为1400的信息。
源节点接收到之后会将报文重新按照PMTU为1400进行分片并再次发送一个分片报文,当分片报文到达MTU值为1300的出接口时,同样返回Packet Too Big错误,携带MTU值为1300的信息。之后源节点重新按照PMTU为1300进行分片并发送分片报文,最终到达目的地,这样就找到了该路径的PMTU。

PS:IPv6 要求链路层最低MTU为 1280。

路由重定向

重定向是指网关设备发现报文从其它网关设备转发更优,它就会发送重定向报文告知报文
的发送者,让报文发送者选择另一个网关设备。

1、PC1希望发送报文到服务器,于是根据配置的默认网关地址向网关R2发送报文。

2、网关R2收到报文后,检查报文信息,发现报文应该 转发到与PC1在同一网段的另一个网关设备R1,此 转发路径是更优的路径,于是R2会向PC1发送一个 重定向消息,通知PC1去往服务器的报文应直接发给R1。
3、PC1收到重定向消息后,会向R1发送报文,R1再将该报文转发至服务器。