为什么终端工具需要 TUN 模式
浏览器能打开 GitHub,不代表 git、npm、pip 或 Docker 一定能连接。常见原因是浏览器遵循了操作系统的 HTTP 代理设置,而终端程序可能使用自己的代理选项,或者直接建立 TCP、UDP 连接。Git、包管理器和容器工具各有代理配置入口,逐个设置既容易遗漏,也可能因环境变量、子进程和配置文件不同而产生结果不一致。
系统代理与 TUN 解决的是不同层面的问题。系统代理主要告诉支持代理设置的应用把请求交给本机 HTTP 或 SOCKS 监听端口;TUN 则通过虚拟网络接口接管符合路由条件的 IP 流量,再交给 Clash 内核处理。终端程序不必理解 Clash 的代理端口,也可能因此进入内核。不过,TUN 只负责流量入口,连接进入内核后仍要经过规则判断:命中 DIRECT 就直连,命中代理策略组才使用节点。
本文配置示例面向支持 TUN 的 mihomo 内核及相应客户端。Clash Verge、Clash Verge Rev 等客户端的菜单名称会随版本和内核有所变化;只看到客户端名称,不能据此确认正在运行的内核支持哪些字段。开始前先在客户端的内核信息或启动日志中确认内核类型与版本,并检查当前配置是否处于规则模式。
先准备代理策略与规则
在开启 TUN 前,先确认配置里存在可用的代理节点或策略组。下面假设已有名为 代理 的策略组;若实际名称不同,请将规则中的名称改成配置里完全一致的名称。示例只展示与开发工具有关的规则,不是完整配置,不能覆盖订阅中的节点、DNS、代理组或其他规则。
mode: rule
log-level: info
tun:
enable: true
stack: mixed
dns-hijack:
- any:53
auto-route: true
auto-detect-interface: true
rules:
# 开发平台及常见包仓库
- DOMAIN-SUFFIX,github.com,代理
- DOMAIN-SUFFIX,githubusercontent.com,代理
- DOMAIN-SUFFIX,githubassets.com,代理
- DOMAIN-SUFFIX,npmjs.org,代理
- DOMAIN-SUFFIX,pypi.org,代理
- DOMAIN-SUFFIX,pythonhosted.org,代理
- DOMAIN-SUFFIX,docker.io,代理
- DOMAIN-SUFFIX,docker.com,代理
# 其余规则应继续放在这里
- GEOIP,CN,DIRECT
- MATCH,代理
tun 与 rules 都是顶层字段。合并时应编辑现有字段,而不是在 YAML 中重复创建第二个 tun:、rules: 或 mode: 映射。stack: mixed 是 mihomo 支持的 TUN 协议栈选择之一,但并非所有旧内核都支持;若配置检查提示字段或取值未知,应先核对内核版本,不要不断添加互相冲突的选项。
规则按从上到下的顺序匹配。这里将常见开发站点放在 GEOIP,CN,DIRECT 之前,是为了避免目标 IP 被归入 CN 后提前直连。域名规则只覆盖列出的域名及其子域名,实际请求还可能依赖额外的登录、鉴权、镜像或对象存储域名。若某个工具仍失败,应从连接列表查看实际目标域名、命中规则和最终策略,再补充经过核实的域名规则,而不是直接把所有连接改成全局代理。
开发者可能需要按项目选择代理或直连。例如公司内网代码仓库应保留在规则前部并指定 DIRECT,而公共仓库使用代理。对单个域名的例外规则要放在更宽泛的规则之前,否则后续规则无法覆盖已经命中的策略。GEOIP 依赖内核使用的 IP 数据,不能替代对明确业务域名的策略设置。
| 工具或服务 | 常见目标 | 排查重点 |
|---|---|---|
| GitHub | github.com、githubusercontent.com | 确认 Git 的 HTTPS 或 SSH 连接是否进入内核;检查实际命中的域名规则 |
| npm | registry.npmjs.org 及其他 npm 域名 | 用 npm config get registry 查看当前 registry,确认其域名有对应策略 |
| PyPI | pypi.org、files.pythonhosted.org | 包索引与文件下载可能访问不同主机,查看失败日志中的实际域名 |
| Docker Hub | docker.io、docker.com 及认证或镜像地址 | 区分 Docker Desktop 虚拟机流量与宿主机流量,检查认证和镜像下载阶段 |
Windows 与 macOS 上启用 TUN
在图形客户端中通常应先导入并更新配置、选择规则模式,再到设置或内核相关页面打开 TUN。具体开关名称和位置因客户端版本而异,不要照搬其他版本的截图。若客户端允许选择内核,优先确认配置字段与当前内核相符;修改后让客户端重新加载配置,并观察启动日志中是否出现 TUN 初始化成功、虚拟网卡创建成功或路由设置成功等信息。
Windows:检查管理员权限与路由冲突
Windows 上创建虚拟网卡和调整路由通常需要客户端服务或管理员权限。若 TUN 开关打开后立即失败,先按客户端提示提升权限,确认安全软件没有阻止虚拟网卡或相关服务,再查看内核日志。设备管理器中可以检查是否出现相应的虚拟网络设备;若设备反复启停,应先关闭其他可能同时接管流量的 VPN、虚拟网卡工具或旧代理服务,然后只保留一套接管路径进行测试。
Windows 上的系统代理开关不等同于 TUN。某些客户端允许两者同时开启,但在排查阶段建议记录各自状态,避免误以为关掉系统代理就会停止 TUN,或者以为打开系统代理便已覆盖不遵循代理设置的终端程序。配置更改后可在客户端连接列表中观察测试连接是否出现,再确认其规则与出站策略。
macOS:检查系统授权与网络扩展
macOS 上的 TUN 接管通常需要客户端申请网络扩展、VPN 配置或相应系统授权。首次启用时按系统提示完成确认;如果授权被拒绝或系统设置中显示扩展未启用,重启客户端并检查系统设置里的网络或隐私与安全相关提示。不同 macOS 版本的设置分类可能变化,应以系统实际弹出的授权说明为准。
Mac 同时运行其他 VPN、网络过滤器或安全软件时,路由与 DNS 接管可能相互影响。建议先断开其他 VPN,只用 Clash 做单一测试;如连接列表没有终端请求,再检查 TUN 状态、活动网络接口和客户端日志。切换 Wi-Fi、有线网络或热点后,若自动检测接口未能选中正确出口,可重新连接网络并重启内核,再验证默认路由是否恢复。
- 备份当前配置,确认代理组可用,并将运行模式设为规则模式。
- 启用 TUN,按系统提示完成权限或网络扩展授权;不要同时启用多个流量接管工具。
- 重新加载配置,确认内核启动日志没有 YAML、权限或虚拟网卡错误。
- 用一个已知目标发起终端请求,在连接列表核对目标、规则、策略组和出口。
- 验证完成后再逐项恢复其他 VPN、DNS 工具或网络过滤软件,找出发生冲突的组件。
验证 Git、npm、PyPI 与 Docker 流量
验证时一次只测试一个工具,避免并行下载让日志难以对应。先清空或记下连接列表中的时间点,再执行请求;测试完成后查看目标域名、规则命中、策略组与最终节点。命令返回超时只能说明该次操作没有按预期完成,不能单凭这一点判断是 TUN、DNS、规则还是远端服务故障。
# 查看 Git 当前代理配置
git config --show-origin --get-regexp 'http\..*\.proxy|https\..*\.proxy'
# 测试 GitHub HTTPS 连接
git ls-remote https://github.com/git/git.git HEAD
# 查看 npm registry 并测试元数据请求
npm config get registry
npm ping
# 查看 pip 当前配置,再执行一次短请求
python -m pip config debug
python -m pip index versions pip
# 查看 Docker 客户端及拉取状态
docker info
docker pull hello-world
示例中的 Git 仓库和软件包用于说明诊断方式,测试结果还会受网络可用性、软件版本、认证状态及服务端限制影响。git config --show-origin 有助于发现仓库级配置、用户级配置或系统级配置中的显式代理。若 Git 已配置某个本机代理端口,而 TUN 也在接管,连接可能走显式代理,也可能因配置过期而失败;排查时应明确选择一种路径,避免同时保留无效的旧端口。
npm 与 pip 可能有独立的 registry、索引或代理设置。用 npm config get registry 和 python -m pip config debug 确认当前生效值;不要只查看某个配置文件后就假定命令实际使用了它。包管理器访问索引成功但下载失败时,通常应检查日志中的文件主机名是否也有对应的分流规则。
Docker Desktop 尤其需要单独验证。它通常通过虚拟化环境运行 daemon,容器镜像请求不一定等同于宿主机 shell 发起的普通连接,也不保证都由宿主机 TUN 以同样方式接管。若 docker pull 失败而其他终端请求成功,应检查 Docker Desktop 的代理设置、daemon 代理环境、镜像仓库配置和认证状态,并查看其自身日志。不要把容器内部 DNS、Docker daemon 出站和宿主机终端连接当成同一条网络路径。
如果某个命令仍未出现在 Clash 连接列表,先验证 TUN 确实启动,再确认操作系统是否将该流量路由到虚拟接口。对于显式设置了代理的程序,检查环境变量与配置文件;对于 SSH、Docker Desktop 或虚拟机流量,则单独核对其出站路径。若连接已经出现但规则为 DIRECT,这是分流问题,不是 TUN 没有工作。
常见故障:按流量入口、DNS 与规则定位
浏览器能用,终端不通:浏览器可能使用系统代理,终端可能绕过系统代理。检查终端请求是否出现在连接列表;若完全没有,排查 TUN 授权、虚拟网卡、路由和应用自身代理配置。若已经出现,检查规则与策略组,不要先反复切换节点。
域名解析失败:查看客户端 DNS 日志和连接列表中出现的目标。如果 DNS 请求没有进入预期内核,检查 TUN 的 DNS 接管配置、系统 DNS 设置以及其他 DNS 软件是否争用。若提示解析失败的是代理服务器域名,而不是 GitHub 或软件包域名,应单独检查节点域名解析;两种解析链不能混为一谈。
请求命中代理但仍超时:先确认策略组当前选择的是可用节点,再区分连接失败发生在节点服务器还是目标站点。轮换同组节点可以帮助判断,但测速成功不等于 Git、HTTPS 下载或 Docker 镜像请求都正常。结合日志中的地址、端口、错误阶段和连接列表确认问题位置。
开启 TUN 后局域网或公司内网不可用:检查是否有针对内网网段、内网域名和企业服务的直连规则,并确认本地路由没有被 VPN 或虚拟网卡覆盖。不要为了让一个内部仓库可用而将所有流量改为直连;应先识别该服务的实际域名或地址,再建立范围尽可能小的例外规则。
命令提示证书或 TLS 错误:这不一定是 TUN 故障。检查系统时间、证书信任、TLS 检查软件和目标主机名;如果连接已经按预期到达节点,继续查看 TLS 握手阶段的报错。不要通过关闭证书验证来掩盖网络或证书链问题。
常见问题
开启 TUN 后还需要打开系统代理吗?
不一定。TUN 与系统代理是两种流量入口,有些客户端允许同时开启,但测试时应记录两者状态。若目标是让不读取系统代理设置的终端程序进入内核,重点是确认 TUN 接管成功,而不是单独依赖系统代理开关。
还要设置 HTTP_PROXY 或 HTTPS_PROXY 吗?
使用 TUN 接管时,通常不必为了让程序进入内核而给每个工具设置环境变量。但已有变量可能让程序主动连接旧代理端口,也可能是团队工作流明确要求的设置。先检查当前 shell 与工具配置,再决定保留或清理;避免同时指向不可用端口并误判为 TUN 故障。
Git 使用 SSH 克隆时也会走 TUN 吗?
如果客户端已正确接管相应 TCP 流量,SSH 连接可能经过 TUN,但是否成功仍取决于目标域名解析、规则、网络出口和服务端可达性。HTTPS Git 与 SSH Git 是不同连接方式,应分别测试;不要因 HTTPS 能用就推断 SSH 端口也可用。
Docker Desktop 的容器流量一定会被 TUN 接管吗?
不能保证。Docker Desktop 的 daemon 和容器可能处于虚拟化网络中,路径会受平台、版本及代理设置影响。宿主机终端测试成功不代表镜像拉取或容器内请求也使用同一出口;应结合 Docker Desktop 的代理配置、daemon 日志和 Clash 连接列表分别验证。