ICMPv6 邻居请求与通告解析本地邻居;邻居发现还包括路由器发现和可达性检测。

IPv6 先用 ICMPv6 解析邻居,TCP 才能正常通信

以太网链路上的 IPv6 主机,需要先取得邻居的链路层目的地址,才能发送相应帧。邻居发现通过 ICMPv6 的邻居请求和邻居通告完成地址解析,同时还涵盖路由器发现、邻居可达性检测等超出 IPv4 ARP 的功能。把它简单理解为“地址更长的 ARP”,会掩盖配置 IPv6 网络时必须考虑的依赖关系,尤其是控制报文与应用通信之间的联系。 坏掉的样子 拥有有效 IPv6 地址和路由,不代表能够解析下一跳的以太网地址。如果必要的请求或通告被过滤,TCP 服务可以一直正常监听,客户端却在交换应用数据前就失败。只开放应用 TCP 端口,无法修复这个较低层依赖。排查时应把邻居表、相关 ICMPv6 流量和服务监听一起观察,不能只从端口是否开放判断整条路径。 缓存状态还可能隐藏错误。已有可用邻居条目的主机,在破坏性规则安装后可能继续通信;新客户端或条目失效之后,故障才暴露。反过来,STALE 状态也不自动意味着损坏:邻居发现可以利用已有链路地址,随后再检查可达性。应理解状态转换,不能要求每个正常条目永远显示 REACHABLE,否则会把正常缓存生命周期误判为故障。 另一类混淆,是在本地以太网段上解析远端应用服务器地址。目的地位于链路之外时,主机通常解析选中的下一跳路由器,而不是远端服务器。判断邻居表应出现哪个地址之前,需要先确认选路。捕获接口错误,或者已有缓存使本次无需重新发送请求,也能解释空白抓包结果,不能据此证明邻居发现根本没有发生。 本图解释 ICMPv6 依赖。邻居解析不认证地址归属,也不单独验证 SLAAC、路由器通告处理或重复地址检测;绘图未重跑网络实验。 快速验证 历史报告使用 Python 3.11.16、iproute2 6.1.0、nftables 1.0.6 与 tcpdump 4.99.3;本轮未重跑。脚本名为 check-neighbor-discovery.py,只应留给另外获得授权的可丢弃 Linux 虚拟机。容器共享其内核,NET_ADMIN、SYS_ADMIN、proc 挂载和命名空间防火墙变更需要这一隔离边界。构建阶段会下载软件包,--network none 只适用于之后的容器运行。保持断言开启,不要为绕过设置失败而放宽宿主安全策略。新建 veth、邻居与防火墙变更仅应存在于实验内部: ...

十一月 16, 2026 · 3 分钟 · XB Field Notes
ARP 在直连以太网链路解析选中的 IPv4 下一跳;缓存把 IPv4 与接口共同映射到学到的 MAC,链路外目的地不参加该次解析。

ARP 把 IPv4 下一跳映射到链路层地址

IPv4 转发选出了下一跳,但以太网仍然需要目的 MAC 地址。地址解析协议(ARP)向本地链路询问哪个网卡拥有某个 IPv4 地址,然后把答案缓存为邻居条目。这种映射是学来的而非永久配置,所以会老化,会在网卡迁移后刷新,也可能被同一广播域里的另一台主机伪造。 在本地链路上发问 假设主机要向直连网络中的 192.0.2.20 发送数据。它广播一条 ARP 请求,带上自己的 IP/MAC,并询问谁拥有目标 IP。属主用单播应答自己的硬件地址。发送方随后才能组装以太网帧。目的地不在本地链路时,主机解析所选网关;每一段以太网链路使用自己的下一跳映射,而不是远端主机的 MAC。 这个请求很小,而且只在本地发生。它不是 DNS 查询,也不会穿过路由器。请求尚未完成时,条目可能是 incomplete;近期流量确认可达时是 reachable;计时器到期后变成 stale;解析失败则可能进入 failed。Linux 用 ip neigh 展示这些状态,较旧的 arp(8) 只呈现更简单的地址到硬件映射。计时器和状态转换取决于内核与网卡策略,不能把“默认 60 秒”当成所有系统的承诺。 网卡是答案的一部分 同一个 IPv4 地址可以出现在不同链路,所以 ARP 记录必须和设备一起理解。ip neigh show dev eth0 只询问一张网卡;arp -an 也把接口列在每条映射旁边。虚拟机迁移或更换网卡后,邻居可能还缓存着旧 MAC。免费 ARP 通告能让邻居更快更新,但它仍是没有签名的声明,在敏感网络上应当监控而不能盲信。 ...

