IPv6学习(三)

NDP协议(上)之地址解析,无状态配置

Posted by 婷 on April 6, 2024 本文总阅读量

简介

NDP,英文全程为Neighbor Discovery Protocol,也即邻居发现协议,由RFC2461定义。NDP协议实现的以下功能有

image-20240404114023457

NDP协议使用ICMPv6报文来实现以上功能,其中为NDP定义的ICMPv6消息如下

image-20240404171244612

这篇文章先讲地址解析跟无状态配置两部分。

地址解析

地址解析主要用到邻居请求NS报文跟邻居通告NA报文。通过这两种报文来解析三层地址对应的链路层地址,替代IPv4中的ARP广播。

如下图所示主机A需要使用目的地址fec0::1:0:0:1:b来访问主机B,初始情况下A没有BIPv6地址对应的MAC地址,因此需要借助NDP协议来获取fec0::1:0:0:1:b地址对应的MAC地址。

image-20240404160206333

第一步是A发送NS报文,目的IPB的被请求节点组组播地址,目的MAC则是B的被请求节点组地址对应的组播MAC地址,同时报文中携带A自己的MAC地址(Source Link-layer Address)。

第二步是B发送NA报文,B在地址生成的时候就会加入自己的被请求节点组播组,这样他就能侦听发送到这个组播组的报文,当A发送NS报文的时候,B就能收到,并回复NA报文,报文中则会携带自己的MAC地址(Target Link-layer Address)。

参照上图,基本可以比较明确。

做个实验抓包看,wsltap0ipv6地址是fd00::aqemuenp0s1ipv6地址是fd00::b。现在wsltap0地址fd00::aping这个qemuenp0s1地址fd00::b

这是qemu中的配置,此时邻居表中没有wslfd00::a地址对应的MAC地址

image-20240404121727953

同理,此时wsl这边也没有

image-20240404121817804

接着fd00::aping地址fd00:b,通了之后查看邻居表

image-20240404121924896

抓包链接

image-20240404160443298

