NDP(Neighbor Discovery Protocol,邻居发现协议)是 IPv6 网络中最核心的控制协议之一。
它负责的功能相当于 IPv4 中 ARP + ICMP Router Discovery + ICMP Redirect + 部分 DHCP 功能 的综合体。
一、NDP 是什么
定义:
NDP 是基于 ICMPv6 的一组消息协议,用于:
- 邻居(主机/路由器)发现与地址解析
- 路由器发现(找网关)
- 前缀与参数自动配置(无状态自动配置 SLAAC)
- 地址冲突检测(DAD)
- 邻居可达性检测(NUD)
- 重定向(Redirect)
📘 标准定义:
RFC 4861(Neighbor Discovery for IP version 6)
二、NDP 的核心思想
在 IPv6 中,所有“邻居层面”的通信控制都通过 ICMPv6 完成。
它用组播代替广播,用更智能的机制取代 ARP。
IPv4 的做法:
- ARP 广播解析 MAC 地址
- ICMP Router Discovery 寻找网关
- ICMP Redirect 由路由器引导更优路径
IPv6 的做法(全部走 ICMPv6):
- Neighbor Solicitation (NS):请求邻居的 MAC 地址
- Neighbor Advertisement (NA):邻居应答
- Router Solicitation (RS):请求路由器信息
- Router Advertisement (RA):路由器通告前缀、MTU、网关等
- Redirect:路由器重定向主机使用更优路径
三、NDP 五种核心报文类型
| 名称 | ICMPv6 Type | 方向 | 功能 |
|---|---|---|---|
| Router Solicitation (RS) | 133 | 主机 → 路由器 | 主机请求网络参数(谁是网关?) |
| Router Advertisement (RA) | 134 | 路由器 → 主机 | 路由器通告前缀、网关、MTU 等信息 |
| Neighbor Solicitation (NS) | 135 | 主机 ↔ 主机/路由器 | 地址解析 + 地址冲突检测 |
| Neighbor Advertisement (NA) | 136 | 主机 ↔ 主机/路由器 | 响应 NS 或通告自身存在 |
| Redirect | 137 | 路由器 → 主机 | 通知主机更优的下一跳地址 |
NS/NA
| 场景 | 使用的报文 | 功能说明 |
|---|---|---|
| 地址解析 | NS → NA | 解析 IPv6 到 MAC(类似 ARP) |
| 地址冲突检测 (DAD) | NS | 检查自己要用的地址是否被占用 |
| 邻居可达性检测 (NUD) | NS ↔ NA | 定期检测邻居是否在线 |
| 主动通告更新 | NA | 告诉别人我的 MAC 改变了 |
RS/RA
| 场景 | 使用的报文 | 功能说明 |
|---|---|---|
| 路由器发现 (Router Discovery) | RS → RA | 主机请求网络中可用的路由器,路由器回应自身信息(默认网关、前缀、MTU 等) |
| 自动地址配置 (SLAAC) | RA | 路由器通过 Prefix Information 通告前缀,主机据此前缀自动生成 IPv6 地址 |
| DHCPv6 协调 (M/O Flags) | RA | 告知主机是否应使用 DHCPv6 获取地址(M)或其他配置(O) |
| 默认路由通告 | RA | 告诉主机该路由器可作为默认网关(Router Lifetime > 0) |
| 链路参数通告 | RA | 通告链路层 MTU、DNS 服务器(RDNSS)、域名信息等 |
| 网络状态维护(周期广播) | RA | 路由器定期发送 RA 保持主机的配置信息最新,检测网络仍然可用 |
| 网络切换检测 | RS → RA | 主机检测到接口状态变化后发送 RS,请求立即获取新的网络参数 |
Redirect
Redirect(Type 137)由路由器发给主机,告诉主机“对于某个目的地址/前缀,你应该把下一跳改为这个更优的目标(target)”,以便优化转发路径或修正错误的下一跳。
触发条件(路由器为什么会发送 Redirect)
路由器在转发来自主机的一个包并且满足下列情形之一时,会向该主机发送 Redirect(RFC 4861 要求):
- 路由器在接收到主机 A 发给目的 D 的数据包并准备转发时,路由器发现 目标 D 在本链路上且可以直接到达(through a neighbor),于是它告诉主机 A 直接把包发给目标或另一个邻居(以避免多跳转发);
- 路由器发现主机 A 使用了一个次优的下一跳(例如 A 把包发给路由器,但路由器知道更合适的下一跳是链路上某个邻居或另一路由器),于是发送 Redirect 指定新的下一跳;
- 路由器能同时提供 Target 的链路层地址(Option),以便主机立刻更新邻居缓存。 额外注意:
- Redirect 必须来自路由器(源地址通常是路由器的 link-local 地址)。
- 路由器通常只在“有益的优化”场景发送,而非随意广播;随意发送会带来安全风险。
主机收到后应做的事情(行为规范)
当主机收到 Redirect,应按 RFC 要求做检查,并相应更新其缓存/路由:
- 校验来源:确保报文的源地址是链路本地地址(link-local)并且该节点是路由器(按本地路由器缓存或接收到过 RA);若校验失败应丢弃(防止伪造)。
- 检查 Redirect 内容合理性:目标地址(Target)应是链路上可到达的地址(on-link),或满足 RFC 的其它验证(Redirected Header 对比)。
- 更新邻居缓存:如果报文携带 Target Link-Layer Address option,主机要用它更新对 Target 的 IPv6→MAC 映射(邻居缓存)。
- 更新路由/下一跳:主机为受影响的目的(Destination Address)建立/修改一条更优的下一跳条目(将数据包发给 Target 而不是原来的下一跳);这通常在本地路由缓存或本地路由表表示为到达该目的应走的新下一跳。
- 可选验证:若 Redirected Header Option 存在,主机可用它与本地正在发送的数据包头比较,作为安全检查。
四、NDP 报文字段结构
所有报文的头部都是 ICMPv6 标准格式:
+--------+--------+----------------+
| Type | Code | Checksum |
+--------+--------+----------------+
| Message Body(因类型不同而变化) |
+----------------------------------+
NS 报文结构(Type 135)
+-------------------------------------------------------------+
| Type (135) | Code (0) | Checksum |
+-------------------------------------------------------------+
| Reserved (32 bits) |
+-------------------------------------------------------------+
| Target Address (128 bits) |
+-------------------------------------------------------------+
| Options (variable) |
+-------------------------------------------------------------+
字段说明:
| 字段 | 说明 |
|---|---|
| Type | 固定为 135 |
| Code | 固定为 0 |
| Checksum | ICMPv6 校验和 |
| Reserved | 保留(一般为 0) |
| Target Address | 想要解析或探测的 IPv6 地址 |
| Options | 可选项,通常包含:Source Link-Layer Address(源 MAC 地址) |
常见用途
| 用途 | 源地址 | 目标地址 | 组播地址 |
|---|---|---|---|
| 地址解析 | 源:主机IPv6 | 目的:Solicited-node 组播(ff02::1:ffXX:XXXX) | 目标节点监听该组播 |
| DAD 检测 | 源:::(未分配) | 目的:Solicited-node 组播 | 防止地址冲突 |
| NUD 检查 | 源:主机IPv6 | 目的:邻居单播 | 检测邻居是否仍可达 |
NA 报文结构(Type 136)
+-------------------------------------------------------------+
| Type (136) | Code (0) | Checksum |
+-------------------------------------------------------------+
|R|S|O| Reserved (29 bits) |
+-------------------------------------------------------------+
| Target Address (128 bits) |
+-------------------------------------------------------------+
| Options (variable) |
+-------------------------------------------------------------+
字段说明
| 字段 | 含义 |
|---|---|
| Type | 固定为 136 |
| Code | 固定为 0 |
| Flags (R/S/O) | 控制报文类型 |
| Target Address | 通告方 IPv6 地址 |
| Options | 通常包含:Target Link-Layer Address(MAC 地址) |
flags解释
| 标志 | 名称 | 作用 |
|---|---|---|
| R | Router | 发送方是否是路由器 |
| S | Solicited | 是否是响应某个 NS 报文(=1 表示应答) |
| O | Override | 是否覆盖已有缓存(=1 表示可更新缓存) |
常见组合
| 用途 | R | S | O | 说明 |
|---|---|---|---|---|
| 响应 NS 请求 | 0 | 1 | 1 | 正常邻居应答 |
| 主动通告自身地址变化 | 0 | 0 | 1 | 比如 MAC 地址变化 |
| DAD 冲突响应 | 0 | 0 | 0 | 表示地址冲突存在 |
RS 报文结构(Type 133)
+-------------------------------------------------------------+
| Type (133) | Code (0) | Checksum |
+-------------------------------------------------------------+
| Reserved (32 bits) |
+-------------------------------------------------------------+
| Options (variable) |
+-------------------------------------------------------------+
字段说明
| 字段 | 含义 | 长度 |
|---|---|---|
| Type | 133 | 8bit |
| Code | 0 | 8bit |
| Checksum | ICMPv6 校验和 | 16bit |
| Reserved | 保留字段(置 0) | 32bit |
| Options | 通常包含 Source Link-Layer Address(主机 MAC 地址) | 可变 |
通信参数
| 项目 | 值 |
|---|---|
| 源地址 | 主机的 Link-Local 地址(fe80:: 开头)或未配置时 :: |
| 目的地址 | ff02::2(所有路由器组播地址) |
| 触发时间 | 主机启动后立即发送,或手动触发(如接口恢复) |
RA 报文结构(Type 134)
+----------------+----------------+----------------+-----------------+
| Type = 134 | Code = 0 | Checksum |
+--------------------------------------------------------------------+
| Cur Hop Limit | M | O |Reserved| Router Lifetime |
+--------------------------------------------------------------------+
| Reachable Time |
+--------------------------------------------------------------------+
| Retrans Timer |
+--------------------------------------------------------------------+
| Options ...(Prefix Info / MTU / SLLAO / RDNSS ) |
+--------------------------------------------------------------------+
字段说明
| 字段名 | 长度 | 内容 | 说明 |
|---|---|---|---|
| Type | 8 bit | 134 | 表示 RA 报文 |
| Code | 8 bit | 0 | 固定 |
| Checksum | 16 bit | ICMPv6 校验和 | 必填 |
| Cur Hop Limit | 8 bit | 一般填 64 | 通告主机默认 Hop Limit |
| Flags | 8 bit | 含 M / O 位 | 控制 DHCPv6 行为 |
| Router Lifetime | 16 bit | 通常为 1800 秒 | 主机可将该路由器设为默认网关的有效期 |
| Reachable Time | 32 bit | 一般为 0(未指定) | 用于 NUD 参考时间 |
| Retrans Timer | 32 bit | 一般为 0(未指定) | 用于 NS 重传间隔参考 |
| Options | 可变 | 含多个可选字段(见下) | 通告网络配置 |
RA 常见 Options(选项字段)
| Option 类型 | 名称 | 功能 |
|---|---|---|
| 1 | Source Link-Layer Address | 路由器 MAC 地址 |
| 3 | Prefix Information | 通告网络前缀、SLAAC 参数 |
| 5 | MTU Option | 建议的链路 MTU |
| 25 | Recursive DNS Server (RDNSS) | 通告 DNS 服务器 |
| 31 | DNS Search List (DNSSL) | 通告域名搜索后缀 |
Prefix Information Option(最关键)
+-------------------------------------------------------------+
| Type (3) | Length | Prefix Length | L | A | Reserved |
+-------------------------------------------------------------+
| Valid Lifetime | Preferred Lifetime | Reserved2 |
+-------------------------------------------------------------+
| Prefix (128 bits) |
+-------------------------------------------------------------+
| 字段 | 含义 |
|---|---|
| Prefix Length | 前缀长度(通常为 64) |
| L 标志(On-link Flag) | 表示此前缀内的地址是直接可达的 |
| A 标志(Autonomous Flag) | 表示可用该前缀自动生成 IPv6 地址(SLAAC) |
| Valid / Preferred Lifetime | 地址有效期与优先期 |
| Prefix | 前缀值(例如 2001:db8:1::) |
标志位总结:
| 标志位 | 含义 | 主要控制什么 |
|---|---|---|
| M(Managed) | 地址由 DHCPv6 管理 | 是否启用 DHCPv6 地址分配 |
| O(Other) | 其他参数由 DHCPv6 管理 | 是否从 DHCPv6 获取 DNS 等信息 |
| A(Autonomous) | 前缀可用于 SLAAC | 是否可自动生成地址 |
| L(On-Link) | 前缀在链路上有效 | 是否可直接通信 |
| M/O flag的位置分别在第7和第6位上,也就是最高位和次高位,剩下的0-5的保留位设为0。 |
Flags 位如何影响主机行为(SLAAC / DHCPv6)
当主机收到 RA 报文时:
- 查看 M / O 标志位
- 决定使用哪种地址配置方式:
- 如果 M=0:使用 Prefix Information Option (PIO) 提供的前缀 + 本地接口标识生成地址(SLAAC)
- 如果 M=1:发起 DHCPv6 Solicit
- 如果 O=1:发起 DHCPv6 Information Request 获取额外参数
RA 报文通常包含一个或多个 Prefix Information Option (PIO),
PIO 里有 A(Autonomous)和 L(On-Link)标志:
- A=1:主机可用此前缀进行 SLAAC 地址自动生成
- L=1:该前缀内的地址被认为是“同一链路”的地址(直接可达)
注意:M/O 位与 A/L 位是配合使用的。
例如:
- 若
M=1,则即使A=1,主机一般也以 DHCPv6 地址为主。 - 若
M=0 且 A=1,主机会使用 SLAAC。
关于RA m/o Flags字段的6bits保留字段
RFC 5175: IPv6 Router Advertisement Flags Option RFC 5175介绍了 “Router Advertisement Flags Option (RAFO)” 的机制,允许定义额外的 flags。当使用 RAFO 时,这些保留位理论上可以携带扩展含义。
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|M|O|H|Prf|P|R|R|
+-+-+-+-+-+-+-+-+
- M - Managed Address Configuration Flag
- O - Other Configuration Flag
- H - Mobile IPv6 Home Agent Flag
- Prf - Router Selection Preferences
- P - Neighbor Discovery Proxy Flag
- R - Reserved
PRF字段
PRF(Default Router Preference) 是 IPv6 RA(Router Advertisement)报文中的一个字段,用来指示该路由器的优先级。它帮助主机在有多个路由器可选时,决定默认网关选哪个。
在 RA 报文的 “Prefix Information Option (PIO)” 或者 Route Information Option (RIO) 里,会携带 PRF 字段。
但最常见的是在 Router Advertisement 的 Flags + Reserved 位 中定义。
| PRF 位值(二进制) | 含义 | 优先级说明 |
|---|---|---|
00 | Medium(默认) | 默认优先级 |
01 | High | 高优先级路由 |
10 | Reserved | 保留,不应使用 |
11 | Low | 低优先级路由 |
假设一个主机收到两个路由器的 RA 报文:
| 路由器 | PRF | Router Lifetime | 主机选择 |
|---|---|---|---|
| Router A | High | 1800 秒 | ✅ 选为默认网关 |
| Router B | Medium | 1800 秒 | ❌ 备用 |
| Router C | Low | 1800 秒 | ❌ 只在A/B都不可达时才用 |
所以 PRF 是决定默认路由优先级的关键字段,比 Router Lifetime 更优先考虑。
五、报文流程
NDP地址解析
以主机 A 要访问主机 B 为例:
1️⃣ A 发送 NS 请求:
源 IPv6:A 的地址
目的 IPv6:B 的 solicited-node multicast(ff02::1:ffxx:xxxx)
Target Address:B 的 IPv6
Option:Source Link-Layer Address(A 的 MAC)
2️⃣ B 收到 NS 后,发送 NA 响应:
源 IPv6:B 的地址
目的 IPv6:A 的地址(单播)
Flags:R=0, S=1, O=1
Target Address:B 的 IPv6
Option:Target Link-Layer Address(B 的 MAC)
3️⃣ A 收到后更新邻居缓存表:
IPv6 → MAC 映射建立完成
这相当于 IPv4 的 ARP Request/Reply。
DAD(Duplicate Address Detection)
在 IPv6 自动配置中,每个新地址都必须先经过 DAD 检查,防止冲突。
1️⃣ 主机发送 NS:
源地址:::(未配置)
目的地址:自己地址对应的 solicited-node multicast
Target Address:自己准备使用的 IPv6 地址
不带源 MAC 地址
2️⃣ 如果网络中有人回应 NA,则说明地址已被占用。
3️⃣ 若无响应,则认为安全,可以正式使用该 IPv6 地址。
NUD(Neighbor Unreachability Detection)
IPv6 会定期验证邻居是否可达:
- 发送 NS 到邻居单播地址;
- 若邻居返回 NA,则确认可达;
- 若多次超时,则标记为不可达(并重新触发发现)。 这样即便链路中 MAC 地址或路由变化,IPv6 也能自动修正。
Unicast #网络/IPv6/Multicast
六、NDP 使用的地址
NDP 报文常见的三种 IPv6 地址类型
| 地址类型 | 举例 | 用途说明 |
|---|---|---|
| 单播地址 (Unicast) | fe80::1、2001:db8::1 | 表示具体某个节点(源或目标)。NDP 报文的源地址几乎都是单播。 |
| 多播地址 (Multicast) | ff02::1、ff02::2、ff02::1:ffxx:xxxx | NDP 核心依赖多播寻址进行发现、通告等。 |
| 未指定地址 (::) | :: | 没有配置任何 IPv6 地址的节点使用此地址作为临时源地址(例如 DAD)。 |
NDP 各报文的地址使用汇总表
| 报文类型 | 源地址 | 目的地址 | 特殊字段 (Target Address) | 说明 |
|---|---|---|---|---|
| Router Solicitation (RS) | 主机的链路本地地址(若有),否则 :: | ff02::2(所有路由器多播地址) | 无 | 主机请求路由器发送 RA。若主机还没地址(初始阶段),就用 :: 作为源。 |
| Router Advertisement (RA) | 路由器的链路本地地址 | 通常为 ff02::1(所有节点多播),或单播回复给 RS 发送者 | 无 | 通告前缀、默认路由、MTU 等信息,可单播或多播发送。 |
| Neighbor Solicitation (NS) | 发送者单播地址(除 DAD 外) | 目标的 solicited-node 多播地址 ff02::1:ffXX:XXXX | 要解析的 IPv6 地址 | 用于解析 IPv6→MAC(邻居解析)或检测邻居可达性(NUD)。若是 DAD,则源地址为 ::,目标地址是自己拟用的 solicited-node 多播地址。 |
| Neighbor Advertisement (NA) | 发送者单播地址 | 请求者单播 或 ff02::1(主动通告) | 本机 IPv6 地址 | 回应 NS 或主动通告地址变化。 |
| Redirect | 路由器的链路本地地址 | 被重定向的主机的单播地址 | 新的下一跳地址(Target Address) | 路由器告诉主机某目的应改走更优路径。 |
常用的 NDP 相关多播地址解释
| 多播地址 | 名称 | 含义 |
|---|---|---|
| ff02::1 | 所有节点 (All Nodes) | 链路内所有 IPv6 节点(主机+路由器) |
| ff02::2 | 所有路由器 (All Routers) | 链路内所有路由器 |
| ff02::1:ffXX:XXXX | Solicited-Node 多播地址 | 每个 IPv6 单播/任播地址自动对应一个 solicited-node 多播组,用于 NS/NA 定向通信(类似 ARP 的广播)。 |
⚙️ Solicited-Node 地址生成规则:
取 IPv6 地址的最后 24 位(低 3 字节)拼在
ff02::1:ff后面。
例如:fe80::abcd:1234:5678→ff02::1:ff34:5678