FlClash TUN 栈模式选择与验证指南
文章目录
- [FlClash TUN 栈模式选择与验证指南](#FlClash TUN 栈模式选择与验证指南)
-
- 先给结论:不要把"兼容性最好"当成固定属性
- 三种模式实际做了什么
-
- [`system`:TCP 和 UDP 均走系统网络栈](#
system:TCP 和 UDP 均走系统网络栈) - [`mixed`:TCP 走系统栈,UDP 走 gVisor](#
mixed:TCP 走系统栈,UDP 走 gVisor) - [`gvisor`:TCP 和 UDP 都走用户态 gVisor 栈](#
gvisor:TCP 和 UDP 都走用户态 gVisor 栈)
- [`system`:TCP 和 UDP 均走系统网络栈](#
- 场景决策:按故障类型,而不是按设备标签盲选
-
- [场景一:真 Mac 上 Codex、浏览器、Git 都正常](#场景一:真 Mac 上 Codex、浏览器、Git 都正常)
- 场景二:黑苹果作为主力开发机,尚未做过稳定性验收
- [场景三:只有视频会议、游戏、HTTP/3 或语音类应用异常](#场景三:只有视频会议、游戏、HTTP/3 或语音类应用异常)
- [场景四:Codex 流式输出断续,但网页也偶发失败](#场景四:Codex 流式输出断续,但网页也偶发失败)
- [场景五:切换网络、合盖唤醒后全局断网或 DNS 失效](#场景五:切换网络、合盖唤醒后全局断网或 DNS 失效)
- 可复现实验:用同一节点比较,而不是凭感觉切换
- 失败路径与容易误判的地方
-
- 反例:把节点拥塞误判为栈兼容性问题
- [反例:用 HTTP 状态码判断 Codex 可用性](#反例:用 HTTP 状态码判断 Codex 可用性)
- 反例:用一次测速判定"最优"
- [反例:黑苹果所有网络故障都归咎于 TUN 栈](#反例:黑苹果所有网络故障都归咎于 TUN 栈)
- 证据、验证边界与参考来源
- 最终建议
内容摘要:本文比较 FlClash/Mihomo 的
system、mixed与gvisorTUN 栈,面向真 Mac 与黑苹果的日常代理、Codex、Git 和 UDP 应用。核心结论是:没有脱离硬件、节点和网络环境的"绝对最优";system是原生硬件上的性能优先基线,mixed是黑苹果或 UDP 兼容问题的优先基线,gvisor仅用于前两者无法复现稳定时的兜底。文中以 Mihomo 和 sing-tun 源码说明机制,并提供可复现实验和判定规则。
先给结论:不要把"兼容性最好"当成固定属性
这三个选项是 FlClash 的 TUN IP 栈实现,决定被 TUN 接管的流量如何在本机解析和转发;它们不改变订阅节点、节点所在地区、节点拥塞或到 OpenAI 的国际线路。因此,切换栈模式不能把一个慢节点变快,也不应替代节点测速。
对大多数用户,建议按下表先选一个基线,再只在同一节点、同一网络下做对照测试。
| 设备与目标 | 首选 | 何时换下一项 | 原因与边界 |
|---|---|---|---|
| Apple Silicon / Intel 真 Mac;浏览器、Codex、Git 都稳定 | system |
出现可复现 UDP、DNS、睡眠唤醒后断网等异常 | TCP 和 UDP 都由系统栈处理,路径最直接;"最直接"不是所有网络下必然最快。 |
| 黑苹果;网卡、Wi-Fi、USB 网卡或睡眠唤醒稳定性未知 | mixed |
mixed 下仍有可复现异常,再测 gvisor |
TCP 保留系统栈,UDP 改由 gVisor 处理,优先保留高频 Web/Codex/Git 的系统 TCP 路径,同时隔离 UDP 的一部分边缘问题。 |
| 特定网络或软件仅在前两者下失败,且日志/对照实验证明与栈有关 | gvisor |
修复设备驱动、MTU、DNS 或规则后回测前两者 | TCP、UDP 都由 gVisor 用户态栈处理;它是排障选项,不是通用性能模式。 |
| 只需要 Codex,当前连续对话、流式输出和 Git 均稳定 | 保持现状 | 只在可复现故障或横向测试胜出时切换 | Codex 的主流流量是 HTTPS/TCP;因此 system 与 mixed 的关键差异通常不在 Codex 的 TCP 流式请求。 |
黑苹果的实用默认值是 mixed,但它不是逻辑上"兼容性最优"的保证。 黑苹果的风险来自具体网卡、驱动、睡眠唤醒、路由与 DNS 配置;若这些没有问题,system 可能同样稳定,且更简单。若黑苹果上的 Codex、浏览器和 Git 已经长期稳定,不应仅因设备标签而切换。
三种模式实际做了什么
system:TCP 和 UDP 均走系统网络栈
Mihomo 的 TUN 配置把 stack 传给 sing-tun 创建栈。system 栈通过本机系统网络接口处理 TCP、UDP 和 ICMP 转发;它不是"绕过 TUN",而是 TUN 收到流量后由系统栈完成协议处理。
这意味着它最贴近 macOS 正常网络路径,适合以下场景:
- 真 Mac 的日常浏览、Codex、IDE 扩展、Git HTTPS/SSH;
- 以 HTTPS/TCP 为主,追求简单路径和较低本机额外开销;
- 已确认网络切换、睡眠唤醒和 DNS 都稳定的黑苹果。
但 system 的稳定性仍受系统与驱动影响。例如,黑苹果在睡眠唤醒后网卡没有正确恢复时,切换栈模式未必能解决根因;先检查网卡驱动、默认路由、DNS 和 TUN 重连状态。
mixed:TCP 走系统栈,UDP 走 gVisor
mixed 不是模糊的"自动兼容模式",其当前上游实现有明确协议分工:它先构造 System,在处理 IPv4/IPv6 包时将 TCP 继续交给系统栈 ;遇到 UDP 时,将数据包注入 gVisor 的 UDP 转发器。ICMP 仍由系统部分处理。
所以,下面两种常见表述都不准确:
- "mixed 的 TCP 用 gVisor、UDP 用 system"------与当前源码相反;
- "mixed 一定比 system 更兼容"------它只改变 UDP 的处理路径,不能自动解决 TCP、节点、规则、DNS 或网卡驱动问题。
mixed 的价值在于:对 Codex、网页和 Git 这类 TCP 主导应用,保留 system 的行为;对 QUIC、HTTP/3、音视频、游戏、实时协作等 UDP 依赖更高的流量,提供不同于系统栈的处理路径。因此它适合作为黑苹果的保守起点,或在 system 下仅 UDP 类应用出现问题时的第一对照组。
gvisor:TCP 和 UDP 都走用户态 gVisor 栈
gvisor 创建用户态的 TCP、UDP、ICMP 协议栈,并将 TUN 数据包交给它处理。它能避开一部分系统协议栈或驱动交互差异,但会增加一个用户态协议实现和数据转发路径。
适用例子:
system与mixed都能复现同一个 TUN 流量异常,而切到gvisor后异常消失;- 需要暂时规避设备/系统栈的特定缺陷,并接受额外资源消耗或不同网络行为;
- 以问题定位为目标,先确认故障是否与系统栈相关。
不应把它当作"最高兼容"或"最高性能"预设。它本身也有实现边界;若故障来自节点、分流规则、DNS 上游、MTU 或真实网卡驱动,gVisor 可能无效,甚至让问题更难定位。
场景决策:按故障类型,而不是按设备标签盲选
场景一:真 Mac 上 Codex、浏览器、Git 都正常
选择 system。例如,Codex 能持续输出、浏览器能稳定打开 ChatGPT、git fetch 无中断,且睡眠唤醒后这些行为仍正常。此时切到 mixed 没有已知收益:Codex 与 Git 的核心 HTTPS/TCP 流量在 mixed 下仍优先经过系统栈。
场景二:黑苹果作为主力开发机,尚未做过稳定性验收
先用 mixed 建立基线。它对 TCP 主导的 Codex/IDE/Git 保持系统路径,同时把 UDP 与系统路径解耦一部分。然后在相同节点、相同网络条件下与 system 对照;若 system 同样稳定、延迟更低或资源更少,可以切回 system。
这里的判断是工程上的风险控制,不是对黑苹果作普遍性能断言。以太网 Intel 网卡、免驱 USB 网卡、无线网卡和不同 OpenCore/Kext 组合的结果可能完全不同。
场景三:只有视频会议、游戏、HTTP/3 或语音类应用异常
优先从 system 切到 mixed。这类应用更可能触及 UDP 路径,而 mixed 恰好只改变 UDP 的协议栈路径。验证应包括具体应用的登录、语音/视频建连、持续 10 分钟播放或通话,以及网络切换后的恢复;只测一个网页的首屏打开不足以证明修复。
场景四:Codex 流式输出断续,但网页也偶发失败
不要直接判定为栈模式问题。先固定节点,排除节点抖动和分流误配;再检查 DNS、默认路由、TUN 状态、睡眠唤醒后的网卡状态。只有在同一节点、同一网络下,system 与 mixed/gvisor 存在可重复的成功率差异,才把栈模式视为有效变量。
对 Codex 本身,优先观察:持续输出是否中断、重连频率、API HTTPS 请求成功率与 Git 操作成功率。延迟必须看多次分布,而不是看一次最快值。
场景五:切换网络、合盖唤醒后全局断网或 DNS 失效
先重启 TUN 或 FlClash,并检查默认路由与 DNS;不要把模式切换当成唯一修复。若重启后恢复、再次唤醒又出问题,优先怀疑驱动、电源管理或 TUN 路由重建。此时记录系统日志和复现步骤,比反复切换三种模式更有价值。
可复现实验:用同一节点比较,而不是凭感觉切换
实验设计与判定标准
每轮只改变 stack,其他条件保持一致:同一个代理节点、相同规则、同一网络、TUN 均已完全重连。每种模式至少测试 10 次 HTTPS 请求,并做一次 Git 只读访问;涉及 UDP 应用时再测试具体 UDP 业务。切换后等待连接重建完成,旧长连接不计入新模式结果。
| 维度 | 通过标准 | 不足以证明什么 |
|---|---|---|
| HTTPS 连通性 | 10 次请求均得到 HTTP 响应;无 curl 超时 | 不证明 Codex 已登录或可用,也不证明节点最优。 |
| 延迟分布 | 比较 10 次总耗时的中位数、P95 和失败数 | 单次最低值不能代表模式更快。 |
| Git | git ls-remote 返回远端引用 |
不证明私有仓库权限或 SSH 代理配置。 |
| Codex | 连续两段较长流式输出无中断、无明显重连 | 不证明所有模型、所有时段和所有节点均稳定。 |
| 网络恢复 | 睡眠唤醒或切换 Wi-Fi 后重新完成上述检查 | 不证明黑苹果驱动长期没有问题。 |
基础只读检查命令
以下命令不包含令牌,不会修改仓库或远端数据。/v1/models 返回 401 也可以说明网络已到达 OpenAI API;它不表示 API 身份认证成功。
zsh
# 记录默认出口与 DNS,切换栈前后都各执行一次。
route -n get default | rg 'gateway|interface'
scutil --dns | rg -m 6 'nameserver\\[[0-9]+\\]'
# 连续 10 次测到 OpenAI API 的 HTTPS 建连与总耗时。
# 不携带密钥时,预期 HTTP 状态通常为 401,而不是 curl 错误。
for attempt in {1..10}; do
curl --connect-timeout 10 --max-time 20 --silent --show-error \\
--output /dev/null \\
--write-out 'attempt=%{num_connects} code=%{http_code} tcp=%{time_connect}s tls=%{time_appconnect}s total=%{time_total}s\\n' \\
https://api.openai.com/v1/models
done
# Git 只读连通性;选择公开仓库,避免把凭据写入日志。
git ls-remote https://github.com/git/git.git HEAD
建议把每轮结果记成下面的表,不要只写"感觉更快"。
| 日期与网络 | 节点 | TUN 栈 | HTTPS 成功/总数 | 总耗时中位数 / P95 | Git | Codex 连续输出 | UDP 应用 | 唤醒后复测 | 结论 |
|---|---|---|---|---|---|---|---|---|---|
| 例:家中 Wi-Fi | 固定节点 A | mixed |
10/10 | 0.42s / 0.61s | 成功 | 成功 | 成功 | 成功 | 可作为基线 |
一个可执行的选择规则
- 若
system的 HTTP 成功率、Codex 与 Git 均为 100%,且 UDP 业务和唤醒恢复也稳定,保留system。 - 若故障仅集中在 UDP 类业务,且
mixed使其消失,同时 TCP 指标没有变差,选mixed。 - 若
system、mixed都在同样条件下失败,而gvisor连续多轮稳定,暂用gvisor,并把 MTU、DNS、路由和网卡驱动列为后续根因排查项。 - 若三个模式同时失败,停止切换模式;问题更可能在节点、订阅、分流、DNS 上游、局域网或 ISP 路径。
失败路径与容易误判的地方
反例:把节点拥塞误判为栈兼容性问题
晚上节点拥塞时,切换 system → mixed 恰好恢复,并不能说明 mixed 更好;节点可能恰好自动切换、远端负载下降,或 DNS 缓存命中。必须锁定节点和网络,重复多轮对照,才能建立因果关系。
反例:用 HTTP 状态码判断 Codex 可用性
对 https://api.openai.com/v1/models 的无凭据请求返回 401,只证明 TCP/TLS/HTTP 已到服务端;返回 403 也可能是访问策略,而非本地断网。判断网络层优先看 curl 是否超时、TLS 是否完成和多次成功率;判断 Codex 业务层则必须在已登录的 Codex 中测试真实对话。
反例:用一次测速判定"最优"
一次请求会受 DNS 缓存、连接复用、TLS 会话、远端负载和无线瞬时干扰影响。要至少比较成功率、中位数、尾延迟和恢复能力;对开发场景,偶发中断的成本通常高于均值相差几十毫秒。
反例:黑苹果所有网络故障都归咎于 TUN 栈
若网卡驱动本身掉线、睡眠唤醒没有恢复接口、USB 网卡省电或 DHCP/IPv6 异常,三个 TUN 栈都可能表现不稳定。mixed 是一个可验证的缓解路径,不是驱动修复方案。
证据、验证边界与参考来源
已核实的事实
| 判断 | 一手证据 | 覆盖范围 |
|---|---|---|
Mihomo 接受 gvisor、system、mixed 三个 TUN 栈值 |
Mihomo constant/tun.go 与 示例配置 |
当前 Alpha 分支的配置/枚举。 |
Mihomo 将选定栈传入 tun.NewStack |
Mihomo listener/sing_tun/server.go |
当前实现的创建路径。 |
mixed 先构造 System,TCP 使用系统部分、UDP 注入 gVisor |
sing-tun stack_mixed.go |
当前上游代码;未来版本可调整实现。 |
gvisor 注册 TCP、UDP、ICMP 转发器 |
sing-tun stack_gvisor.go |
当前带 with_gvisor 构建标签的实现。 |
本文没有证明的事情
- 没有对某一台具体黑苹果、某个 FlClash 版本或任一订阅节点做压力测试;
- 没有证明某个模式在所有 macOS 或所有黑苹果上最快;
- 没有证明生产网络、特定 OpenAI 账号或全部 Codex 功能可用。
因此,本文的"首选"是按协议路径与风险最小化给出的起点,不是替代上述实验的绝对结论。
最终建议
- 真 Mac、当前稳定: 用
system,不要为理论兼容性无故切换。 - 黑苹果、未做验收: 从
mixed开始;完成同节点、同网络的三模式对照后,以成功率、尾延迟和唤醒恢复结果决定是否留在mixed或回到system。 - 前两者均复现故障: 用
gvisor做有界验证;若它改善,先作为临时方案,同时排查网卡驱动、MTU、DNS、分流和路由。 - 只为 Codex: 不要用模式名称替代业务验收。持续输出、HTTPS 成功率、Git 只读访问及网络恢复能力,才是有效判断依据。
结论:mixed 不是绝对兼容性最优,而是在当前实现中"TCP 走系统、UDP 走 gVisor"的折中栈;真 Mac 稳定时优先 system,黑苹果应先以 mixed 为可验证基线,并由同条件实测而非经验口号决定最终模式。