wsl发出的NS报文(Type = 135,Code = 0

image-20240404161917221

NS报文

NS报文格式如下所示

image-20240404170357192

qemu回复的NA报文

image-20240404164856037

NA报文

NA报文的格式如下(Type = 136,Code = 0

image-20240404170334888

其中第四点Flags

  • Router Flag:表示消息发送者是否为路由器,是路由器则置1
  • Solicited Flag:该NA消息是否为响应某个邻居请求的消息,是则置1
  • Overide Flag:该NA消息是否可以覆盖已有的条目 ,是则置1

无状态配置

无状态配置在RFC2462中定义。这里的配置不止是指地址的配置,还有DNS,路由器等。

前面的文章介绍过单播地址的无状态配置方法。

前缀公告

前缀公告,也即路由公告 ,主机从RA报文中,获取路由器分配的前缀,简单流程如下。

image-20240404230904199

一般前缀的获取会有两种情况

  • 第一种如上图所示,路由器打开RA消息抑制功能,主机发送RS报文,路由器收到RS报文后,回复RA报文
  • 第二种就是主机不发送RS报文,但是路由器周期性的发送RA报文,如果Linux主机打开的accept_ra选项跟autoconf选项,则会自动根据RA中的路由前缀自行构造IPv6地址

这里就用之前文章的抓包的文件来分析RS跟RA报文了,文件链接

image-test

RS报文

RS报文如下,在RFC2461定义 (Type = 133,Code = 0

image-20240404231342402

可以看到RS的源地址是linklocal地址,目的地址也是链路上的所有组播路由器

image-20240404231919956

RFC2461中提到对RS报文可以暂时忽略Reserved部分

Future versions of this protocol may define new option types. Receivers MUST silently ignore any options they do not recognize and continue processing the message.

RA报文

RA报文如下,在RFC2461定义,(Type = 134,Code = 0

image-20240404231418771

RA报文可以携带的Options信息种类则是非常的多,除了图中的地址前缀 ,DNS Server信息,还可以用于PMTU中传递MTU相关信息。

image-20240404233143049

hop limit

图中RA报文的hoplimit64,那么接收到此RA通告前缀构造地址的的PC,之后发出的报文都是64hoplimit

image-20240405231329343

flags

Mbit

M位默认为0,该标志指示主机该使用哪种自动配置方式获取IPv6单播地址

  • 0时,收到该RA消息的主机使用消息中包含的IPv6前缀用于无状态地址自动配置
  • 1时,收到该RA消息的主机采用有状态自动配置,也就是DHCPv6的方式来获取IPv6地址

image-20240405231551482

Obit

Obit默认为0,该标志指示主机使用何种方式来配置除了IPv6地址以外的其他配置信息

  • 0表示,除了IPv6地址以外的其他参数,比如DNS Server,主机不应该使用有状态自动配置机制来配置
  • 1表示,除了IPv6地址以外的其他参数,主机需要使用DHCPv6来配置,比如DNS

image-20240405235358565

Mbit跟Obit结合小结

image-20240406205819685

根据参考链接,下面是一些设备在Obit = 0的测试结果,说明不同主机主机对Mbit的处理可能不同

  • 在思科的设备上,将M比特置0(默认就是0),RA消息会携带IPv6前缀信息,Win7主机收到该RA消息后,使用消息内的前缀信息构建IPv6地址,但是不会发送DHCPv6 Solicitation消息去请求地址信息
  • 在思科的设备上,将M比特置1,RA消息依然会携带IPv6前缀信息,而Win7主机收到该RA消息后,依然会使用RA消息中的IPv6前缀构建IPv6单播地址,同时主机发送DHCPv6 Solicitation消息去请求地址信息
  • 在华为的设备上,将M比特置0(默认就是0),RA消息会携带IPv6前缀信息,Win7主机收到该RA消息后,使用消息内的前缀信息构建IPv6地址,但是不会发送DHCPv6 Solicitation消息去请求地址信息
  • 在华为的设备上,将M比特置1 ,则该接口发送的RA消息将不包含任何IPv6前缀,自然主机也就无法使用RA中的前缀构造IPv6地址。当主机收到M=1的RA消息,将会发送DHCPv6 Solicitation消息去请求IPv6地址

以上测试,思科平台采用C3640-IK9O3S-M。同时注意上述测试O比特始终为0。总结一下,其实M比特对于windows7而言,就是一个是否使用DHCPv6获取IPv6地址的开关,如果为0,则否,如果为1,则是,而且为1时并不代表就不能使用无状态自动配置来获取地址。

router time

单位为,主机将路由器视为缺省路由器的时间,该计时器到计数为0时,该路由器将不会出现在主机的缺省网关列表中,不过从我做的实验来看,主机收到RA报文,不一定会那发送RA报文的路由器当成自己的默认网关

image-20240405231925283

不过这里就会显示一个proto ra的打印(我也不是特别清楚)

image-20240406124918376

options:prefix

RFC2461定义

image-20240406000204519

Lbit

L比特位,默认为1,为1时表示RA消息中的该前缀是分配给本地链路的,因此,向包含这个指定前缀的地址发送数据的节点认为目的地是本地链路可达的。

image-20240406123732746

Abit

A比特位,默认为1

  • 1时,指示本地链路的主机可以使用该前缀进行无状态自动配置
  • 0时,表示该前缀不能用于无状态自动配置

image-20240406123859397

valid && preffered lifetime

IPv6前缀信息中有两个时间,分别是valid lifetimepreffered lifetime

image-20240406124143531

其关系如下,他表示的是一个IPv6地址的一个生命周期。当地址处于deprecated状态,地址不能主动的发起连接只能是被动的接受连接,这也是为了保证上层应用而设计的,但是过了valid lifetime时间地址就变为invalid,这 时任何连接就会down掉。

image-20240406124117594

可以使用ip addr show查看IPv6地址的这两个时间点,这里特地sleep 5s来查看时间差

image-20240406124844081

DAD

  • Duplicate Address Detection地址重复检测机制
  • 只要是获得了一个IPv6地址或者是启动一个IPv6接口(link down and link up),无论是有状态或者是无状态自动配置的,都需要先经过DAD,保证在链路上的唯一性(就算是Linklocal地址也要做DAD检测)
  • DAD使用NSNA消息实现

工作流程如下

image-20240406133722487

我们的2000::1这个时候还没通过DAD检测,实际上是一个tentative地址(但实际上主机A还是会加入这个2000::1对应的被请求节点多播组)。所以源IP::,也就是1280,作为NS消息的源IP,而目的IP则是2000::1对应的被请求节点组播地址

image-20240406134036612

如果1秒后没有检测到冲突,A就会发送一个NA消息,宣告大家我将正式使用这个IPv6地址。如果有其他设备已经使用了这个地址,就会发送一个NA消息,这样主机就知道这个地址已经有人再用了,就会放弃这个地址。如下所示。其实这个过程就很像IPv4中的ARP Probe

image-20240406134351102

内核接口/proc/sys/net/ipv6/conf/xxx/dad_transmits用来表示需要dad检测的次数,如果为0则表示不进行dad检测

image-20240406143722209

抓包文件链接上传于此

image-20240406142831949

image-20240406142919018

DAD NS报文如下

image-20240406143004249

DAD NA报文如下

image-20240406143054424

当然前面有提到,一开始当地址为tentative状态时,但还是会加入相应的多播组。如果碰到如下两台设备都要做DAD检测,会是怎样的结果呢?

image-20240406143143918

  • 若2个节点配置相同地址,同时作重复地址检测时,该地址处于tentative状态,当一方收到对方发出的DAD NS,则接收方将不启用该地址
  • 一种极端的情况,如果同时收到NS报文,则两端都放弃改地址

前缀重编址

RA报文中的前缀是有valid lifetimepreffered lifetime的,而前缀重编址,让新老前缀平滑过渡,则是通过利用IPv6地址生存周期,把preffered lifetime设置为0,使地址处于deprecated状态,地址不能主动的发起连接只能是被动的接受连接。而当valid lifetime过去之后,地址变为invalid则不可用了。

这样灵活的设置地址生存时间,实现新老前缀平滑过渡,无需在主机终端上消耗大量的手工劳动重新配置地址。

image-20240406193537426

这边可以用radvd去做这个前缀过渡(图中的AdvSendAdvert需要改为off,不然为on的话,radvd会一直发送RA报文)

image-20240406194759029

不过我发现地址处于deprecated状态依旧可以进行通信?

image-20240406194549933

参考链接