Clash Verge Rev 到 v2.6 时代,TUN Stack 终于不用每次换 Wi-Fi 后手动重启——auto-detect-interface 能自动跟上网络接口切换。但订阅合并这块仍然容易踩坑:QuickJS 扩展脚本没有网络 I/O,没法在脚本里直接 fetch 多个订阅 URL 再合并。这篇文章把两个功能拆开说清楚。

切换 Wi-Fi 后 TUN 断流:auto-detect-interface 怎么生效?

笔记本用户在公司和家里之间切换网络时,最常见的场景是:合上盖子到办公室打开,Wi-Fi 换了,TUN 没跟上,所有走代理的流量全断。

TUN Stack 的 auto-detect-interface: true 解决的就是这件事。它让 Mihomo 内核在检测到默认路由接口变化时自动重新绑定,不需要手动重启客户端或重新开启 TUN。

在 Clash Verge Rev 的 TUN 设置中,YAML 配置如下:

tun:
  enable: true
  stack: gvisor
  dns-hijack:
    - 0.0.0.0:53
  auto-route: true
  auto-detect-interface: true

如果你同时连着两根网线或者 Wi-Fi + 有线,auto-detect 会跟默认路由。选错了接口的话关掉这个选项,手动写 interface-name: eth0

TUN Stack 三种模式:不是越新越好

Stack网络栈位置兼容性性能推荐场景
gvisor用户态最好中等日常办公、三端通用
system系统内核Linux 好 / macOS 需授权最高Linux 软路由、游戏 UDP
mixed混合中等较高特殊网卡、Docker 环境

gvisor 是 Clash Verge Rev 的默认选项,胜在不折腾。system 在 Linux 上性能明显更好,TCP 吞吐量能高出 15%-25%(根据 Mihomo 社区测试反馈),但 macOS 上每次开都要弹系统扩展授权。mixed 是 Mihomo v1.19.x 引入的,把 TCP 走 system、UDP 走 gvisor,适合游戏场景——TCP 控制连接走 system 追求低延迟,UDP 数据包走 gvisor 保证兼容性。

日常用户直接选 gvisor,不用纠结。 Linux 软路由用户想压榨性能再切 system。

订阅合并的两个路径:proxy-providers 还是外部脚本?

Clash Verge Rev 的增强管线有 4 种类型:Merge(YAML 深度合并)、Script(QuickJS 脚本)、Rules、Proxies/Groups。它们的执行顺序是:

全局扩展配置(Merge) → 全局扩展脚本(Script) → 订阅扩展配置 → 订阅扩展脚本

很多人想用 Script 里的 main(config, profileName) 同时 fetch 多个订阅 URL 并合并节点——这不可行。QuickJS 引擎没有网络 I/O 能力,fetch() 不存在。

proxy-providers 方案(不改脚本,直接聚合)

适合不想写脚本的用户。在配置里声明多个 provider,Mihomo 内核会自动拉取并合并:

proxy-providers:
  sub1:
    url: "https://your-sub-1.link"
    type: http
    interval: 86400
    override:
      additional-prefix: "[A]"
  sub2:
    url: "https://your-sub-2.link"
    type: http
    interval: 86400
    override:
      additional-prefix: "[B]"

additional-prefix 给每个来源的节点名称加前缀,避免混淆。限制是这些 provider 的节点不会在 QuickJS 脚本里展开,脚本只能看到 provider 的声明。

外部脚本 + Local 导入(最灵活,推荐)

如果你的合并需求不只是加前缀——比如要去重、按延迟排序、过滤特定协议——就写一个外部脚本:

  1. Python 脚本 fetch 所有订阅 URL,用 yaml.safe_load() 解析每个返回的节点列表
  2. 合并、去重、加标签,按规则重新组织 proxy-groups
  3. 输出完整 YAML 到本地文件,例如 ~/merged-config.yaml
  4. 在 Clash Verge Rev 中以 Local 类型导入该文件

每次需要更新时重新跑脚本,然后点一下客户端里的更新按钮。这条路虽然多一步,但自由度最高。GitHub Discussion #6107 里有用户反馈用 AI 生成的 Python 脚本跑通了整个流程。

两种合并方案取舍

维度proxy-providers外部脚本 + Local 导入
配置难度低,直接写 YAML中,需要基础 Python/Node
去重能力无,全量合并可脚本去重
节点排序可按延迟/协议排序
更新方式内核自动按 interval 拉取手动跑脚本 + 客户端点更新
跨订阅规则不支持支持自定义 proxy-groups

日常双订阅合并用 proxy-providers 就够。超过 3 个订阅或需要去重/排序,上外部脚本。

如果代理客户端在多网络环境下频繁断线

笔记本用户在办公 Wi-Fi、家庭宽带、移动热点之间切换时,客户端订阅更新和连接保活的稳定性是实打实的痛点。如果用 proxy-providers 聚合了多个订阅源,每次切换网络后自动拉取的健康检查也会跟着新接口走。

可以给各端的代理客户端固定订阅更新间隔,并配合 兼容 Clash / Singbox / V2Ray 的订阅 减少因订阅端网络波动导致的节点不显示问题。

验证 TUN Stack 是否正常工作

配置完 TUN 后,用两个终端窗口同时测试:

窗口 1 —— 看路由表:

# macOS / Linux
netstat -rn | head -20
# Windows
route print

确认 TUN 创建的虚拟网卡出现在路由表里,且默认路由指向它。

窗口 2 —— 测试实际流量:

curl -x http://127.0.0.1:7890 https://httpbin.org/ip

返回的 IP 应该是代理出口 IP,不是你本机 ISP 的 IP。

如果路由表里有但 curl 不通,优先检查 DNS hijack 是否生效:nslookup google.com 看返回的 DNS 服务器是不是 127.0.0.1:53 或你配置的 DNS。

未覆盖的边界

  • 本文以 Clash Verge Rev v2.5.x / v2.6 为基础,Mihomo 内核版本 v1.19.x。更早的版本 TUN 配置结构不同。
  • Linux 端 system stack 的性能数据来自社区反馈,未在 ARM 设备(树莓派)上验证。
  • 外部合并脚本的示例仅描述逻辑,不提供可直接运行的完整脚本——订阅格式差异大,需要根据实际返回结构调整解析逻辑。
  • macOS Sequoia 15.x 的网络扩展授权行为可能与本文描述有差异,未在该版本上测试。

相关阅读