Clash 系统代理已开启却不走代理:浏览器与终端分开排查步骤

浏览器扩展抢占、系统代理未写入、终端不读系统代理是三大主因,本文分浏览器与命令行两条线给出检查顺序与环境变量设置。

先区分:请求没进内核,还是规则选择了直连

先打开客户端的连接页面,再访问一次目标网站。系统代理是操作系统提供的代理设置,只有读取这份设置的应用才会使用它。客户端按钮显示“已开启”,并不代表浏览器、终端和后台服务都已接入。

先理解两层职责。图形客户端负责切换系统设置和展示连接;Clash 或 mihomo 内核负责监听端口、匹配规则、转发请求。mihomo 是 Clash Meta 更名后的内核。内核正常运行、系统代理正确写入、应用愿意读取设置,三项都满足,请求才会按这条路径进入内核。

观察结果优先排查下一步动作
浏览器访问后没有新连接系统代理、扩展、浏览器独立设置核对代理地址与端口,再临时停用代理扩展
浏览器正常,终端没有新连接命令行工具未读取系统代理用 curl 显式指定代理测试
有连接,出口显示 DIRECT规则命中直连查看命中规则与完整策略链
有连接,代理链报超时节点连通性或远端解析查看日志,不再反复切系统代理

关闭目标页面后重新打开,或发起一次新的命令行请求。浏览器缓存、后台长连接、连接页筛选条件都会干扰观察。没有新记录只是线索,不能单独当作结论。若正在使用 TUN 模式,应先记下状态;TUN 是通过虚拟网卡接管流量的方式,会让测试不再只反映系统代理是否生效。

核对本地端口:7890 只是示例值

先查客户端展示的 HTTP 端口或混合端口,再检查系统设置。混合端口可以在同一端口接受 HTTP 和 SOCKS 代理连接。本文使用 127.0.0.1:7890 举例;如果实际端口是 7897,后文命令也要一并替换。

# mihomo 配置片段,不是完整订阅配置
mixed-port: 7890
allow-lan: false
mode: rule

不要把管理接口端口当成代理端口。external-controller 提供的是控制接口,即使它能响应,也不能代替 HTTP 代理监听。也不要为了让本机浏览器连接而开启“允许局域网”;同一系统内通常使用回环地址即可。

检查端口是否真的在监听

在 Windows PowerShell 中执行下面的命令。看到监听记录只能说明该端口有人使用,还需要确认进程是否属于当前客户端的内核。

Get-NetTCPConnection -LocalPort 7890 -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess

# 将上一条输出中的进程号填入交互提示
Get-Process -Id (Read-Host "输入 OwningProcess 进程号")

在 macOS 上使用 lsof,在 Linux 上使用 ss。没有输出时,先检查内核启动日志、实际端口以及是否存在启动失败,不要先改浏览器。

# macOS
lsof -nP -iTCP:7890 -sTCP:LISTEN

# Linux
ss -lntp 'sport = :7890'

浏览器排查:先检查系统设置,再排除扩展接管

第一步:核对系统代理是否写入

在 Windows 11 中,打开「设置」→「网络和 Internet」→「代理」→「手动设置代理」→「编辑」。手动代理模式下,地址应指向本机回环地址,端口应与客户端一致。若客户端使用 PAC,也就是代理自动配置脚本,则检查「使用设置脚本」及其脚本地址,而不是要求手动代理开关同时开启。

在 macOS 13 及以后版本中,打开「系统设置」→「网络」→当前网络服务→「详细信息」→「代理」。检查网页代理(HTTP)和安全网页代理(HTTPS)。不要把“安全网页代理”的名称理解为本地端口一定需要 TLS;它通常仍连接本机 HTTP 代理端口,由代理建立 HTTPS 隧道。

  • 退出其他会自动修改系统代理的客户端,避免设置刚写入就被覆盖。
  • 检查代理例外列表。目标域名若被列为绕过地址,浏览器可能直接连接。
  • 切换 Wi-Fi、有线网络或 VPN 后再看一次设置,尤其注意 macOS 当前网络服务是否改变。
  • 如果设备由组织管理,先检查策略限制。不要反复修改被管理策略强制覆盖的字段。

