摘要

  • IPv6 邻居不可达检测保存的是一项有时效的窄结论:近期证据表明,前向路径曾把报文送到邻居的 IP 层并在那里得到处理。计时器到期后,REACHABLE 变成 STALE,即使没有任何报文被观察到失败。
  • 当没有替代邻居时,RFC 7048 允许保留已有链路层地址并以更长退避继续探测。继续发送不是认证,也不证明地址归属、授权决定或应用动作已经完成。

值班工程师看到两行看似冲突的记录:邻居状态已经是 STALE,下一秒的报文却仍发往原来的链路层地址。若把状态理解成设备健康,系统像是在无视故障;若把它理解成证据寿命,行为就很清楚——地址记忆还在,只是支持“当前可达”的那份确认已经过期。

Neighbor Unreachability Detection,简称 NUD,正是在管理这种差别。它既不要求每个计时器到期都立刻发探测包,也不允许旧确认无限延期。只有当新的业务流量再次用到这条缓存时,问题才从“证据旧了”变成“现在需要核实”。

Erik Nordmark 在这套机制的公开文献中有明确位置。他是 RFC 4861 四位作者之一,该 Standards Track 文档定义 IPv6 Neighbor Discovery;他也是 RFC 7048 两位作者中列名第一者,该文档修正 NUD 在特定条件下过于急躁的失败策略。他还参与 RFC 3756,这是一份分析 Neighbor Discovery 信任模型与威胁的 Informational 文档。作者名单证明的是对 IETF 集体工作的可核实参与,不是独占发明、产品合规或对运营网络的控制权。

“可达”只是一条有方向的句子

RFC 4861 对可达性的定义很窄:从发送节点看,有正面证据表明单向前向路径正常,所发报文抵达邻居的 IP 层并在那里得到正确处理;若邻居是路由器,还要包括它正在履行路由器的转发功能。

这不等于“服务正常”。它不证明返回路径对称,不证明沿途每一跳都健康,不证明设备由谁拥有,也不证明应用接受了一次操作。它只说明在一个有限的新鲜度窗口内,某个观察者面向某个下一跳的前向路径获得过确认。

NUD 接受两类主要正面确认。第一类是对 Neighbor Solicitation 作出的、带 Solicited 标志的 Neighbor Advertisement。第二类是上层协议提供的前向进展提示。

例如,一个新的 TCP ACK 可以说明最近发送的数据已经抵达远端对等方。如果去往该对等方的路径以缓存中的邻居作为第一跳,那么 ACK 支持“这个第一跳刚才可用”的推断。收到新的、非重复数据,也可能说明此前的 ACK 已经沿前向方向到达对端。

有用的推断不能因此无限扩张。TCP ACK 不认证链路层邻居,不证明回程仍走同一路径,不核准用户权限,更不证明业务动作完成。上层观察可以借给下层一个范围清楚的结论,但不能替所有参与者签字。

五个状态对应五个不同问题

INCOMPLETE 表示地址解析尚未取得可用的链路层地址。REACHABLE 表示存在近期正面确认。Reachable Time 到期后,条目转为 STALE。链路层地址没有被删除;降低的是关于“当前可达”的证据等级。

一条闲置的 STALE 缓存不会仅因时间流逝而主动发包。下一份需要使用它的报文到来时,状态才转为 DELAY,报文仍可发往原地址。这个短暂等待窗口给上层留下机会:若 TCP 等机制恰好提供新进展,条目可以直接恢复 REACHABLE,无需多发 Neighbor Solicitation。

如果没有新确认,状态进入 PROBE。节点向已知链路层地址发送单播 Neighbor Solicitation。有效的 Solicited Neighbor Advertisement 可以恢复 REACHABLE。按照基础算法,单播探测次数耗尽后,条目会被删除,并重新进行下一跳选择或地址解析。

这条状态链把四类事实分开:存储的地址、确认的新鲜度、当前是否有使用需求、以及是否正在主动核验。一个 last_seen 时间戳无法表达这些差别。它看见的是无请求公告、TCP 进展、探测回应,还是反方向的任意报文?若机制与方向不在记录里,时间越精确,误导可能越精确。

听到对方说话,不代表对方听得到你

未请求的 Neighbor Advertisement 可能带来重要信息,比如链路层地址变化。Router Advertisement 也能显示某个报文从邻居抵达了接收者。但 NUD 询问的是反方向:接收者发出的报文是否能到邻居。

