开了 Clash 浏览器还是直连?系统代理不生效的浏览器与终端分路排查
系统代理开关亮着,流量却没走代理——这类问题往往不是 Clash 本身的锅,而是浏览器和终端各自维护了一套独立的代理判断逻辑。本文把排查拆成注册表/网络设置、浏览器插件冲突、终端环境变量三条线,逐项定位,最后给出不依赖任何单一开关的 TUN 模式兜底方案。
系统代理开关到底改了什么
Clash 客户端界面上的"系统代理"开关,本质是在操作系统层面写入一条 HTTP/HTTPS 代理配置——Windows 写注册表里的 ProxyServer 键值,macOS 写网络服务的代理设置,Linux 桌面环境写 GSettings 或环境变量。这条配置只对**遵守系统代理设置的程序**生效,而"遵守"与否完全由应用自己决定,操作系统并不会强制拦截所有出站连接去套用这条规则。
也就是说,系统代理是一份"建议",不是强制转发。主流浏览器(Chrome、Edge、Firefox 默认模式)会读取这份建议,大多数命令行工具和部分老旧软件则完全无视它,直接按自己的网络库发起连接。这就是为什么同一台电脑上,浏览器可能已经走了代理,终端里 curl 却还是直连失败或直连成功但没经过代理。
第一条线:系统级注册表与网络设置
这是最基础的一层,如果这一层没配好,后面浏览器和终端的问题都无从谈起。
Windows:检查 Internet 选项与注册表
打开系统代理开关后,Clash 会写入当前用户的 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings,关键字段是 ProxyEnable(应为 1)和 ProxyServer(应指向 Clash 监听的地址与端口,通常是 127.0.0.1:7890)。可以直接打开"设置 → 网络和 Internet → 代理",看手动代理设置是否与 Clash 的 HTTP 端口一致。
- 如果这里显示的地址、端口是空的或者是别的软件写入的旧值,说明系统代理没被 Clash 正确接管,需要在 Clash 里重新点一次系统代理开关。
- 如果地址端口都对,但依然直连,问题大概率不在系统层,要往下查具体程序。
- 企业域策略、部分安全软件会强制锁定代理设置,每次重启后被重置为空,这种情况需要联系管理员放开该注册表项的写入权限,或者直接使用 TUN 模式规避。
macOS:检查网络服务的代理配置
macOS 的代理设置挂在每个网络服务(Wi-Fi、以太网等)下面,而不是全局唯一。打开"系统设置 → 网络 → 你正在使用的服务 → 详细信息 → 代理",确认"网页代理(HTTP)"和"安全网页代理(HTTPS)"都已勾选,且地址端口指向 Clash 的本地监听端口。多网卡、多网络服务时容易漏勾某一个,尤其是同时插了有线网又开着 Wi-Fi 的情况,只改了一个服务的代理是白改。
第二条线:浏览器为什么不听系统代理
浏览器不走代理,通常出现在以下四种情况,按排查优先级排列:
- 浏览器自身设置了独立代理模式。 Firefox 默认不跟随系统代理,而是走自己的"网络设置"里的手动配置,需要在
about:preferences里手动选择"使用系统代理设置",否则 Clash 怎么开都跟它无关。 - 安装了代理管理类扩展插件。 SwitchyOmega 之类的扩展会接管浏览器的代理决策,即使系统代理已经指向 Clash,插件里如果设置的是"直接连接"或指向了别的地址,浏览器实际用的是插件的配置,不是系统的。这是最容易被忽略的一类冲突,建议排查时先临时禁用所有代理类扩展,确认走不走代理,再决定是否要在插件里单独配置。
- 浏览器内置了 VPN 或"安全浏览"之类的网络加速功能。 部分浏览器(尤其国产浏览器)自带的网络加速开关会绕过系统代理直接发起连接,遇到怎么设都不生效的情况,先在浏览器自身设置里关掉这类功能。
- PAC 脚本模式配置错误。 如果 Clash 使用的是自动配置脚本(PAC)而不是固定的 HTTP 代理,浏览器需要能正常拉取到这个 PAC 文件。可以直接在浏览器里访问 PAC 地址(通常是
http://127.0.0.1:<端口>/proxy.pac),打不开说明 PAC 服务没启动,改用固定 HTTP 代理模式更稳。
排查顺序建议:先用浏览器自带的"网络诊断"或直接访问一个已知会被规则命中的域名,观察 Clash 客户端的连接面板里是否出现这条记录。出现了但是标着直连,说明规则或策略组的问题;完全没出现,说明浏览器压根没把请求送到 Clash,回头查上面四条。
第三条线:终端为什么不听系统代理
终端环境是最容易被误解的一块——很多人以为开了系统代理,命令行工具就会自动跟着走,但 Linux 和 macOS 的终端工具链基本不读取图形界面的代理设置,它们看的是**环境变量**。
标准环境变量清单
大多数遵循 Unix 惯例的命令行工具(curl、wget、git、包管理器等)会读取以下环境变量:
export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export all_proxy="socks5://127.0.0.1:7891"
export no_proxy="localhost,127.0.0.1,.local"
这几行只在当前终端会话生效,关掉窗口就没了。想要长期生效,需要写进 ~/.zshrc、~/.bashrc 或对应 shell 的启动脚本里,并 source 一次让它立即生效。Windows 的命令提示符和 PowerShell 同理,可以用 $env:HTTP_PROXY、$env:HTTPS_PROXY 在当前会话设置,或者在系统环境变量里长期写入。
常见踩坑点
- 大小写不一致。 少数程序只读大写的
HTTP_PROXY,另一些只读小写的http_proxy,稳妥做法是大小写各写一份。 - SOCKS 和 HTTP 端口搞混。 Clash 通常同时监听一个 HTTP 端口和一个 SOCKS5 端口(混合端口模式下是同一个端口),环境变量里协议头和实际端口类型要对应,写错协议头会直接连接失败而不是绕过代理。
- Docker 容器、SSH 会话内的环境变量是独立的。 主机上设了代理,容器内部或者远程 SSH 会话默认不会继承,需要单独在容器/远程环境里配置,或者用
-e参数显式传入。 - 包管理器有自己的配置文件。 比如 npm 需要
npm config set proxy单独设置,git 需要git config --global http.proxy,这些工具即使环境变量配好了,也可能因为自身配置文件里写了别的值而覆盖环境变量。
| 工具 | 是否读环境变量 | 需要额外配置 |
|---|---|---|
| curl / wget | 是 | 无 |
| git | 否(默认) | http.proxy 配置项 |
| npm / yarn | 否(默认) | proxy / https-proxy 配置项 |
| docker CLI | 是(需容器内单独设置) | 容器环境变量或 daemon.json |
| Python requests | 是 | 无(遵循标准环境变量) |
TUN 模式:不依赖任何单一开关的兜底方案
如果按上面三条线逐项排查后还是有个别程序死活不走代理,或者根本不想再一个个配置环境变量和浏览器插件,更彻底的做法是切换到 TUN 模式。TUN 模式在系统里建立一个虚拟网卡,在网络层劫持全部出站流量,不再依赖应用层是否读取系统代理设置或环境变量,理论上能覆盖包括后台服务、游戏客户端在内的几乎所有网络请求。
开启 TUN 模式一般需要:客户端具备管理员/root 权限运行,在配置里启用 tun 字段,并确认 stack(如 gvisor 或 system)与本机网络环境兼容。开启后系统代理开关可以保持关闭状态,因为流量已经在更底层被接管,两者同时开启通常不会冲突,但没有必要叠加使用。
tun:
enable: true
stack: gvisor
auto-route: true
auto-detect-interface: true
排查流程小结
遇到"系统代理开了但没生效"的情况,建议按下面顺序走一遍,而不是东一下西一下地试:
- 先看 Clash 客户端的连接面板,确认对应请求有没有出现——没出现说明流量根本没送到 Clash,先查系统代理配置写没写对。
- 浏览器问题优先排查代理管理类扩展和浏览器自带的网络加速功能,这两项最容易被忽略。
- 终端问题先确认环境变量是否已在当前会话生效,再确认具体工具是否遵循环境变量还是需要独立配置文件。
- 逐项排查成本过高、或者存在大量不遵循标准代理逻辑的程序时,直接切换 TUN 模式做兜底,不必纠结于逐个适配。
系统代理、浏览器插件、环境变量、TUN 模式,本质上是四套互相独立又可以叠加的流量接管方式,搞清楚当前问题出在哪一层,排查效率会比盲目重启客户端高得多。