第二步:检查浏览器自己的代理来源

在 Chrome 或 Edge 的扩展管理页中,临时停用具有代理控制权限的扩展,再新建普通窗口测试。浏览器代理扩展可以覆盖系统设置。无痕窗口不是可靠的唯一对照,因为扩展可能被允许在无痕模式运行,浏览器策略也仍然有效。

在 Firefox 中,打开「设置」→「常规」→页面底部「网络设置」→「设置」。若希望跟随客户端切换,选择「使用系统代理设置」;若要做独立测试,可暂时选择手动代理并填入实际地址。测试结束后恢复原设置,避免以后切换客户端时留下旧端口。

如果只有某个浏览器失败,用另一款浏览器访问同一地址作对照。若另一个浏览器能在连接页产生记录,优先检查原浏览器的扩展、配置文件和企业策略,不必先重装内核。

终端排查:用显式代理命令建立对照

先不要依赖环境变量,直接给 curl 指定代理。很多命令行工具不会自动读取桌面系统代理;浏览器已经能用,并不能证明终端也应该能用。下面的命令适用于 macOS、Linux 的常见 shell,测试地址使用 https://example.com/。

curl -q -v --connect-timeout 10 --max-time 30 \
  --noproxy "" \
  --proxy http://127.0.0.1:7890 \
  https://example.com/ -o /dev/null

在 Windows PowerShell 中明确调用 curl.exe,避免 Windows PowerShell 5.1 中 curl 别名指向其他命令。使用 NUL 丢弃响应正文:

curl.exe -q -v --connect-timeout 10 --max-time 30 --noproxy "" --proxy http://127.0.0.1:7890 https://example.com/ -o NUL
  • -q 放在第一个参数位置,避免用户级 curl 配置文件干扰本次测试。
  • --noproxy "" 清空本次请求的绕过列表,避免目标地址被代理例外排除。
  • --connect-timeout 10 限制连接阶段等待时间,--max-time 30 限制整次传输时间,单位都是秒。
  • 详细输出中先确认连接了 127.0.0.1 的实际端口,再查看 HTTPS 的 CONNECT 隧道与后续响应。

看到 Connection refused 时,先回查本地监听地址与端口;看到 407 Proxy Authentication Required 时,检查本地代理是否启用了认证;建立隧道后才超时,则继续查策略组和节点。网站返回 403 也不等于没走代理,它可能是目标站的访问限制。

不要只凭网页是否打开下结论。显式代理命令成功,同时客户端连接页出现对应目标,才能说明应用到内核这一段已接通。之后再判断规则是否选中了预期出口。

设置终端环境变量:区分 HTTP 代理与 SOCKS 代理

macOS 与 Linux:先只在当前 shell 生效

先在当前终端执行以下设置,再运行不带 --proxy 的命令验证。https_proxy 表示访问 HTTPS 目标时使用的代理;变量值仍然可以是 http://,因为这里描述的是本机代理服务的协议。

export http_proxy="http://127.0.0.1:7890"
export https_proxy="http://127.0.0.1:7890"
export no_proxy="localhost,127.0.0.1,::1"

curl -q -v --connect-timeout 10 --max-time 30 \
  https://example.com/ -o /dev/null

确认有效后,再考虑写入 ~/.zshrc 或 ~/.bashrc 等当前 shell 实际读取的文件。不要一开始就写入全局配置,否则客户端退出以后,终端仍会尝试连接已关闭的端口。环境变量通常只影响当前进程及其后续启动的子进程,不会自动改动已运行的程序。

如果工具明确支持 SOCKS,可使用下面的单次调用。socks5h 中的 h 表示让代理处理目标域名解析;socks5 通常由本机先解析目标域名。只有实际启用了 SOCKS 或混合监听的端口才能这样使用。

curl -q --proxy socks5h://127.0.0.1:7890 \
  --noproxy "" --connect-timeout 10 --max-time 30 \
  https://example.com/ -o /dev/null

Windows PowerShell:修改当前进程环境