十一月 15, 2026 · 2 分钟 · XB Field Notes
路径上三段链路的 MTU 依次为 1500、1280 和 1500 字节。中间链路决定路径 MTU;小交互成功并不能验证大传输。

路径 MTU 发现失效时,握手和小请求仍可能成功

路径 MTU 是某条具体路由上各链路 MTU 的最小值。发送端不能只根据自身接口确定它,因为中间链路可能只能承载更小的数据包。经典 IPv4 路径 MTU 发现设置禁止分片标志,通过 ICMP“需要分片”反馈降低估计包大小。路由能够到达目的地,与发送大小适合整条路径,是两项不同条件,前者成立不能自动证明后者。 最小链路决定包大小是否适合。应结合反馈、全新路由状态、有效 MSS,以及原故障方向上有代表性的应用交付。 坏掉的样子 隧道或其他受限中间链路,可能使大传输失败,而 TCP 握手与小请求仍然成功。小报文能够通过瓶颈,因此这些成功没有验证完整大小的数据。反复只测短 ping 或微小健康响应,就可能漏掉影响上传、大响应或持续传输的路径 MTU 问题。应让检查包含真实负载中会触发限制的大小,避免健康探针与实际业务长期脱节。 过滤必要 ICMP 反馈,会让过大报文进入黑洞。发送端观察到没有进展,却缺少指出更小 MTU 的经典信号。其他探测机制可能提供帮助,取决于传输协议和配置,因此不能断言所有 TCP 实现遇到这种过滤都会永久卡住。作出结论前,应查明实际启用了哪一种发现或黑洞恢复机制,不能把某个实验控制条件省略后推广到所有环境。 路径信息还可能被缓存。成功发现之后进行的测试,即使防火墙改变,也可能与全新客户端表现不同。复用已有状态会隐藏反馈路径损坏。路由变化和非对称返回路径进一步增加复杂性,所以需要记录方向、来源、目的地,以及估计是在什么条件下学到的。配置变化前后的结果,只有在这些前提清楚时才适合直接比较。 快速验证 以下命名空间、抓包与套接字集成原样保留,本轮未重跑;观察属于历史记录,离线检查不能复现网络结果。 历史报告使用 Linux 6.12.76、Python 3.11.16、iproute2 6.1.0、nftables 1.0.6 与 tcpdump 4.99.3。脚本名为 check-path-mtu.py,只应留给另外获得授权的可丢弃 Linux 虚拟机。Docker 共享其内核,NET_ADMIN、SYS_ADMIN、proc 挂载和命名空间参数需要这一隔离边界。后续运行的 --network none 不阻止构建下载软件包。保持断言开启,设置失败时不要放宽宿主安全策略。新建 veth、地址与路由仅应存在于实验内部: ...

十一月 14, 2026 · 3 分钟 · XB Field Notes
两个连接四元组共用本地地址 192.0.2.1 和端口 40200,但远端端口分别为 18080 和 18081。复用取决于套接字与内核规则。

TIME-WAIT 保护连接实例,不是独占一个端口号

TIME-WAIT 是 TCP 在某些有序关闭之后继续保留的协议状态。它为必要时重发最后确认、完成关闭交换留出时间,也帮助避免早先连接实例的延迟报文被误认成新连接数据。相关身份包含两端地址和端口,不能把一个 TIME-WAIT 条目简单理解成对某个本地端口号的全局锁。连接四元组和单独端口,是不同范围的概念。 TIME-WAIT 保护连接实例。判断身份要看四元组,复用结果取决于套接字路径与内核条件。 坏掉的样子 普通关闭中,首先发起关闭的一端通常在确认对端 FIN 后进入 TIME-WAIT。这一端可能是客户端,也可能是服务器;同时关闭还可能涉及双方。假定 TIME-WAIT 永远属于服务器,会掩盖真正制造连接周转的工作负载。应查看状态及两端四元组,不能从应用角色推断谁先关闭,也不能把客户端保留该状态直接视为异常。 高频连接周转可能限制到某个目的地的新连接,但 TIME-WAIT 数量很大,本身不证明资源耗尽或应用文件描述符泄漏。应用关闭套接字之后,操作系统仍可保留协议状态。源地址、可用端口、目的地多样性、显式绑定、复用选项与内核行为,都会影响实际限制。诊断资源耗尽之前,应同时测量连接失败与状态分布,而不是只盯一个总数。 混淆 TIME-WAIT 和 FIN-WAIT-2 会导致无效调参。Linux 的 tcp_fin_timeout 控制另一种孤立套接字情形,不是通用的 TIME-WAIT 时长开关。关于 tcp_tw_recycle 的旧建议,也不适用于当前 Linux。复用受到协议安全条件约束,其中包含时间戳相关检查;如果不了解真实套接字路径,仅修改一个参数,就可能产生错误的行为预期。 ...

