对软件开发者来说,代理问题往往不是「浏览器打不开网页」这么简单。你可能在同一台电脑上同时使用 GitHub 拉取代码、用 Git 推送远程分支,通过 npm 或 pnpm 安装依赖,用 pip 创建 Python 环境,再用 Homebrew 和 Docker 获取工具与镜像。浏览器打开网页,并不代表这些命令行程序都能正常访问网络;不同运行时对系统代理、环境变量和 DNS 的处理方式也不一致。本文以 Clash Verge Rev 或其他支持 Mihomo 内核的 Clash 客户端为例,从开发者的真实工作流出发,说明如何用 Clash TUN 模式统一接管终端流量,同时保留 Git 私服、企业内网和国内镜像的直连能力。
先说明一个重要原则:TUN 模式不是「打开后所有网络问题都会自动消失」。它解决的是一部分进程不读取系统代理、不会使用 HTTP_PROXY,或者通过原生 TCP、UDP 直接访问网络的问题;它不能替代正确的规则、稳定的节点、可信的 DNS 和清晰的网络拓扑。配置前请确认你所在地区的法律法规、公司安全制度和网络使用政策,并避免把公司代码、私有仓库凭据或内部域名发送到不受信任的代理节点。
开发者为什么需要统一接管终端流量
浏览器通常会遵循操作系统代理设置,因而很多人第一次遇到问题时会产生错觉:网页可以打开,Git、npm 或 Docker 应该也能用。但命令行工具的网络行为并不统一。Git 的 HTTPS 传输可能读取自己的代理配置,SSH 则通常直接建立 TCP 连接;Node.js 程序是否读取代理变量取决于使用的库,Python 的 requests 与某些异步客户端也可能有不同默认值;Docker CLI 发起的请求与 Docker daemon 发起的请求更不是同一个进程。
这种差异会产生一组非常典型的现象:GitHub 网页能访问,但 git clone 在 TLS 握手阶段超时;npm 官方源偶尔返回网络错误,但换成某个镜像后又能安装;pip install 卡在解析包索引,Homebrew 更新时长时间没有响应;Docker Desktop 能启动,拉取镜像却反复出现 i/o timeout。如果只在某个工具里单独填写代理,短期也许有效,但换到新项目、IDE 集成终端或 CI 脚本后,很容易遗漏。
TUN 模式的思路是在操作系统中创建虚拟网卡,把符合条件的连接交给 Clash 内核处理。应用不需要知道本地 HTTP 或 SOCKS 代理端口,只要它通过系统路由发起连接,Mihomo 就有机会根据域名、IP、进程和规则集进行分流。对开发者而言,这意味着可以把「每个工具分别配置」变成「在 Clash 中集中维护」,再对确实需要特殊处理的 Git SSH、容器 daemon 或企业域名补充例外规则。
git ls-remote、npm view、python -m pip index versions 与 docker pull。这样开启后才能判断究竟是哪一层发生了变化。
Clash TUN 模式的开启与基础设置
以 Clash Verge Rev 为例,先导入一份能够正常使用的配置,再进入设置或内核相关页面,找到 TUN、增强模式或服务模式入口。不同版本的名称和权限提示可能不同,但核心选项通常包括启用 TUN、自动路由、严格路由、栈类型以及 DNS 劫持。首次开启时,Windows 可能弹出管理员权限请求,macOS 可能要求允许系统扩展或网络相关权限;请只在确认客户端来源可靠、配置文件可信的前提下授权。
初次测试不建议一口气打开所有高级选项。可以先采用较保守的组合:开启 TUN 和自动路由,保持规则模式,使用客户端推荐的栈类型;如果启用严格路由后局域网打印机、公司内网或虚拟机无法访问,再暂时关闭它定位问题。所谓「全局 TUN」并不等于「所有流量都必须走代理」,真正决定出口的是规则和最终策略。你的目标应当是让需要跨境访问的开发服务稳定进入代理策略组,让内网、局域网和可信镜像继续直连。
DNS 是 TUN 配置中最容易被忽视的一环。域名如果在本地被解析成错误地址,后续即使连接经过代理,也可能遇到证书错误、连接重置或命中错误规则。对于使用 fake-ip 的配置,要确认 fake-ip 排除列表包含公司内网域名、路由器地址、打印机和某些需要返回真实地址的服务;使用 redir-host 时,则要观察本地 DNS 是否受到污染或被其他 VPN 接管。不要在系统、浏览器、Docker、代理客户端里同时启用多套互相竞争的 DNS 方案。
开启后先不要立刻拉取大型镜像或更新整个依赖树。打开 Clash 的连接面板,依次执行一个轻量测试,让面板显示实际访问的主机名和策略。若面板完全没有记录,而命令行已经失败,可能是 TUN 没有接管该接口、应用使用了特殊网络命名空间,或者请求还没真正发出;若能看到连接但策略为 DIRECT,则应优先检查规则顺序,而不是马上更换节点。
Git、HTTPS 与 SSH:两条链路分别处理
GitHub、GitLab 等代码托管平台常见两种远程地址。第一种是 https:// 开头的 HTTPS 地址,通常可以直接受益于 TUN,也可以在 Git 中显式指定代理。第二种是 git@host:owner/repository.git 形式的 SSH 地址,它建立的是 TCP 连接,不会因为你设置了 HTTPS_PROXY 就自动使用 HTTP 代理。很多开发者只配置了 HTTPS 代理,却仍然发现 SSH clone 超时,原因就在这里。
建议先查看当前远程地址与 Git 配置,避免把排错对象搞错:
git remote -v
git config --global --get http.proxy
git config --global --get https.proxy
ssh -T [email protected]
如果使用 HTTPS,可以让 Git 读取 Clash 的 mixed-port,例如:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
这里的端口只是示例,必须替换成客户端实际监听的端口。若已确认 TUN 能稳定接管 Git HTTPS,是否保留 Git 自身代理取决于你的维护习惯:两者同时存在时,Git 可能先走显式 HTTP 代理,再由代理客户端继续分流;如果端口改动,Git 配置却没有同步更新,就会出现「TUN 正常、Git 失败」的假象。企业内网仓库通常不应发送到公共代理,可以按主机单独设置直连,或通过 NO_PROXY 与 Clash 规则共同处理。
SSH 的处理方式有三种。第一种是优先使用 TUN,让 SSH 的 TCP 连接按照域名解析和路由规则进入代理;第二种是通过 SSH 的 ProxyCommand 调用本地 SOCKS 或 HTTP 转发工具;第三种是把远端改成 HTTPS 地址,适合不依赖 SSH 密钥转发的普通代码操作。若选择 TUN,必须在连接面板中确认目标主机命中了代理策略,而不是只看终端有没有返回错误。若公司网络对 SSH 端口限制严格,HTTPS 远程地址通常更容易穿过出口策略,但仍应遵守组织的仓库访问规定。
git ls-remote 测试轻量请求,再测试 clone;HTTPS 与 SSH 分开验证。不要在一次排错中同时改远程地址、节点、TUN 和 Git 代理,否则很难知道真正有效的改动是什么。
npm、pip 与 Homebrew 的分流策略
包管理器最适合采用「官方源或可信镜像二选一」的策略,而不是让每一次请求随机切换出口。npm、pip 和 Homebrew 都会访问多个域名,有时还会跟随重定向或调用额外的 CDN。你可以在 Clash 连接面板中观察实际主机,再把稳定、明确的域名放入规则;不要只凭工具名称写一条规则,因为同一个工具可能访问包索引、对象存储、签名服务和更新接口。
对 npm 来说,先查看当前 registry:
npm config get registry
npm ping
npm view lodash version
如果使用官方 registry,应该让相关域名进入稳定的代理策略组;如果公司或团队规定使用内部镜像,则应将内部 registry 域名放入直连或企业专用策略,并确认 TUN 的 DNS 能解析该内网地址。pnpm、Yarn 可能有自己的配置文件和缓存目录,不能假设修改 npm 配置后所有行为都同步。遇到安装失败时,要区分 DNS 失败、TLS 失败、权限错误、lockfile 冲突和包版本不存在,网络代理只能解决其中一部分。
pip 的索引、额外索引和 Git 依赖可能走不同路径。执行安装前可查看当前配置来源,检查用户目录、虚拟环境和项目配置是否互相覆盖。若使用私有 PyPI,建议把私有域名设为直连或企业线路,并避免在公共配置文件中写入带密码的完整 URL。TUN 解决的是请求路径,不能替代证书信任链;如果公司私有索引使用内部 CA,应按照公司文档安装 CA,而不是关闭 TLS 校验。
Homebrew 在更新 formula、下载 bottle 和访问代码托管平台时,可能出现多个连接目标。开启 TUN 后,如果更新命中代理而下载瓶装包仍失败,要在面板里分别观察元数据请求和实际下载请求。不要为了让一次更新成功而把所有域名永久设为全局代理;更合理的做法是记录失败主机、确认它属于官方发布基础设施,再添加精确的域名后缀规则。对于公司网络、内部 Git 或本地开发镜像,则应明确放在 DIRECT 或指定的内网策略组。
Docker、环境变量与系统化排错
Docker 是开发代理排错中最容易误判的部分。执行 docker pull 时,命令由 Docker CLI 发出,但真正访问 registry 的往往是 Docker daemon。即使当前终端已经设置 HTTPS_PROXY,daemon 也可能没有继承这组变量;Docker Desktop、Linux systemd 服务和远程 Docker 主机的配置方式各不相同。因此首先要确认你连接的是本机 daemon 还是远程上下文:
docker context show
docker info
docker pull alpine:latest
如果是 Docker Desktop,应在其网络或代理设置中按照官方说明配置,并通过 Clash 连接面板观察 registry、鉴权服务和镜像层下载地址。Linux 上的 daemon 常由 systemd 启动,需要在服务级别配置代理并重新加载;不要只修改 ~/.bashrc。如果镜像来自企业私有 registry,还要同步处理 CA 证书、登录凭据和内网 DNS。TUN 可以帮助宿主机上的部分连接,但容器内部、虚拟机内部和远程 daemon 可能拥有独立的网络路径,不能把它们当成同一层。
终端环境变量仍然值得保留,因为它对大量 SDK、脚本和包管理器都有效。可以在项目之外维护一个不提交到 Git 的代理环境文件:
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export ALL_PROXY=http://127.0.0.1:7890
export NO_PROXY=localhost,127.0.0.1,.local,git.internal.example.com
使用前检查变量是否真的进入当前会话,并确认大小写版本是否符合工具习惯。NO_PROXY 不应写得过于宽泛,例如把整个顶级域名加入排除列表,可能意外绕过代理;也不要把公司域名发送到公共节点。IDE 集成终端、任务运行器、launchd、systemd 和容器进程都可能拥有不同的环境变量,因此排错时要在「实际启动程序的环境」中验证。
推荐采用固定的五步排错法。第一步,确认 Clash 内核正在运行,TUN 网卡和权限状态正常;第二步,确认 DNS 返回结果与预期一致;第三步,在连接面板搜索真实主机名,查看是否有请求、命中的规则和最终策略;第四步,使用最小命令测试,例如 git ls-remote、npm ping 或轻量镜像拉取;第五步,再检查节点延迟、服务端限流、证书、凭据和工具自身配置。若日志显示 DIRECT,先改规则;若显示代理但握手失败,再检查节点与 DNS;若返回 401、403 或 429,则不要继续重复切换代理。
一套适合日常开发的稳定工作流
完成基础配置后,建议把 Clash 规则分成几类管理。第一类是代理开发平台与必要的鉴权域名,例如你实际使用的代码托管平台和包服务;第二类是企业内网、私有 Git、私有包仓库和局域网设备,明确走直连或专用策略;第三类是常见国内镜像,只有在确认镜像可信、证书和包完整性符合要求时才使用;第四类是未知或无法归类的流量,交给默认策略,但不要在开发机上长期使用完全不可预测的「自动选择」。
规则顺序同样重要。精确的 DOMAIN 或 DOMAIN-SUFFIX 规则通常应放在宽泛的 GEOIP、地区规则或兜底规则之前;否则一个本应代理的开发平台可能先被归类为直连。修改订阅配置时,优先使用客户端提供的覆写或自定义规则入口,避免直接改动会被下一次更新覆盖的原始订阅。每次更新后都要重新查看规则是否仍然存在,以及策略组名称是否发生变化。
当项目需要长期稳定运行时,可以把测试写进开发文档或脚本:启动项目之前检查代理端口是否可用,调用包管理器的轻量查询,确认 Git 远程地址和 Docker context,再开始耗时较长的构建。这样做的价值不只是节省几分钟,还能避免构建到一半才发现基础镜像或依赖包无法下载。对于 CI、远程开发机和服务器,最好在对应主机或网关上单独设计代理路径,不要假设桌面电脑上的 TUN 会自动覆盖它们。
相比只依赖浏览器插件或为 Git、npm、pip、Homebrew 分别复制一组代理参数,Clash TUN 模式的优势在于能够从系统路由层统一接管更多进程,再结合规则把开发平台送入稳定策略,同时为企业内网和可信镜像保留直连;一些仅支持单一协议、只覆盖浏览器,或需要每个工具重复配置的同类方案,在切换 IDE、容器 daemon 和 SSH 工作流时更容易出现遗漏。当然,Clash 也需要认真处理 DNS、权限、规则顺序和多层网络路径。如果你希望在一套可视化分流体系中集中管理这些开发流量,可以先从下面的下载页获取适合当前平台的 Clash 客户端。