前言:为什么终端流量没有跟随代理?
在浏览器里打开 Clash 的系统代理后,网页能够正常访问,并不代表终端中的所有请求也会自动走代理。开发者常用的 Git、SSH、Homebrew、npm、pip、Docker 等工具,各自采用的网络库、协议和代理设置方式并不完全相同。有的程序会读取操作系统的 HTTP 代理,有的只认环境变量,还有些直接建立 TCP 或 UDP 连接,完全不理会浏览器或桌面客户端的代理设置。
这就是常见的“浏览器可以访问,终端却超时”的原因。反复给每个工具写代理变量或单独修改配置,短期能解决问题,但容易出现代理地址不一致、终端窗口之间配置不同、关闭 Clash 后命令仍指向失效端口等情况。对于需要长期使用 Git、SSH 和包管理器的开发者,TUN 模式可以提供更统一的流量入口:Clash 在系统中建立虚拟网络接口,将符合路由条件的连接交给内核,再由规则决定走代理还是直连。
本文目标
理解 TUN 与终端代理环境变量的区别,配置一套适合开发工作的接管方案,并通过 Git、SSH、Homebrew 和 DNS 测试确认流量路径,而不是只凭浏览器能否打开网页来判断。
1先理解 TUN:接管流量不等于自动选择代理
系统代理通常是向操作系统登记一个 HTTP 或 SOCKS 代理地址。支持读取系统代理的应用可以使用它,但很多终端程序不会主动查询这一设置。TUN 模式则是在操作系统网络层创建虚拟网卡,通过路由将符合条件的网络包送入 Clash 内核。对不支持代理设置的程序来说,这种方式往往更透明;不过,TUN 只负责让流量进入 Clash,后续是否走代理,仍由配置中的规则、策略组和 DNS 处理共同决定。
因此,开启 TUN 后如果规则将目标判定为 DIRECT,该连接仍会直连;如果域名解析结果不符合预期、规则没有匹配到目标,流量也可能走到兜底规则。相反,若所有流量都被送入一个不可用的代理组,终端访问国内代码仓库、公司内网或局域网服务也可能失败。把“开启 TUN”理解为“所有终端请求必然经过代理”是不准确的。
适用场景
当命令行工具不支持 HTTP/SOCKS 代理、工具数量较多,或你希望按域名与规则统一管理流量时,可以考虑 TUN。若只有一两个工具需要代理,且它们支持标准代理变量,使用环境变量通常更简单,也更容易限定影响范围。
TUN 一般需要较高系统权限,Windows 上可能需要安装或启用虚拟网卡组件;macOS 可能要求授权网络扩展或 VPN 配置;Linux 则涉及内核路由、设备权限和防火墙。不同客户端的菜单名称会随版本变化,Clash Verge、Clash Verge Rev 和其他 Mihomo 客户端的开关位置不一定相同。配置前先确认客户端正在使用支持 TUN 的 Mihomo 内核,而不要只依据界面上是否存在一个名为“TUN”的选项。
2配置 TUN 与规则:从最小改动开始
建议先备份当前配置,再在客户端中启用 TUN。部分客户端提供图形化开关,会自动生成必要配置;如果你通过配置文件管理内核选项,可先参考下面的最小示例。实际字段支持情况以当前 Mihomo 内核版本和客户端说明为准,不要把示例整段覆盖到机场订阅配置中。
示例中的 auto-route 用于自动设置相关路由,auto-detect-interface 帮助内核识别出站接口,strict-route 用于加强路由接管,避免部分流量绕过虚拟网卡。stack: mixed 是一种常见选择,但在不同系统和网络环境下,system 或 gvisor 可能更合适;遇到连接异常时,应一次只调整一个选项并观察日志。dns-hijack 会影响 DNS 请求处理,不熟悉当前 DNS 配置时,不要随意叠加多套 DNS 接管方案。
终端流量进入内核后仍按规则匹配。以下内容展示的是规则思路,不是可以脱离现有策略组直接使用的完整配置。将 Developer 替换为你配置中真实存在的策略组名称,并确认这些规则排在可能提前匹配的宽泛规则之前。
规则需要结合你的使用方式调整。Git 操作可能连接代码托管网站、对象存储或自建服务器,单独匹配 github.com 不一定涵盖所有下载请求。SSH 连接通常通过目标主机和端口建立,使用 IP 地址连接时,域名规则也无法匹配;如果目标是自建服务器,应优先确认服务器地址、端口以及相应网络路径,而不是盲目添加宽泛的代理规则。公司 VPN、开发机、数据库和局域网服务通常需要保留直连路径。
避免规则冲突
订阅配置可能已经含有域名规则、规则提供者和兜底规则。重复添加相同规则未必会生效,规则先后顺序也会改变结果。修改前应查看客户端最终生效配置或连接日志,不要直接覆盖原有 rules、proxy-groups 与 DNS 设置。
3Git、SSH 与 Homebrew 的实际工作流
TUN 启用并不意味着需要删除所有终端代理变量。先检查当前 shell 是否已经配置了旧代理,再决定保留或清理。代理环境变量只影响会读取它们的程序;TUN 则从系统网络层接管符合路由条件的流量。两者同时启用时,个别工具可能先连到环境变量指定的本地代理,再由 TUN 处理这段连接,造成重复转发或排查困难。
Git:区分 HTTPS 与 SSH 远程地址
先查看仓库远程地址,确认当前使用的是 HTTPS 还是 SSH:
HTTPS 连接通常会访问代码托管平台的 Web 域名;SSH 则通常连接远程主机的 SSH 端口,常见为 22,但也可能使用服务商提供的其他端口。若 HTTPS 失败,检查域名规则和策略组;若 SSH 失败,检查主机名能否解析、目标端口是否可达,以及网络或服务商是否限制该端口。不要把 Git 的 HTTPS 代理配置当作 SSH 代理配置,它们不是一回事。
如果此前为 Git 单独设置过代理,可检查配置来源并按需移除。删除前确认该设置不是公司网络或特定项目所必需;也可以仅在当前项目中调整,而不改动全局配置。目标是避免旧的代理地址与当前 Clash 端口不一致,而不是不加判断地清空所有 Git 设置。
SSH:确认端口与连接方式
排查 SSH 时,可使用详细日志观察客户端解析到的主机、尝试连接的地址和端口:
如果连接停在建立 TCP 连接阶段,重点查看 TUN 是否接管该目标、规则是否匹配,以及出口策略是否可用;如果已连接但认证失败,则问题更可能在 SSH 密钥、账号权限或服务端配置,不应继续反复调整代理。对于只支持代理跳转的网络环境,可以通过 SSH 自身的代理或跳板机配置实现,但这属于 SSH 客户端层面的设置,应与 TUN 路由分开诊断。
Homebrew:检查下载域名和终端继承环境
Homebrew 安装软件时可能访问公式仓库、代码托管平台和发布文件存储服务,涉及的域名并不总是只有一个。运行安装或更新命令后,可在 Clash 的连接页面观察实际请求,并确认每个目标命中了预期策略。若连接日志没有对应记录,检查 TUN 权限、系统路由和 DNS;如果日志有记录但失败,进一步确认策略组选择的节点、错误信息以及目标站点是否可达。
需要临时使用环境变量时,可以在当前 shell 会话中设置 HTTP 与 HTTPS 代理,并在完成后取消;但地址和端口必须与客户端实际监听值一致。TUN 已覆盖目标流量且终端变量没有遗留时,不必为了“让命令行代理”而机械地为每个工具增加一份代理配置。
4验证连接路径与常见故障排查
验证应从简单到具体,分别检查客户端、域名解析、HTTPS 请求和实际开发命令。首先确认 TUN 开关已启用、内核运行正常、系统权限授权完成,并在 Clash 日志或连接列表中观察新连接。然后使用下面的命令查看终端是否存在代理变量,并测试 HTTPS 请求能否完成。请求成功只证明该请求可达,不能单独证明它使用了预期节点;最终还要对照 Clash 的连接记录和所选策略。
在部分终端中,env | grep -i proxy 没有输出是正常的:它表示当前 shell 没有匹配到代理环境变量,并不能证明 TUN 失效。反过来,如果输出了旧的 HTTP_PROXY 或 HTTPS_PROXY,也不代表请求一定经过当前 Clash。测试时应结合连接日志、规则命中结果和目标程序输出判断。
- 浏览器正常,终端请求失败:确认客户端使用的内核支持 TUN,系统权限已经批准,并检查终端是否配置了失效的代理变量。
- Clash 日志中看不到终端连接:检查虚拟网卡、系统路由、客户端运行状态和系统防火墙;如果仅 DNS 查询缺失,还要检查 DNS 劫持及系统解析路径。
- 日志显示连接为直连:检查命中规则、规则顺序、目标域名以及兜底策略。TUN 接管与代理分流是两个不同环节。
- Git HTTPS 成功但 SSH 超时:检查 SSH 目标端口和主机解析,确认该连接是否有匹配规则;HTTPS 规则不一定覆盖 SSH 连接。
- 国内站点或内网失效:检查是否误将局域网和公司网段送入代理,必要时按网络环境补充直连规则,并确认没有与其他 VPN 路由冲突。
- 开启 TUN 后整机断网:先关闭 TUN 恢复网络,再查看内核日志、DNS 设置和路由冲突;不要在失去网络时继续叠加多项配置修改。
如果所在网络使用公司 VPN、容器网络或多网卡环境,TUN 可能与现有路由产生冲突。建议先在个人网络中验证基本功能,再逐项恢复 VPN、容器或防火墙设置。每次只修改一个变量,例如先确认 DNS,再测试规则,最后调整 TUN 栈类型;保留修改前的配置,便于出现问题时快速回滚。
对开发者来说,稳定的方案通常不是“所有东西都强制走代理”,而是确保目标请求能被正确接管、规则能够解释流量去向,并让内网与本地开发服务保持可用。建立清晰的连接验证习惯后,Git、SSH、Homebrew 等工具出现网络问题时,就能区分是代理、DNS、端口、认证还是服务端故障。