十一月 13, 2026 · 2 分钟 · XB Field Notes
拥塞窗口与接收窗口分别约束未确认数据;另一条 pacing 时间线显示发送间隔。每个发送端选择自己的拥塞策略。

TCP 拥塞控制由每个发送端决定,两端可以使用不同算法

TCP 拥塞控制限制发送端向容量有限、可能被共享的网络注入数据。拥塞窗口约束未确认数据量,采用 pacing 时还会控制发送在时间上的分布。接收端通告窗口施加的是另一类流量控制限制。这些机制相互作用,却描述不同约束,不能笼统合并成一个“发送速度设置”,否则很难判断真正限制当前连接的是哪一部分。 数据量、发送时序与应用供给是不同约束。回读套接字实际控制器,并结合该算法解释反馈。图中文章报告值未在本轮重现。 坏掉的样子 两端不需要选择完全相同的拥塞控制算法。每端负责控制自己发送的流量,因此 Reno 客户端能够与 CUBIC 服务器通信。TCP 建立过程协商传输选项,没有要求双方发送算法名称一致。把不同控制器名称诊断成协议不匹配,会分散注意力,掩盖真正的路由、缓冲或应用故障。算法选择需要按方向和具体套接字理解。 算法是否可用,也是需要核对的运行时事实。配置字符串写了某个控制器,不证明内核支持它或允许调用进程选择它。Linux 的 TCP_CONGESTION 按套接字设置,受可用和允许算法约束。应检查调用结果,并回读实际名称,不能默认请求标签已生效。选择失败与选择成功后性能不合适,属于不同问题,需要不同处理。 丢失恢复不存在适用于所有情况的统一曲线。重传超时、快速恢复、显式拥塞通知和基于模型的估计,会因控制器不同而产生不同响应。丢失可能来自拥塞,也可能来自其他原因,发送端仍须按算法规则作出反应。增加缓冲并不能自动修复持续丢包或等待确认的连接,也不能替代对具体恢复状态和触发信号的检查。 快速验证 将脚本保存为 check-congestion-control.py,准备 Docker 后运行 python3 check-congestion-control.py。一次性环境使用 Python 3.11.16、iproute2 6.1.0 和 nftables 1.0.6,在 Linux 6.12.76 上验证。NET_ADMIN 与 SYS_ADMIN 支持嵌套命名空间。新建 veth 两个方向出口各增加十毫秒延迟,不修改宿主接口或生产流量: ...

十一月 12, 2026 · 2 分钟 · XB Field Notes
三个独立数据报卡片分别为 A:1 字节、BC:2 字节、空载荷:0 字节;空载荷仍是一条消息,不代表 EOF。

UDP 保留数据报边界,恢复和时效由应用负责

UDP 在传输端点之间携带独立数据报,八字节首部包含来源端口、目的端口、长度和校验和字段。它不会加入 TCP 的可靠有序字节流或拥塞控制行为,让应用可以选择自己的交付策略,但不承诺所有负载下延迟都更低。应用确实需要某条内容时,丢失的数据报可能比建立连接的开销更昂贵,必须按完整请求过程评估。 原文发送 A、BC 和空数据报,得到长度 1、2、0。八字节 abcdefgh 用三字节缓冲区接收,得到 abc 与 MSG_TRUNC;defgh 被丢弃,下次读取超时,新发的 next 数据报仍能收到。刻意编写的中继把 1、2、3 改成 3、1、1;集合去重只留下 3、1,没有恢复 2 或原始顺序。 原有实验示意,本轮未重跑;中继属于故障注入,不是网络丢包统计或延迟保证。 坏掉的样子 发送成功不证明目标应用已经收到或处理消息。UDP 没有内建确认、重传、去重或顺序保证,因此超时不能告诉支付客户端操作是否发生。允许重试时,应用需要能够处理重复请求和结果不确定的协议,不能把没有响应直接解释成业务失败。消息是否到达、动作是否执行、结果是否持久化,也应具有不同含义。 ...

十一月 11, 2026 · 1 分钟 · XB Field Notes
原文预期情景,不是实测记录。HTTP 转发行把客户端经路由器连到目标;下方探测回复行在路由器处为星号,目标仍以 10.201.2.2 回复。缺少中间诊断回复不能证明转发停止。

