为什么浏览器能访问,Git 和 npm 却仍然超时

很多开发者第一次遇到终端网络问题时,会发现一个看似矛盾的现象:浏览器已经能正常打开代码托管平台,Clash 的系统代理也显示开启,但执行 git clone、npm install 或 docker pull 时仍然卡住。原因通常不是某一个软件「不支持 Clash」,而是不同程序采用的代理方式并不相同。浏览器一般会读取桌面系统代理设置;命令行程序则可能只认 HTTP_PROXY、HTTPS_PROXY 等环境变量,也可能自行建立网络连接,完全不查看系统代理。

Clash TUN 模式的作用,是通过虚拟网络接口和操作系统路由接管符合条件的流量,使没有代理设置选项的终端进程也有机会进入 Clash 的规则系统。它并不是「开启后所有请求必定走代理」的开关:实际结果仍受内核能力、系统权限、路由模式、规则顺序、DNS 处理和目标地址影响。理解这一点很重要,否则 TUN 开启后遇到连接失败,很容易误判成节点故障,或者为了验证而把所有流量长期切到全局代理。

本文以使用 Mihomo 内核的 Clash 客户端为思路,涵盖 Clash Verge、Clash Verge Rev 等常见桌面环境。各版本的菜单名称会有差异,具体选项也取决于客户端和系统版本,因此请以你当前界面和运行日志为准。排查目标不是「让终端能联网」这么笼统,而是确认某一个命令连接的目标主机是否被捕获、是否命中预期规则,以及最终从哪个出站策略组离开。

ℹ 先别同时改三处:开始验证时保留现有规则与节点,只确认内核正常、TUN 已接管、连接日志能看到测试请求。若同时切换规则模式、DNS、系统代理和订阅,出了问题就很难判断是哪一项造成的。

启用前的准备:内核、权限与现有代理

先确认正在运行的核心确实支持当前配置中的 TUN 功能。Clash 客户端是图形管理界面,真正负责创建虚拟接口、解析规则和建立代理连接的是内核;界面上有 TUN 开关,不代表旧内核一定能正确处理配置。若启动后日志提示未知字段、权限不足或设备创建失败,先核对客户端所使用的 Mihomo 版本与配置格式,再去怀疑节点。更新内核之前应备份配置,特别是有本地覆写、脚本生成规则或自定义 DNS 设置的环境。

TUN 通常需要系统授权才能创建虚拟网卡并修改路由。在 macOS 上,首次启用可能出现网络扩展或管理员授权提示;Windows 上可能需要管理员权限,并受到防火墙、安全软件或组织策略限制;Linux 上则要检查运行权限、TUN 设备和路由管理能力。请只批准来自可信客户端的必要权限,不要为了排障永久关闭系统防火墙、终端防护或设备管理策略。公司 VPN、零信任客户端和终端安全软件也可能安装自己的虚拟接口,它们与 Clash 同时接管路由时容易发生冲突。

在客户端设置中找到 TUN 或增强模式相关选项后,先查看是否有自动路由、严格路由、接口地址、DNS 劫持或栈类型等设置。不同客户端的默认值并不相同,不能把某篇教程里的开关状态直接当成所有机器的标准答案。日常使用通常应让局域网、回环地址和明确需要直连的目标保持可达;若设备上有 NAS、开发板、虚拟机或公司内网,先记录其网段和访问方式,再决定如何处理这些流量。

同时检查是否残留了其他代理配置。终端环境可能在 shell 启动文件中设置了代理变量,Git 也可能单独保存 HTTP 代理;即使 TUN 已经接管部分连接,这些设置仍可能让请求尝试连接已经失效的本地端口,或绕过你预期的规则路径。建议先查看当前值,再决定保留还是临时取消,而不是直接覆盖全局设置。可分别检查环境变量和 Git 自身配置,确认它们指向的端口确实存在、协议也与端口类型相符。

开启 TUN 后,按层验证是否真的接管终端

一个稳妥的验证顺序是:先启动 Clash 内核并确认状态正常,再开启 TUN,等待系统授权和虚拟接口建立,最后才运行测试命令。若客户端提供连接、日志或实时流量页面,保持该页面打开,以便在终端发起请求时观察新连接。先选择一个你已知可访问、且规则预期会走代理的 HTTPS 站点,再用一个本应直连的目标做对照。只看命令返回成功并不足以证明 TUN 生效;还要查看日志中的域名、匹配规则和出站策略,避免请求实际经由本机其他代理或缓存成功。

可以先用 curl 测试网页响应,再测试开发工具。若 curl 连接超时而日志里没有对应记录,优先检查 TUN 权限、系统路由与进程是否被排除;如果日志出现连接但命中直连规则,检查规则顺序和域名解析结果;如果命中代理策略却连接失败,再检查策略组是否选中可用节点以及该节点能否访问目标服务。DNS 失败和 TCP 连接失败要分开判断:前者常见表现是无法解析主机名,后者则可能解析成功但握手或传输阶段超时。