在 PowerShell 中使用 $env:,不要照抄 shell 的 export。以下设置对当前 PowerShell 及之后从它启动的子进程生效,不会立即修改其他已打开的终端窗口。

$env:http_proxy = "http://127.0.0.1:7890"
$env:https_proxy = "http://127.0.0.1:7890"
$env:no_proxy = "localhost,127.0.0.1,::1"

curl.exe -q -v --connect-timeout 10 --max-time 30 https://example.com/ -o NUL

不要用 setx 做第一轮验证。它写入持久环境,通常还需要新开进程才能看到变化,容易与当前窗口里的旧值混淆。不同工具对变量名称和优先级的支持不同;curl 的 HTTP 代理变量应使用小写 http_proxy,不能假定所有工具都统一读取大写 HTTP_PROXY。

检查旧变量和工具自己的代理配置

显式代理成功、普通命令失败时,检查 ALL_PROXY、all_proxy、NO_PROXY 和 no_proxy 是否还指向旧端口或包含目标域名。Git 等工具也有独立配置,下面的命令只读取配置来源,不会修改文件:

git config --show-origin --get-regexp '.*proxy.*'

没有输出不一定是错误,只说明未查到匹配项。若发现历史配置,先确认它属于哪个文件、是否仍被其他工作环境使用,再决定修改。分享终端输出前,遮盖代理账号、密码、订阅链接和含访问令牌的地址。

进入内核仍未走代理:检查规则与策略组

先看连接详情里的匹配规则与最终出口。规则模式会按配置顺序匹配,命中 DIRECT 表示内核选择直连,不是系统代理失效。策略组也可能包含 DIRECT,所以只看到策略组名称还不够,要继续查看完整链路。

  1. 保持同一个目标地址测试,记录当前模式、命中规则和策略链。
  2. 检查所选代理组是否实际选中了可用节点,而不是直连选项。
  3. 必要时短暂切到全局模式,并确认全局策略组选中了代理节点,再发起同样的请求。
  4. 若全局可用、规则模式直连,回查规则顺序;若两者都超时,转查节点与日志。
  5. 测试结束恢复规则模式,避免长期改变其他应用的分流行为。

注意“使用代理”和“目标能访问”是两回事。节点不可用、远端限制以及 DNS 解析失败,都可能发生在请求进入内核之后。不要通过不断追加域名规则来修复本地端口拒绝连接,也不要用重装客户端代替确认命中规则。

WSL、容器与 TUN:最后处理特殊运行环境

先确认命令究竟运行在哪个系统里。WSL、Docker 容器和虚拟机中的 127.0.0.1 不一定指向宿主机。WSL 2 的 NAT 网络与镜像网络行为不同;Docker 的宿主机地址也取决于运行环境。宿主机浏览器可用而容器中拒绝连接时,优先查网络边界,不要直接照搬回环地址。

只有确实需要跨边界连接时,才评估监听地址、允许局域网和防火墙规则。把代理监听扩大到其他网卡会增加可访问范围,应限制可信来源并按需配置认证。不要为了排查终端问题就把端口暴露到公共网络。

对于不支持代理设置、也不读取代理环境变量的应用,再考虑 TUN 模式。TUN 通常需要系统权限,涉及路由和 DNS 接管;它不是修复错误端口的快捷开关。开启前记录原状态,避免与另一套 VPN 或虚拟网卡同时接管后难以定位问题。

完成后恢复设置,并保留最小排查记录

先恢复临时改动,再验证日常工作流程。如果此前没有设置代理变量,可用下面的命令清除本次添加的变量;如果原来已有值,应恢复原值,而不是直接删除。

# macOS / Linux:仅清除本文临时设置的小写变量
unset http_proxy https_proxy no_proxy

# PowerShell:仅清除本文临时设置的进程变量
Remove-Item Env:http_proxy, Env:https_proxy, Env:no_proxy -ErrorAction SilentlyContinue

最后保留四项记录:实际监听端口、显式 curl 测试结果、浏览器使用的代理来源、连接详情里的规则与出口。它们能把问题定位到应用设置、本地监听或内核转发,而不是只留下“开了代理还是不行”的描述。

下载Clash选择客户端平台