10 月 15 日深夜和 17 日凌晨,首尔自建节点先后出现两次超时。TCP 端口能连上,Mihomo 节点测试却返回 504。第二次故障的抓包显示:首次 TLS 握手中,较大的首段不断重传,服务端却收到了后面较小的片段。
目前保留 RouterOS 上仅针对该节点的 MSS 1400 规则。调整后的抓包显示客户端发送的数据段缩小,随后 21 次节点测试全部成功。
10月21日只读复核,定向MSS规则仍启用、值为1400,mihomo配置哈希与此前维护基线一致。本文抓包、21次节点测试及testedWith/verifiedAt均保留10月17日的实际窗口,没有因文章更新改成新的测试结果。
10月21日的DNS分流维护解决的是解析答案和后端故障恢复,不会改变本规则,也不能据此认定先前的大握手重传已经根治。某个域名解析正常、某个策略组可用,都不能代替指定首尔节点的新连接验证。
两次超时的时间
以下均为北京时间。恢复时间以主动测试成功为准。
| 时间 | 现象 |
|---|---|
| 10 月 15 日 23:58 | 开始记录到首尔业务连接超时 |
| 10 月 16 日 00:18 | 没有改配置,主动测试确认节点恢复 |
| 10 月 17 日 00:37 | 再次出现业务超时;00:38 健康测试也失败 |
| 10 月 17 日 00:41–00:43 | 抓包和独立 TLS 对照测试复现故障 |
| 10 月 17 日 00:44 左右 | 节点在 MSS 规则启用前又暂时恢复 |
| 10 月 17 日 00:45 以后 | 完成定向调整和验证,保留 MSS 1400 |
两次故障期间都没有 PPPoE 重拨或 Xray 重启。第一次缺少故障时的双端同流抓包,只能确认症状相似。
TCP 建连成功后的握手超时
故障时,首尔 TCP 端口约 70–80 ms 可达,日本节点对照测试也正常。但 Mihomo 的首尔测试持续返回 504,业务日志显示连接超时。服务端 Xray 仍在监听,也仍能接受其他来源的连接。
一次新连接完成 TCP 三次握手后,客户端发送了约 1824 字节的首次握手数据。在家庭 WAN 抓包中,它被分成 1412 字节的首段和 412 字节的尾段。服务端通过选择性确认(SACK)报告收到了尾段,首段却一直未获确认,并反复重传。
另用 OpenSSL 直连同一端点,默认分段也会超时;将测试连接的 MSS 分别降至 1400、1360、1280 或 1000 后,握手都能完成。故障并非只出现在 Mihomo 的节点测试里。
较大的 ClientHello
Mihomo 为该节点开启了 X25519MLKEM768 混合密钥交换。现场观察到的首次握手数据约 1824 字节。在独立的 OpenSSL 3.5.7 对照中,默认 ClientHello 为 1560 字节,仅使用 X25519 时为 517 字节。这些是本次测试的数值,会随客户端和握手参数变化。
较大的 ClientHello 更容易跨越 TCP 段。OpenSSL 官方说明过,混合密钥交换带来的大 ClientHello 在跨段后,可能遇到中间防火墙错误处理而失败或超时。官方说明
这次保留了混合密钥交换,只调整 TCP 分段大小。
双端抓包里的 MSS 变化
恢复后的双端同步抓包中,虽然共享地址转换改变了源端口,仍可通过序列号、确认号和时间对应上同一连接:
| 方向 | 家庭物理 WAN 抓包 | 首尔服务器网卡抓包 |
|---|---|---|
| 客户端 SYN 的 MSS | 发出 1452 | 收到 1424 |
| 服务端 SYN ACK 的 MSS | 收到 1424 | 发出 1460 |
这表明路径中存在 MSS 改写,但还不能据此找出丢包设备。
故障时,设置 DF(禁止分片)的 Ping 可以通过,IP 包总长为 1464 字节,其中 ICMP 数据为 1436 字节。恢复后,从不受新规则影响的测试来源发起默认大段 TLS,也能成功。因此,目前更怀疑路径或中间设备间歇性地处理大握手数据异常,证据还不足以认定存在固定的 IP MTU 上限。
家庭物理网卡的错误计数为零,发送抓包也能看到这些数据段。不过,抓包点位于数据真正上网线之前,硬件卸载和后续链路仍需保留排查。两次故障时间都接近午夜,但暂未找到对应的定时任务或重拨记录。
只针对首尔节点限制 MSS
MSS 是 TCP 握手时声明的单段最大数据长度。服务端返回的 MSS 约束客户端的发送方向,所以这次修改的是首尔返回给代理主机的 SYN ACK,让代理主机向首尔发送较小的数据段。
规则同时限定节点地址、源端口、代理主机地址、入出接口、TCP 标志和原 MSS。它只把大于 1400 的值降到 1400,不抬高原本更小的值,也不处理其他节点、其他客户端、UDP 或 IPv6。
下面使用文档示例地址,接口名也需按实际环境替换。place-before=0 将规则放在现有 Mangle 表的首条之前,以免被前面的终止规则跳过;示例以禁用状态添加,检查后再启用。家庭路由器已经部署,无需重复添加。
/ip firewall mangle add chain=forward action=change-mss new-mss=1400 \
passthrough=yes protocol=tcp tcp-flags=syn,ack tcp-mss=1401-65535 \
src-address=203.0.113.10/32 src-port=24443 dst-address=192.0.2.6/32 \
in-interface=pppoe-out1 out-interface=bridge-lan place-before=0 \
disabled=yes comment="Example Seoul TLS MSS 1400"
203.0.113.10 代表节点,192.0.2.6 代表代理主机,均不是实际设备地址。不要原样用于生产。
先查看规则,确认该备注只对应这一条,再启用:
/ip firewall mangle print detail where comment="Example Seoul TLS MSS 1400"
:put [:len [/ip firewall mangle find where comment="Example Seoul TLS MSS 1400"]]
/ip firewall mangle enable [find where comment="Example Seoul TLS MSS 1400"]
/ip firewall mangle print stats where comment="Example Seoul TLS MSS 1400"
这次没有修改通用 MSS、全局 MTU、QoS、节点认证或 Mihomo 配置。新规则只影响新 TCP 握手,已有连接不会被强制重建。
调整后的抓包与请求结果
规则启用后,代理主机收到的 SYN ACK 已变为 MSS 1400。数据段中还有 12 字节的 TCP 时间戳选项及填充,因此家庭物理 WAN 上的首段 TCP 数据为 1388 字节(1400 − 12);服务端随后完整确认了首次握手数据。MSS 的计算与选项处理见 RFC 9293 第 3.7.1 节。
随后首尔 21/21 次测试成功,延迟 103–118 ms,日本、香港、新加坡的对照测试也通过。逐项比对后,原有 23 条 Mangle 的内容和相对顺序没有变化;Mihomo 配置哈希一致,进程没有重启。
通过当时选中首尔的 AI 策略访问 OpenAI API,未携带凭据的请求返回了预期的 401,Xray 访问日志也记录到了这次请求。TLS 和 HTTP 往返已完成,但这里没有测试登录后的业务或推理速度。
00:55 再测三次均成功,从 00:45:35 起的日志中也没有新的首尔连接超时。节点在规则启用前已经暂时恢复,所以这些结果只能确认分段调整生效、当时连接可用,长期效果还要继续观察。
回滚只撤销本次规则
修改前已保存路由器原生备份、Mangle 导出和本次规则的回滚命令。生产规则的准确备注与备份路径保存在家庭网络文档中;以下命令只对应本文示例,不能直接撤销家庭路由器上的生产规则。
若使用了上面的示例,先查看匹配条件和数量。数量应为 1,地址、端口和动作也应与新增规则一致;若为 0 或多于 1 条,先核对备注。
/ip firewall mangle print detail where comment="Example Seoul TLS MSS 1400"
:put [:len [/ip firewall mangle find where comment="Example Seoul TLS MSS 1400"]]
临时停用:
/ip firewall mangle disable [find where comment="Example Seoul TLS MSS 1400"]
完整撤销时,删除同一条规则。停用和删除按需要选择其中一种:
/ip firewall mangle remove [find where comment="Example Seoul TLS MSS 1400"]
回滚后再查看规则状态或数量,并发起新连接检查;旧连接仍沿用握手时协商的 MSS。临时停用后,可用前面的 enable 命令重新启用。
直接导入整份旧 Mangle 导出可能追加重复规则;整机恢复则会覆盖其他配置。撤销这一条规则无需这样操作。
复发时需要记录的证据
如果再次超时,先记录故障时间,分别测试首尔和对照节点,查看 MSS 规则是否启用、命中计数是否增长,再检查连接停在 TCP 建连、TLS/REALITY 握手还是代理后的 HTTP 请求。
最有价值的是故障仍在发生时,家庭 WAN 与服务端同一新连接的包头:检查大段是否到达、SACK 确认了哪些字节、重传是否仍失败,以及是否收到需要分片的 ICMP。恢复后的正常抓包无法定位先前的丢包设备。