运行测试时尽量使用新的连接,避免浏览器缓存、DNS 缓存或已有长连接造成误判。可以重新执行一次请求、换一个明确的目标地址,并在 Clash 日志中按域名或进程过滤。如果系统支持按进程显示连接来源,应确认记录对应的是当前的终端程序,而不是浏览器或后台更新服务。连接日志里看到目标 IP 而不是域名时,也要考虑 DNS 映射、嗅探是否生效,以及规则是否只能匹配到 IP。

有些环境需要在 TUN 和显式代理变量之间作选择。TUN 的优势是多数应用不必逐个配置代理变量,对 Git、包管理器和部分 SSH 场景更方便;环境变量的优势是作用范围清楚、容易在单个终端会话启用或撤销,也更适合远程服务器和 CI 环境。两者不必盲目叠加:若某工具本身已设置代理变量,而 TUN 又在系统层接管连接,可能造成重复转发或排障路径变复杂。遇到异常时,先用单一方式建立可复现的基线,再决定是否组合使用。

验证 Git、SSH 与 Homebrew:按协议区分问题

先从 Git 的 HTTPS 地址开始测试,因为它通常使用常见的 TLS 连接,容易在 Clash 日志中识别目标域名。执行一次只读的仓库访问或克隆测试,观察代码托管平台的主域以及实际下载过程中出现的其他主机名。仓库页面能打开,不代表对象文件、重定向或大文件存储使用的域名也都已覆盖;如果失败发生在传输中途,应查看日志中最后出现的 Host,而不是只给主页域名增加规则。对照本机 Git 配置时,也要区分全局配置、仓库级配置与当前 shell 环境,避免把旧代理设置误认为 TUN 的行为。

SSH 与 Git HTTPS 不是同一种连接。SSH 通常直接建立 TCP 会话,常见默认端口是 22,但企业网络、代码托管服务或用户配置可能采用不同端口,也可能通过 SSH 配置文件指定跳板机。TUN 能否接管取决于路由和客户端设置,不应假设「Git 的 HTTPS 规则」会自动覆盖 SSH。执行 SSH 连通性测试时,留意它使用的主机别名最终解析到哪里、连接哪个端口;若日志中没有对应记录,检查 TUN 路由和目标地址;若网络能通但密钥认证失败,则问题属于 SSH 密钥、账号权限或服务器端授权,不是代理节点。

Homebrew 在 macOS 上可能涉及仓库拉取、软件包下载和预编译包镜像等不同请求。一次 brew install 中,Git 访问与下载二进制文件未必指向同一域名,所以安装卡住时应区分是更新索引、获取源码还是下载 bottle。先读终端报错和 Clash 连接日志,记录失败阶段出现的目标主机;不要仅凭软件包名称推断域名。若你使用了自定义镜像或企业内部仓库,应确认这些地址按预期直连或走指定代理,并检查其证书和访问权限。

规则设计应以实际日志为依据。对稳定、已知的域名,优先采用明确的域名规则并放在会先匹配的位置;避免仅用宽泛关键字匹配,把同名但无关的服务也导向代理。一个可维护的做法是把代码托管、包仓库和容器镜像按用途分别归类,策略组使用清晰名称,并在新增规则后逐项复测。规则过宽会增加不必要的代理流量,也可能让内网镜像、公司代码库或本地开发服务走错出口。

npm、pip 与 Docker:区分宿主机和容器网络

对 npm 而言,安装命令不仅访问 registry 读取元数据,还会根据包信息下载 tarball;不同包或镜像配置可能让下载落到其他主机。若安装失败,先检查 npm 当前使用的 registry,再从日志确认真正失败的下载域名。TUN 若已捕获宿主机进程,通常不需要专门为每一个 npm 命令写代理变量,但公司网络、私有 registry 或自定义证书仍需要按其要求配置。不要为了临时解决一次安装问题,把全局 registry 永久改成来源不明的镜像。

pip 同样可能访问 Python 包索引、文件分发主机以及私有仓库。索引页加载成功不等于 wheel 或源码包下载成功,因此应结合 pip 输出与连接日志确认下载请求的去向。若使用虚拟环境,网络行为一般仍由宿主操作系统和当前进程决定,但容器化构建、远程解释器或 IDE 的后台服务可能运行在不同网络命名空间里,不能把本地 shell 的测试结果直接套用到它们身上。遇到证书错误时,优先核对时间、证书链和企业 TLS 检查策略,不要通过关闭证书校验来掩盖代理问题。

Docker 是最容易把「TUN 已经工作」误判为「容器也一定走同一条路」的场景。Docker CLI 向守护进程提交拉取请求,实际下载镜像层的通常是 Docker daemon;它可能运行在独立服务、虚拟机或桌面应用管理的环境中,网络路径与当前终端并不完全相同。因此,即使终端中的 curl 已命中 Clash 规则,docker pull 仍可能超时。要分别检查 Docker daemon 的代理设置、Docker Desktop 的网络选项、镜像仓库地址以及宿主机防火墙规则,不要只给当前 shell 设置代理变量后就认定守护进程会继承。