因此 RFC 4861 明确要求,Router Advertisement 以及 Solicited 标志为零的 Neighbor Advertisement 不得用作可达性确认。学到一个地址,不代表去往该地址的路径畅通;听见一个声音,也不代表对方听见了自己的呼叫。

若监控系统收到任何 ND 消息就刷新 last_reachable_at,未请求公告可以让健康灯长期保持绿色,却从未回答前向路径问题。合格的回执必须保留消息方向、Solicited 标志、接口、目标、链路层地址变化以及它被允许触发的状态转换。

“获得邻居信息”和“确认前向可达”应当是两个事件。它们使用同一协议,并不意味着拥有同一证明力。

三次探测是否足够,取决于失败后能去哪里

RFC 7048 描述的默认行为大致是三次、每次间隔一秒的探测。若主机有另一个真实可用的默认路由器,这种快速失败很合理:当前邻居未确认,流量可以转向一条有希望的替代路径。

没有替代邻居时,同一计时器会产生另一种后果。短暂无线衰落、休眠链路或缓慢恢复可能超过探测预算。删除缓存后,节点通常重新发起地址解析并增加组播;与此同时,它扔掉了唯一合理的链路层地址。所谓“快速失败”没有找到备份,只是清空了上下文。

RFC 7048 为这种条件引入概念上的 UNREACHABLE 状态。条目和链路层地址可以保留,报文也可以继续发往那里。Neighbor Solicitation 按指数退避继续进行,并最终从单播切换到组播。切换很关键:如果邻居的链路层地址已经变化,永远只向旧地址单播就永远无法发现新地址。

此处 UNREACHABLE 不是停机证明。它表示主动探测没有取得预期确认,不表示实现必须停止发包,也不表示应用永久失效。若后来出现真正可用的替代下一跳,未确认条目不应阻止重新选择;某些由 Redirect 建立的条目甚至可以直接删除。

耐心并不天然比快速失败安全。无替代路径时,它保存连续性的机会;有可靠替代路径时,它可能拖延切换。正确策略必须同时记录当时的替代集合,而不是只看状态名字。

正确执行状态机,也可能接受了伪造证据

RFC 3756 解释了信任边界。若攻击者能在链路上注入 Neighbor Discovery 消息,一份伪造的 Solicited Neighbor Advertisement 可以制造虚假正面确认,让缓存指向恶意或不存在的链路层地址,并造成拒绝服务。状态机可能完全按规则运行,输入却来自对手。

所以 REACHABLE 不是“已认证”的同义词。IPv6 地址与链路层地址的映射,也不能单独证明设备所有者、责任机构、运行软件或允许报文通过的政策。链路接入控制、密码学、资产清单与应用授权各自产生独立证据。

事故账本应把这些证据并列保存,而不是让一个字段覆盖另一个。NUD 侧保留接口、下一跳、地址映射、确认来源、探测序列、可用替代、安全上下文与实现版本;应用侧另行保留认证主体、授权决定、资源版本与结果回执。“邻居回应了”不能自动改写成“动作获准并完成”。

精确归功,也要精确限制权力

截至 2026 年 8 月 30 日审阅时,IETF 公开资料列出 Erik Nordmark 参与的 25 份 RFC,并显示他担任 Internet of Things Directorate 评审人。这些角色与数量可能变化。文档本身提供更稳定的归因:RFC 4861 作者为 Thomas Narten、Nordmark、William Simpson 与 Hesham Soliman;RFC 7048 作者为 Nordmark 与 Igor Gashinsky;RFC 3756 列出编辑 Pekka Nikander,以及 James Kempf 与 Nordmark。

RFC 4861 与 RFC 7048 属于 Standards Track,RFC 3756 是 Informational。文档状态、作者顺序和 IETF 共识都不能替代部署证据。运行中的代码仍需证明:实现接受哪些上层提示,如何转换状态,如何判断替代路径,如何退避,以及日志实际保留了什么。

RFC 是公开协调点,不是某个网络的远程控制器。它让独立实现可以比较,也给审计提供边界。NUD 最值得继承的恰是这种克制:保留仍可能有用的地址,但在证据过期时主动降低结论;需要更强主张时,再要求新的运行证据。

先变陈旧的不是邻居,而是证明。这一字之差,决定缓存是在帮助决策,还是在冒充事实。

来源