连接排障 · Clash 技术博客

Mihomo MASQUE 下载卡住:ip-stack 排查

MASQUE 下载中途归零,新连接却正常?先核对 Mihomo 版本与 with_gvisor,只为目标节点对照 ip-stack,验证同一请求并保留回退;不把报告当成已发布修复。

  • MASQUE
  • Mihomo
  • ip-stack
  • gvisor
  • 单连接停滞
本文目录

MASQUE 节点能连上,文件也开始下载,传输却突然停住;与此同时,新开的网页又能访问。这与整条代理断线不同。可以先分清停住的是一个请求还是所有连接,再检查 Mihomo 的实际版本和该出站节点的 IP 栈。

下载停住了,怎样判断隧道是否还在工作?

Mihomo #3325 是一份 Linux/ImmortalWrt 用户报告:单条 TCP 下载中途停止接收数据,同一 MASQUE 隧道上的新连接仍正常。报告涉及 alpha-bc76c13 与自行编译的 alpha-94b13ae,改用 gvisor 后在其对照测试中未再出现同样停滞。

截至本次核对,该报告仍开放、没有维护者定论或已发布修复。这里提供的是可撤销的排查办法,不把它推广为所有 MASQUE、所有平台或 v1.19.32 都有的已确认缺陷,也不承诺切换后一定恢复。

按同一节点的新旧连接分流

观察到的情况下一步
一条下载不动,新建请求仍正常记录停住的时间、已接收数据和实际出站,再做单字段 IP 栈对照。
新旧请求都失败,或者 MASQUE 无法建连先处理配置、节点或连接本身的错误;单连接停滞报告不能解释全部断网。
只做短测试暂时正常保留观察结果,但不能据此排除长连接才出现的问题,也不必立刻扩大流量测试。

确认实际内核与 with_gvisor 构建能力

先保存当前可用配置的独立副本,记下目标节点名称、完整 ip-stack 原值、实际内核版本和下载工具的请求信息。图形客户端版本不是内核版本;命令行里另一个 Mihomo 副本也不能代表应用正在运行的那一份。

下列 mihomo 代表正在运行的内核可执行文件。嵌入客户端或路由器插件时,应按其实际路径调用;不要仅凭命令搜索路径中的另一个程序判断。查看版本输出中的 Use tags,确认是否包含 with_gvisor。

查看实际运行内核的版本和构建标签
mihomo -v

固定 v1.19.32 与报告使用的 94b13ae 源码均支持 MASQUE 的 ip-stack 字段。已核验实现中,空值归为 auto,而 auto 选择 mips;gvisor 要求编译时包含 with_gvisor。这里的 mips 是出站 IP 栈选项,不是安装内核时的处理器架构。

本次对照只适用于使用用户态 IP 栈的 MASQUE 配置。network 为 h3-l4proxy 时不经过该栈,不能用 ip-stack.mode 作同样对照;不要为了套用本文而切换 network。

缺少该构建能力时,固定源码会返回 gVisor IP stack requires the with_gvisor build tag。遇到这个错误应撤销测试,而不是反复重载。旧版或其他分支可能不认识或忽略字段;配置检查通过,也不能单独证明它实际使用了该字段。

部分语言的文档仍可能保留较早的 auto 说明,因此本文以明确版本的固定实现核对含义。v1.19.32 存在配置能力,不等于本次用户报告已经证明该正式版受影响。不要为这个对照盲目安装 Alpha 内核。

只在目标 MASQUE 节点中切换 ip-stack

改动位置是已有 type: masque 出站节点内部,ip-stack 与 type、server 等字段处于同一层。它不同于 TUN 入站的 stack;把 gvisor 写进 tun.stack,并不能完成这里的出站对照。

以下只是要合入目标节点的局部内容,不是一份完整配置。如果原来已有 ip-stack,只改它的 mode 并保留其他项;原来没有则记录这一点,便于结束测试后准确还原。

合入目标 MASQUE 节点的局部 YAML;不是根层或 TUN 配置
ip-stack:
  mode: gvisor

保留原配置,按单个节点进行对照

  1. 找到实际承载失败请求的节点

    在连接记录中确认请求使用目标 MASQUE 节点,而不是仅凭当前策略组名称猜测。保存原订阅或本地配置、目标节点原值,以及已有可用备用节点。

  2. 在可持久保存的副本修改 mode

    在自己维护的本地配置副本或客户端明确支持的持久覆写中,仅把该节点的 ip-stack.mode 改为 gvisor。远程订阅更新可能覆盖缓存;无法可靠保存时先联系配置维护方,不直接改临时文件。

  3. 检查配置并确认应用确实加载了它

    使用当前内核的配置检查;直接运行 Mihomo 时可按实际路径使用 -t 与 -f。保存后核对最终配置中的目标节点、运行内核和启动日志;有配置或构建错误就恢复原副本。

  4. 用新请求进行对照

    重新发起同一目标文件的请求,保持节点、网络和其他设置一致。已建立的旧 TCP 连接不能当成已经切换 IP 栈的新请求。记录结果后,再决定是否保留这次设置。

怎样判断对照有没有改善?

选用自己有权访问的非安装包测试文件,并预先限制测试时间与流量。先记录原设置下的表现,再以同一条件重试。无需照搬报告中的超大文件,也不要因为短测试没有复现就不断扩大下载量。

如果再次停住,在保留现有记录的同时发起一个新的短请求:旧下载不再增长、新请求仍正常,才与报告的特征接近。测速数字、单次网页打开或没有错误日志,都不能单独证明长连接已经恢复。

保存这五项验证结果

  • 实际内核版本、Use tags 和目标节点配置对应同一份正在运行的内核。
  • 最终配置只有目标 ip-stack.mode 按计划改变,原值与独立备份仍可用。
  • 同一目标文件的新请求能继续接收数据;同时记录限时结束、主动取消或自然完成,不能把三者混为一谈。
  • 停滞时的新连接对照、连接实际出站及短日志完整,未把普通断网或策略组切换误判为单连接故障。
  • 重新加载配置并再次选中该节点后,设置仍保存,真实请求结果与前一次相符;短测试的结论只适用于该观察时段。

失败时怎样回退并反馈?

出现配置错误、构建能力不足或联网变差时,恢复目标节点原有的 ip-stack 内容;原来没有该项,就撤销本次新增部分。重新加载并验证原配置,再切回此前已经可用的备用节点或配置,不用重装或清空全部数据来完成回退。

若 gvisor 对照改善了当前请求,也只说明这个环境中的临时结果;尚不能把它写成项目已修复。若两种设置都失败,或所有新连接也失败,应保存证据并按实际错误继续检查,不能强行归为同一 IP 栈问题。

反馈时提供真实内核版本和构建标签、平台、实际 mode、最小脱敏配置、请求停止的时间与接收量,以及同隧道新连接结果。移除 private-key、账号、订阅 Token 和其他敏感信息;没有必要公开完整凭据或为反馈持续传输大文件。

本文完成了官方文档与固定源码复核,没有在真实路由器上复现该故障,也没有独立验证报告者的性能数据。后续是否确认原因、发布修复或改变默认行为,应以项目维护者的新结论和明确版本记录为准。

参考资料