Clash 系统代理不生效排查:浏览器正常但终端失败怎么办
分别检查系统代理、浏览器独立设置、终端环境变量与本地监听端口。
先确认浏览器使用的代理路径
“浏览器可以访问,但终端失败”并不能直接说明 Clash 的系统代理开关失效。浏览器与命令行程序可能走完全不同的网络路径:浏览器可以读取操作系统代理,也可能使用浏览器扩展、独立代理配置或自身的安全 DNS;终端程序则可能直接连接目标地址,完全忽略系统代理。
排查的第一步不是反复切换节点,而是确认浏览器流量究竟从哪里进入 Clash。可以暂时关闭浏览器中的代理扩展和独立代理选项,只保留 Clash 的系统代理功能,再重新访问测试页面。如果关闭扩展后浏览器也无法连接,原先成功的流量很可能来自扩展,而不是系统代理。
随后查看 Clash 客户端的连接记录。访问一个此前没有打开过的域名,观察连接列表中是否出现对应域名、目标地址、命中的规则和策略组。如果浏览器显示访问成功,但 Clash 中没有任何新连接,说明该请求没有进入当前运行的 Clash 实例。常见原因包括浏览器使用其他代理、浏览器启用了独立 VPN、系统中同时运行多个代理客户端,或者浏览器复用了尚未关闭的旧连接。
还应确认浏览器与终端测试的是同一个域名和协议。访问普通网页、请求 HTTPS 接口、连接 Git 仓库以及下载软件包,可能涉及不同域名、端口和规则。某个网页可用,并不代表 Git、包管理器或远程 API 使用的目标也被同一规则正确处理。
检查 Clash 本地监听端口与协议
终端要通过 Clash 转发流量,首先必须连接到一个正在监听的本地代理端口。不同客户端的默认值可能不同,导入配置后也可能被覆盖,因此不要仅凭经验假定端口一定是 7890。应在客户端的端口设置、运行日志或当前生效配置中确认实际数值。
常见配置会提供 HTTP 端口、SOCKS 端口或 mixed-port。mixed-port 可以在同一端口接收 HTTP 和 SOCKS 代理连接,适合同时供浏览器、curl 与其他工具使用。以下片段只是结构示例,实际排查时应以客户端展示的生效配置为准:
mixed-port: 7890
socks-port: 7891
allow-lan: false
mode: rule
配置中出现端口并不等于进程已经成功监听。端口可能被其他程序占用,Clash 内核也可能因为配置加载失败而没有启动。Windows 可以使用 netstat 或 PowerShell 查看监听状态,macOS 与 Linux 可以使用 lsof 或 ss:
netstat -ano | findstr 7890
lsof -nP -iTCP:7890 -sTCP:LISTEN
ss -lntp | grep 7890
如果没有任何监听结果,应先回到 Clash 客户端检查内核运行状态与日志,而不是继续修改终端。若端口已经被其他进程占用,需要关闭冲突程序或修改 Clash 端口,并同步更新终端中的代理地址。
确认监听后,可以让 curl 显式指定代理。这一步绕过系统代理与环境变量,能够快速验证“终端到本地端口”和“Clash 到目标站点”两段路径是否工作:
curl -I -x http://127.0.0.1:7890 https://example.com
curl -I --proxy socks5h://127.0.0.1:7891 https://example.com
第一条命令按 HTTP 代理测试,第二条按 SOCKS5 测试。socks5h 中的 h 表示由代理端解析目标域名,有助于区分本地 DNS 问题与代理连接问题。如果显式指定代理能够成功,Clash 的端口与节点大体可用,问题通常集中在系统代理读取方式或终端环境变量上。
如果出现“connection refused”,优先检查端口和内核状态;如果长时间超时,检查防火墙、节点连通性与规则;如果收到代理认证错误,则确认所用客户端是否为本地端口设置了认证信息。若日志显示请求进入 Clash 后被 DIRECT 规则处理,还需要检查规则顺序和最终命中的策略组。
为终端程序设置代理环境变量
许多命令行工具不会自动读取桌面系统的代理设置,而是查找 http_proxy、https_proxy 和 all_proxy 等环境变量。变量名有大小写差异,具体支持范围由程序决定。为了减少兼容问题,可以同时设置小写和大写形式,但应避免在同一会话中留下互相冲突的地址。
macOS 与 Linux 临时设置
在 Bash、Zsh 等 Shell 中,可以只对当前终端会话导出代理变量:
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
curl -I https://example.com
https_proxy 表示处理 HTTPS 目标时使用的代理,不代表变量值必须写成 https://。本地 Clash 端口通常提供 HTTP 代理,因此地址仍常写作 http://127.0.0.1:7890。如果希望统一使用 SOCKS,可设置:
export all_proxy=socks5h://127.0.0.1:7891
export ALL_PROXY=socks5h://127.0.0.1:7891
Windows CMD 与 PowerShell 临时设置
CMD 使用 set 设置当前窗口的环境变量:
set http_proxy=http://127.0.0.1:7890
set https_proxy=http://127.0.0.1:7890
curl.exe -I https://example.com
PowerShell 则需要写入当前进程的 Env 作用域:
$Env:http_proxy = "http://127.0.0.1:7890"
$Env:https_proxy = "http://127.0.0.1:7890"
curl.exe -I https://example.com
在 PowerShell 中应明确使用 curl.exe 完成测试,避免旧版环境里的命令别名让测试结果产生歧义。对于 Invoke-WebRequest,还可以直接指定代理:
Invoke-WebRequest -Uri "https://example.com" -Proxy "http://127.0.0.1:7890"
检查残留与排除列表
修改变量前,应先输出当前值,确认是否残留了旧端口、失效主机名或另一款代理软件的地址。macOS 与 Linux 可以执行 env | grep -i proxy,PowerShell 可以执行 Get-ChildItem Env: | Where-Object Name -Match 'proxy'。
no_proxy 或 NO_PROXY 用于指定不经过代理的地址。若目标域名意外出现在排除列表中,程序会直接连接。常见的合理排除项包括 localhost、127.0.0.1 和局域网服务,但过宽的后缀规则可能连带排除外部域名。
处理系统代理、工具配置与平台差异
系统代理不是一个所有程序都必须遵守的统一转发层。它更像操作系统提供的一组代理参数,应用是否读取、何时读取以及支持哪些协议,都由应用自身决定。浏览器通常会读取系统设置,而 Git、npm、Python 包管理器、容器进程和部分 Java 程序经常使用自己的配置。
Windows 的系统代理与 WinHTTP
Windows 桌面应用常读取用户级系统代理,而部分系统组件和服务使用 WinHTTP 配置。两套设置并不完全等价。因此,浏览器正常但以服务身份运行的工具失败,并不罕见。可以使用以下命令查看 WinHTTP 当前状态:
netsh winhttp show proxy
不要在没有确认用途时直接把用户代理导入 WinHTTP,因为这会影响依赖它的系统组件。更稳妥的方法是先让具体命令显式连接 Clash,确认问题边界,再决定使用工具自己的配置还是调整系统级设置。
Git 与包管理器的独立代理
Git 可以单独保存 HTTP 与 HTTPS 代理。如果环境变量正确但 Git 仍失败,应检查是否存在旧配置:
git config --global --get http.proxy
git config --global --get https.proxy
需要使用当前 Clash HTTP 端口时,可以设置:
git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
如果不再需要 Git 独立代理,应删除对应项目,而不是把值改成空字符串。npm、pnpm、pip、Maven 与 Gradle 也各有配置来源。排查时要同时检查工具配置文件、环境变量和 IDE 设置,避免同一个请求被多层配置重复覆盖。
代理协议必须与端口匹配
把 SOCKS 端口当作 HTTP 代理使用,或把 HTTP 端口写成 SOCKS 地址,会导致握手失败。应从 Clash 客户端确认端口类型,再让工具使用对应的 URL 方案。HTTP 代理通常写作 http://127.0.0.1:端口,SOCKS5 则写作 socks5:// 或 socks5h://。
还要留意 127.0.0.1 与 localhost 的解析差异。部分环境会优先把 localhost 解析为 IPv6 地址 ::1,但 Clash 可能只监听 IPv4。排查阶段直接使用 127.0.0.1,可以减少这一变量。
检查 TUN 模式、DNS 与隔离环境
TUN 模式通过虚拟网络接口接管更多流量,通常不要求每个终端程序单独支持系统代理。但这不意味着开启 TUN 后所有命令都会自动成功。虚拟接口创建权限、路由写入、DNS 接管、进程绕过规则以及其他 VPN 软件都可能影响结果。
如果普通系统代理下 curl 显式指定端口可以工作,而开启 TUN 后直接请求仍失败,应检查 Clash 日志中是否出现该连接。完全没有记录通常表示路由没有进入 TUN;有连接但域名解析失败,则应检查 DNS 配置;连接被规则分配到错误策略组时,应回到规则匹配结果进行修正。
Clash Meta,也称 Mihomo,支持更完整的 TUN、DNS 与规则能力,但图形客户端是否暴露相关选项、使用哪种运行权限,取决于客户端实现。修改 YAML 之前,应确认客户端是否会在启动时重新生成配置,避免手工改动被覆盖。
WSL、Docker、虚拟机和远程开发容器需要特别处理。它们看到的 127.0.0.1 通常指向自身,而不是宿主机。宿主机上的 Clash 即使监听正常,容器内部访问 127.0.0.1:7890 也可能被拒绝。此时需要使用宿主机在该虚拟网络中的地址,并确认 Clash 允许局域网连接、监听地址覆盖相应接口,同时检查宿主机防火墙。
通过 SSH 登录远程服务器后,终端命令运行在远程主机上。远程主机的 127.0.0.1 同样不是本地电脑。若要让远程命令使用本机 Clash,需要建立明确的 SSH 端口转发或在远程环境配置可达代理,不能直接复制本机环境变量。
按顺序完成 Clash 终端代理定位
有效的排查方式是逐层验证,而不是同时修改系统代理、规则、DNS 和节点。每一步只回答一个问题,并记录测试结果:
- 确认内核运行:检查 Clash 客户端状态和启动日志,确保当前配置加载成功。
- 确认端口监听:从生效配置读取 HTTP、SOCKS 或 mixed-port,再用系统命令确认对应端口处于监听状态。
- 显式指定代理:使用
curl -x或--proxy直接连接本地端口,排除系统代理读取问题。 - 观察连接记录:确认请求进入 Clash,并查看命中的规则、策略组、节点和错误信息。
- 检查终端变量:输出所有 proxy 相关变量,删除旧地址和冲突值,再为当前会话设置正确端口。
- 检查工具独立配置:查看 Git、包管理器、IDE 和运行时是否保存了另一套代理。
- 识别运行边界:判断命令位于宿主机、WSL、容器、虚拟机还是远程服务器,确认其中的本地地址实际指向哪里。
- 最后检查 TUN 与 DNS:仅在基础端口测试通过后,再分析虚拟接口、路由和域名解析。
若显式代理测试成功、环境变量测试也成功,但某个特定工具仍失败,问题基本位于该工具自身。此时应开启工具的详细日志,查看它连接的域名、读取的代理配置以及 TLS 错误,而不是继续更换 Clash 节点。
若所有显式代理测试都失败,则回到 Clash 侧检查端口、配置和节点。可以分别测试多个目标域名,并在连接记录中比较规则结果。只有部分域名失败时,重点检查规则、DNS 与目标服务;所有域名都无法建立连接时,优先检查本地监听、内核日志和代理节点。
完成排查后,应清理不再使用的临时变量和重复配置,只保留一条明确的代理路径。系统代理适合桌面应用,环境变量适合终端会话,工具独立设置适合有固定需求的程序,TUN 则适合需要接管更多网络流量的场景。选择其中符合当前环境的一层作为主要入口,可以减少端口变化和配置冲突带来的故障。