先把结论摆在前面

系统代理和 TUN 模式不在同一层。系统代理是应用层约定:操作系统把代理地址写进设置,应用主动来读,读了才走代理。TUN 模式是网络层接管:mihomo 创建一块虚拟网卡,内核把符合条件的 IP 包全部送进网卡,应用不知道代理存在,也无法绕过。

一句话:系统代理靠应用配合,TUN 模式靠内核路由。两者在命令行、游戏、UDP 场景下表现完全不同,根源就在这里。

系统代理:应用主动读取,代理才生效

开启系统代理后,Windows 在「设置」→「网络和 Internet」→「代理」写入地址,macOS 在「系统设置」→「网络」→「代理」写入同一份信息。mihomo 默认在 127.0.0.1:7890 监听混合端口,同时接受 HTTP 与 SOCKS5 连接。

关键在第二步:应用必须主动向系统查询代理设置,并真正用这个地址建立连接。于是出现四类分化:

  • 浏览器与多数 Electron 应用走系统网络 API,会读取,系统代理对它们有效。
  • 游戏引擎常直接创建 socket,不查系统代理,直接裸连。
  • curlwgetgit 在 Windows 与 macOS 上默认不读系统代理,只认 http_proxy / https_proxy 环境变量。
  • 所有 UDP 流量:HTTP 代理只承载 TCP;SOCKS5 虽有 UDP ASSOCIATE 扩展,绝大多数应用并不实现。

所以「开了代理,终端里 curl 还是直连」不是配置坏了,是系统代理的机制边界。对照如下:

流量类型系统代理TUN 模式
浏览器 HTTP/HTTPS接管接管
命令行 curl / git / brew不接管(需环境变量)接管
游戏与语音 UDP不接管接管
QUIC / HTTP/3不接管(浏览器降级 TCP)接管
局域网设备访问不受影响需排除内网段

TUN 模式:虚拟网卡接管 IP 层

TUN 是内核提供的虚拟网络设备。mihomo 开启 TUN 后创建虚拟网卡——Windows 用 wintun 驱动,macOS 用 utun,Linux 用 tun——再修改路由表,把非本机地址的 IP 包指向这块网卡。

流量路径因此改变:

  1. 应用把数据交给内核;
  2. 内核按路由表送入虚拟网卡;
  3. mihomo 在用户态读到完整 IP 包;
  4. 解出 TCP 或 UDP,按规则匹配;
  5. 经节点转发出去。

接管层级是网络层(L3),不是应用层(L7)。mihomo 不关心应用怎么发数据,只看到一个个 IP 包。三个直接结果:应用完全不知道自己在被代理;TCP 与 UDP 一视同仁;无论进程用什么语言、什么网络库,都逃不出路由表。

代价同样明确:创建虚拟网卡需要管理员或 root 权限;路由表被改动,内网与局域网访问需要额外放行。

DNS 是 TUN 模式容易忽略的另一半。TUN 配置里的 dns-hijack 把所有发往 53 端口的查询劫持到本地解析,配合 enhanced-mode: fake-ip,域名解析也走代理链路,避免 DNS 泄漏。以 Clash Verge 默认配置为例:

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  nameserver:
    - https://doh.pub/dns-query

开启后,解析无法直连的域名返回的是 198.18.0.0/16 段的 Fake-IP,真实解析由远端 DoH 完成——这是判断 TUN 是否真正生效的直观信号。

命令行、游戏与 UDP:两种模式的分水岭

命令行工具

git clonecurlbrewnpmgo install 在系统代理模式下全部直连。只想开系统代理就覆盖它们,需要手动导出环境变量:

export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

7890 是混合端口,HTTP 与 SOCKS5 共用,上面三行让 git、curl、npm 走同一个入口。TUN 模式下不需要这一步,残留的环境变量反而会造成重复代理,建议清掉。

游戏与 UDP

游戏匹配、语音、状态同步大量使用 UDP。系统代理在协议层面就不承载 UDP;即便开启 SOCKS5,游戏客户端也不会去实现 UDP ASSOCIATE。于是常见「能登录、匹配不到人」「语音时断时续」的半通状态。TUN 把 UDP 包原样收进虚拟网卡再按规则转发,表现接近直连。

QUIC 与 HTTP/3

Chrome、Safari 对支持 HTTP/3 的站点优先尝试 QUIC(UDP/443)。系统代理下浏览器检测到代理不支持 UDP,自动降级回 TCP;TUN 下 QUIC 流量直接被接管,不降级。

场景对照:什么时候用哪个

场景推荐模式理由
日常浏览网页系统代理无需管理员权限,资源占用低
开发与命令行TUN 模式一次性覆盖 git / npm / curl
游戏、语音、视频通话TUN 模式UDP 必须由网络层接管
公司内网与代理并存系统代理 + 规则内网段不接管,策略更可控
不允许程序申请管理员权限系统代理TUN 创建网卡需要提权
全局抓包、全量测试TUN 模式所有进程统一路径

切换前的检查清单

  • 连通性:用 curl -I https://www.gstatic.com/generate_204 验证,别用 ping——ICMP 是否被接管取决于节点与栈,不能作为代理生效的依据。
  • DNS:解析一个无法直连的域名,返回 198.18.x.x 说明 Fake-IP 生效;返回真实 IP 则检查 dns-hijackenhanced-mode
  • 局域网:打印机、NAS、路由器后台在 TUN 下可能被截走,在 tun 段加 route-exclude-address: 192.168.0.0/16,或用规则直连。
  • Windows 兼容:游戏或 P2P 连不上时,依次切换 stack: systemgvisormixed 再测。
  • 残留环境变量:系统代理模式下,终端执行 env | grep -i proxy,有残留就 unset,否则命令行会继续走旧代理。

最后提醒:两种模式不是二选一的单选题。日常浏览用系统代理,开发与游戏场景临时切到 TUN,是多数用户最省心的组合;如果网络环境固定、又不想每次手动切换,也可以把 TUN 常开,再在规则里把内网与国内域名直连,兼顾接管范围与访问速度。切换后记得用上面的清单复核一遍,确认 DNS、局域网与命令行三个环节都符合预期。

常见误区:开 TUN 后又开系统代理。两者不会叠加,浏览器流量只是多绕一步进 7890 再出来。TUN 模式下把系统代理开关关掉,路径最短,排查问题也更干净。