问题背景
公司办公网约 40 人,出口是一台 RouterOS 软路由,PPPoE 双栈已经稳定运行一年多:IPv6 通过 DHCPv6-PD 拿到 /60 前缀,由 RA 通告给办公网段,员工电脑大多持有 IPv6 全局地址,平时上网一切正常。
上周四上午开始,陆续有同事反馈:打开公司 ERP 客户端和个别网站时,界面会卡二十秒左右才"缓过来"。奇怪的是,同一台电脑上用浏览器打开网页却基本正常。受影响的人越来越多,但故障像是"挑软件"——ERP 客户端、老版 VPN 拨号工具几乎必卡,浏览器和常用 IM 则无感。
故障现象
- 卡顿时长高度一致:每次约 21 秒,然后要么成功、要么重试一次即通。
- 浏览器打开网页基本正常,顶多首次略慢;问题集中在几款传统客户端软件。
- 同一台电脑上 ping 域名(默认走 IPv4)完全正常;换 ping 该域名对应的 IPv6 地址则超时。
- 内网互通无异常:能 ping 通网关,内网 IPv6 地址互访正常。
- 电脑 CPU、内存、无线信号都正常,换有线、重启电脑均无效。
- 换手机热点访问同一服务正常,排除目标服务端问题。
排查过程
第一步,把"卡 21 秒"和 IPv6 联系起来。 在一台必卡的电脑上复现故障,同时抓包。Wireshark 里看得很清楚:客户端解析域名拿到 A 和 AAAA 两组地址后,先向 IPv6 地址发 SYN;这个 SYN 无人应答,按 3 秒起步、指数退避重传两次,直到约 21 秒后才放弃,转而对 IPv4 地址发 SYN、秒连。netstat 里同步能看到连接长时间停在 SYN_SENT。21 秒不是业务慢,而是 Windows 默认的 TCP 连接超时(三次 SYN 尝试)——这就是"卡 21 秒"的全部来源。
第二步,解释为什么浏览器没事、老客户端遭殃。 Windows 按 RFC 6724 的地址排序规则,域名同时有 A/AAAA 记录时优先尝试 IPv6。现代浏览器都实现了 Happy Eyeballs(RFC 8305):IPv6 连接约 300 毫秒没有进展,就并行发起 IPv4,谁先通用谁,用户几乎无感。而大量传统客户端(尤其 Java 写的、以及一些老国产软件)没有这个机制,严格按地址顺序先试 IPv6,只能吃满整个 TCP 超时。顺带一提,Linux 默认的重传参数更"耐心"(约两分钟),同样的故障在 Linux 客户端上会卡得更久——这解释了为什么"同一个故障,每个人的体感完全不同"。
第三步,从内到外逐段确认 IPv6 出站已断。 终端侧:ping6 网关秒通,LAN 侧 RA、地址、邻居发现都健康。路由器侧:在 RouterOS 上 ping 公网 IPv6 地址(如 2400:3200::1)四次全部超时,而 ping 223.5.5.5 四次全通——IPv4 出站完好、IPv6 出站不通,故障范围收缩到"路由器之外"。/ipv6 route print 显示默认路由还在、指向 PPPoE 接口;traceroute6 显示数据包出一跳后就没有回应。也就是说,这不是"无路由"(那会立刻返回不可达),而是有路由、包在运途中被某一跳静默丢弃,一路没有任何 ICMPv6 错误返回。
第四步,确认运营商侧故障。 向宽带运营商报障,后台确认该区域 IPv6 出口前一晚有割接维护、IPv4 不受影响,恢复时间待定。至此链路闭环:运营商 IPv6 出口故障(静默黑洞)+ 内网双栈"半通"状态 + 无 Happy Eyeballs 的客户端,共同构成了这次 21 秒卡顿。
解决方案
- 止血:在出口把"黑洞"改成"快速失败"。 既然公网 IPv6 暂时不可达,就不要再让流量出去"等死"——在路由器上对出站 IPv6 转发流量配置明确的 reject(回 ICMPv6 不可达),让客户端瞬间失败、立即回退 IPv4:
|
|
改完后所有客户端的 21 秒卡顿立即消失。这里有个容易踩的坑:单纯撤下 RA 通告并不能即时止血——已分配 IPv6 地址的终端会继续持有地址直到寿命到期,照样先试 IPv6;快速失败策略才是立竿见影的那个动作。
-
根治:等待运营商修复。 运营商恢复后用
ping6 2400:3200::1验证出站正常,再移除临时 reject 规则。 -
长期:IPv6 可用性探测与联动。 在路由器上部署探测任务(比如每 5 分钟 ping6 两个公网目标):连续失败自动启用快速失败规则并告警,恢复后自动解除。让"上游 IPv6 挂了"从一个要靠用户投诉才会发现的事件,变成自动降级、用户无感的日常动作。
根因分析
直接根因是运营商侧 IPv6 出口割接故障,出站 IPv6 流量在运营商网络中被静默黑洞;而内网双栈照常工作——终端持有 IPv6 地址、按 RFC 6724 优先选 IPv6、连接请求却永远等不到回应,直到 Windows 默认的 TCP 连接超时(约 21 秒)才回退 IPv4。
更深一层,这是"静默失败"与"快速失败"的代价差:同样是 IPv6 不可用,如果失败是"立即被拒绝",客户端毫秒级回退 IPv4、用户毫无感知;而静默黑洞把一次网络故障放大成了用户可见的 21 秒卡顿,还让排查一开始失去方向。运营商网络的失败方式我们控制不了,但自己边界上"失败的速度"是可控的——这次故障真正的教训在这里。
预防措施
- 双栈网络增加 IPv6 可用性主动探测,并与降级策略(快速失败/告警)联动,不让上游故障以"用户体验问题"的形式抵达;
- 出口设备策略评审:对确定不可达的流量优先使用 reject(带 ICMP 错误)而不是 drop,让客户端快速回退;
- 双栈改造与变更原则:上游 IPv6 端到端验证稳定后,再向内网通告 RA;上游维护窗口前先评估双栈降级预案;
- 对没有 Happy Eyeballs 的历史客户端,评估升级,或在网络库层面配置连接超时,缩短最坏情况的等待;
- “卡顿"类问题的排查清单里加入"显式 ping6 / 检查 AAAA 记录"一项——默认 ping 走 IPv4,会把 IPv6 的问题完整地藏起来。
总结
故障可以来自上游,但"失败的速度"掌握在自己手里。这次 21 秒卡顿的全部戏剧性来自三个机制的叠加:RFC 6724 让终端优先选 IPv6,Happy Eyeballs 的缺席让老客户端老老实实等超时,运营商侧的静默黑洞则让每一次尝试都注定失败。把"黑洞"改成"快速失败"之后,同样的上游故障,用户几乎无感。双栈时代值得反复默念的一条原则是:让失败大声且迅速,别让它安静地拖时间。