Traceroute 展示探测响应,不能完整代表转发健康

Traceroute 发送 TTL 逐步增大的探测包,观察数据包在哪里到期,以及哪些系统报告了到期。IPv4 路由器转发时递减 TTL;到期后,通常由 ICMP Time Exceeded 响应标识一个作出回复的跳点。传统 UDP 跟踪在目标报告端口未使用时结束。输出是一系列关于探测和回复的观察,不保证列出全部转发设备,也不直接等同于应用经过的唯一稳定路径。 坏掉的样子 星号表示某个探测没有在等待时间内获得预期响应。路由器可能仍正常转发普通流量,却过滤、抑制或限制自己生成的 ICMP 回复。回复的返回路径也可能出问题。因此,中间某跳沉默,本身不能证明应用数据包在那里停止;后续跳点仍然回复,甚至会直接反驳这种判断。需要区分转发动作和产生诊断响应这两种行为。 探测协议同样重要。传统高端口 UDP 流量可能遇到与允许服务端口上的 TCP 不同的策略。TCP traceroute 可以让探测更接近被允许的传输方式,但仍没有执行完整应用交互。收到 SYN 响应或重置,可以帮助判断目的地可达,却不能证明 HTTP、认证或某项业务操作成功。协议层面的终点响应必须与应用结果分别解释。 每跳时间是从观察者出发的往返时间,包含响应生成和返回路径。把相邻数值相减,不能可靠测量两台路由器之间的单向链路延迟。负载均衡、返回路径不对称、调度与 ICMP 处理都会影响观察。比较跟踪时,应保留探测方式和测量条件,不能把一次打印序列当作永久拓扑,也不能把后续更短的往返值解释成负延迟。 沉默跳点仍可转发流量。 仅为原文预期模型。实验前提缺失,可执行验收受阻;不声称具有保留的运行证据。 快速验证 2026-10-18 源码审阅说明:下述预期结果与历史报告没有在本次审阅中重新运行,当前执行验证仍受阻。 ...

十一月 5, 2026 · 3 分钟 · XB Field Notes
原文的本地示例中,IPv6 仍排在候选列表首位,但已停止的监听拒绝连接;按序尝试的客户端随后通过 IPv4 成功。

双栈地址排序与最终成功的连接选择是不同步骤

发现 A 与 AAAA 记录,只提供可能的目的地,本身不会选出成功连接。地址排序、源地址选择、路由以及应用连接算法都会参与结果。RFC 6724 描述默认源地址和目的地址选择规则,应用仍可作自己的选择。如果程序只请求 IPv4,那么在任何双栈连接策略开始工作前,它就已经缩小了候选范围。解释行为时,应先确认实际调用方请求了什么。 坏掉的样子 地址偏好不是应用健康探测。某个 IPv6 目的地可能符合本地策略和路由条件,远端服务却已经停止,或者更后面的网络跳点会丢包,因此优先候选仍可能失败。如果假定操作系统已经测试了返回列表中每个端点,就会忽略连接截止时间和尝试其他地址的必要性。查询成功只能证明获得候选信息,不能代替服务通信结果。 RFC 6724 的规则是按顺序比较条件,并不是对网络成本或速度打一个总分。相关属性包括可用性、作用域、策略标签、优先顺序和匹配前缀,但它们不测量应用响应时间。目的地址选择还应与路由表最长前缀匹配区分:后者决定已选目的地的数据包如何发送。混用这两个阶段,会把主机偏好错误解释成已经知道整条路径延迟最低。 Happy Eyeballs 属于另一层,通过协调地址发现和错开连接尝试,减少某个地址族出问题时的等待。按顺序逐个尝试地址的客户端,并不自动实现该算法。立即拒绝连接与静默丢弃连接尝试,可能造成非常不同的等待时间,即使最后都能通过 IPv4 成功。不能只看最终用了另一个地址族,就把过程统称为相同的快速竞速机制。 首个候选只代表偏好,不能证明服务健康。图示 IPv6 优先顺序仅属于原文的本地进程。网络示例执行仍受阻,本草稿未重跑。 快速验证 将脚本保存为 check-address-selection.py,准备 Docker 后执行 python3 check-address-selection.py。固定环境使用 glibc 2.36、Python 3.11,以及提供 DNS 的 BIND 9.18.49 和 dnsmasq 2.90。两个真实 HTTP 监听分别使用 IPv4 与 IPv6 回环,端口相同。实验没有公网路径,因此观察到的排序明确属于这个本地环境,不作为所有客户端的默认承诺: ...

十一月 4, 2026 · 3 分钟 · XB Field Notes