对容器内部发出的请求还要再多看一层:镜像拉取成功,只说明 daemon 能获取镜像,并不代表容器启动后访问外网也会自动经过宿主机 Clash。容器可能处于桥接网络、用户自定义网络或远程 Docker 主机上;开发容器、CI Runner 和 Kubernetes 节点也各有自己的网络边界。先明确请求发生在「宿主机进程」「Docker daemon」还是「容器内进程」,再选对应的代理变量、网络路由或服务端配置。若目标是让容器访问本地服务,还需核对容器视角中的主机地址,不能想当然地把容器里的 localhost 当作宿主机。

常见故障:用日志把路由、DNS 和权限分开

当所有命令都失败时,先回到最小测试:确认内核仍在运行、TUN 状态正常、系统没有弹出待处理授权,再用一个简单 HTTPS 请求复现。若只有终端失败而浏览器正常,比较两者连接日志里的目标域名、匹配规则和策略组;若所有程序都失败,优先检查节点、系统路由冲突和核心日志。不要立即更换多个节点或清空配置,因为这会丢失最有价值的故障线索。

如果域名无法解析,检查当前 DNS 配置、TUN 的 DNS 接管选项以及是否有 VPN 或安全软件更改解析路径。若主机名已解析但 TCP 连接无法建立,查看目标端口、出站节点状态和规则命中结果。若 TLS 握手时报证书问题,则核对系统时间、证书存储和企业代理的证书安装要求。把错误信息中的阶段和时间记下来,并与 Clash 日志对应,通常比反复执行同一条命令更快定位问题。

若只有某一个工具失败,检查该工具自身是否另有代理配置、私有证书、代理白名单或自定义 DNS。若问题只在公司 VPN 开启后出现,比较两套虚拟接口的路由优先级,并遵循组织的网络接入要求;不要以绕过企业访问控制为目的调整路由。若 TUN 关闭后立即恢复,则可将其作为冲突线索,但仍要确认是自动路由、严格路由、DNS 劫持还是特定网段造成,不能把「关掉就好」当作长期修复方案。

最后,把可复现的结果整理成一张小清单:执行命令、失败时间、目标主机、解析结果、命中的规则、选择的出站策略、错误阶段和是否开启 VPN。这样的记录既便于自己回滚规则,也便于向客户端或网络管理员描述问题。修改规则后每次只调整一类因素,并重复相同测试;确认结果稳定后,再把变更写入可备份的本地覆写配置,避免订阅更新或客户端切换后改动丢失。

常见问题

开启 TUN 后,还需要设置系统代理吗?

不一定。TUN 通过路由层处理符合条件的连接,而系统代理是应用主动读取的代理配置,两者是不同机制。建议先单独验证 TUN 是否捕获目标流量;如果某个程序有特殊限制,再根据它的文档决定是否使用显式代理变量。避免在没有验证的情况下同时叠加多套代理设置。

Git HTTPS 可以克隆,SSH 地址却连接超时,正常吗?

可能发生。HTTPS 和 SSH 使用不同协议、端口及主机配置,命中的规则也可能不同。检查 SSH 实际连接的主机与端口,并在 Clash 日志中确认是否出现对应连接;如果连接已建立但提示密钥拒绝,则应转查密钥和仓库权限。

终端里的 curl 正常,为什么 Docker 拉镜像仍失败?

因为拉取镜像通常由 Docker daemon 发起,而不是当前 shell 中的 curl 进程。daemon 可能运行在独立服务或虚拟机中,有自己的代理与网络设置。请检查 Docker Desktop 或 daemon 的代理配置,并确认日志中镜像仓库请求是否经过预期路径。

使用 TUN 时,能删除 HTTPS_PROXY 环境变量吗?

先查看它是否仍被其他工具、远程开发环境或 CI 任务依赖。可在一个临时终端会话中取消变量进行对照,不要未经检查就修改全局 shell 配置。确认各工具都能通过 TUN 正常连接后,再决定是否清理过期设置。

单纯依靠浏览器系统代理的方案配置简单,但遇到不读取系统代理的 CLI、SSH 或独立运行的 Docker daemon 时,往往还要逐个设置环境变量,且容易漏掉包下载域名;只为每个工具添加独立代理插件,也会让配置分散、难以统一观察。Clash TUN 配合清晰的分流规则,可以在系统网络层集中管理符合条件的终端连接,并通过日志核对命中路径;遇到容器或企业 VPN 等独立网络边界时,仍需按进程和运行环境分别验证。若你希望用一个界面管理规则、节点与连接记录,可以前往下载 Clash V.CORE,按本文的顺序逐项测试自己的开发工具链。

// 编辑推荐

让终端流量按规则走对代理

使用 Clash V.CORE 管理 TUN、分流策略与连接日志,更清楚地排查 Git、包管理器和 Docker 网络问题。

  • 集中查看终端连接与规则命中情况
  • 按开发工具用途维护分流策略
  • 辅助核对代理节点和出站结果
  • 适配常见 Mihomo 内核工作流
获取 Clash V.CORE →