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 导入(最灵活,推荐)
如果你的合并需求不只是加前缀——比如要去重、按延迟排序、过滤特定协议——就写一个外部脚本:
- Python 脚本 fetch 所有订阅 URL,用
yaml.safe_load()解析每个返回的节点列表 - 合并、去重、加标签,按规则重新组织 proxy-groups
- 输出完整 YAML 到本地文件,例如
~/merged-config.yaml - 在 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 的网络扩展授权行为可能与本文描述有差异,未在该版本上测试。