先用显式代理请求确定故障层级

打开“系统代理”只代表客户端尝试把代理地址写入操作系统设置,不代表所有应用都会读取它。mihomo 内核是否运行、应用是否连接本地端口、规则是否选择代理节点,是三个独立问题。先做一次绕过浏览器设置的显式代理测试,再分别处理浏览器和终端。

下文统一以本机混合端口 7890 为例。请先在客户端的端口设置或当前生效配置中读取实际值,不能把示例端口当作所有 Clash 客户端的默认值。Windows PowerShell 使用 curl.exe,避免旧版 Windows PowerShell 将 curl 解释为其他命令。

# macOS / Linux
curl --noproxy "" -x http://127.0.0.1:7890 -I --connect-timeout 10 --max-time 20 https://example.com

# Windows PowerShell
curl.exe --noproxy "" -x http://127.0.0.1:7890 -I --connect-timeout 10 --max-time 20 https://example.com
  • 连接被拒绝:优先检查内核、监听端口和进程归属,不要先换 DNS。
  • 连接本地代理成功,但后续超时:检查客户端连接记录、命中规则、策略组与节点。
  • 获得站点 HTTP 响应:说明该目标的显式代理请求已完成;还需确认它实际使用了代理出站,而不是规则中的 DIRECT。

检查端口、内核与进程占用

订阅导入成功与本地代理监听成功不是同一件事。客户端界面可以正常打开,但内核可能因配置错误退出;另一个代理程序也可能先占用了端口。先确认当前配置已启用,再查看内核启动日志中的监听信息。

核对配置字段

# 本地监听示例,不是完整可连接配置
mixed-port: 7890
allow-lan: false
mode: rule

mixed-port 在同一端口接受 HTTP 与 SOCKS 代理请求。若使用分离配置,port 对应 HTTP 代理,socks-port 对应 SOCKS 代理,不应混填。上面的片段没有节点、策略组或规则,不能代替订阅;图形客户端还可能通过覆写生成运行配置,应以最终生效值为准。

查看 7890 端口的监听者

# Windows PowerShell:查看监听 PID
Get-NetTCPConnection -LocalPort 7890 -State Listen |
  Select-Object LocalAddress, LocalPort, OwningProcess

# macOS:查看进程名与 PID
lsof -nP -iTCP:7890 -sTCP:LISTEN

# Linux:查看监听地址与进程信息,部分信息需要权限
ss -lntp 'sport = :7890'

Windows 可把查到的 PID 填入 Get-Process -Id 1234,其中 1234 只是示例。如果监听者属于旧客户端,先正常退出旧程序,再启动当前内核。不要直接终止无法确认用途的系统进程。没有监听结果时,查看日志中的配置解析错误、端口绑定失败以及内核退出原因。

若本机请求用的是 localhost,还要留意它可能解析到 IPv6 回环地址 ::1,而内核只监听 IPv4。排查时先固定使用 127.0.0.1,让地址与监听结果一致。

浏览器线路:系统设置、扩展与 PAC

显式代理可用而浏览器不可用,通常需要查浏览器采用了哪套代理设置。不同浏览器、桌面环境和企业策略的行为并不完全相同,不能只看客户端开关颜色。

  1. Windows 11:进入「设置」→「网络和 Internet」→「代理」。检查“使用代理服务器”的地址和端口,并记录“使用设置脚本”是否启用。
  2. macOS:进入「系统设置」→「网络」→当前网络服务→「详细信息」→「代理」。核对网页代理、安全网页代理以及自动代理配置。
  3. Chrome:在地址栏输入 chrome://settings/system,打开计算机的代理设置;再到 chrome://extensions 检查能控制代理的扩展。
  4. Firefox:进入「设置」→「常规」→「网络设置」→「设置」。明确选择“使用系统代理设置”,或手动填入与内核一致的 HTTP、HTTPS 代理地址。

先移除重复控制,再判断 PAC

代理切换扩展可能覆盖系统设置。先暂时停用相关扩展,完全退出浏览器后重新打开,再观察客户端连接列表。隐私窗口不一定能排除扩展影响,因为扩展可能已获准在隐私窗口运行。

PAC 是按请求 URL 决定代理或直连的脚本,不是“全部流量走代理”的开关。例如脚本返回 DIRECT 时,浏览器不会连接本地代理。排障时记录原有设置,临时只保留一种控制方式,避免自动脚本、手动代理和扩展规则叠加。受单位策略管理的设备应先联系管理员,不要删除组织下发的设置。

Windows 可在 PowerShell 执行以下命令读取当前用户的一部分代理设置。这里的结果用于定位配置来源,不代表所有浏览器最终都采用它:

Get-ItemProperty 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' |
  Select-Object ProxyEnable, ProxyServer, AutoConfigURL

netsh winhttp show proxy 显示的是 WinHTTP 代理配置,不能据此断定 Chrome 使用的系统代理已开启或关闭。把两套设置混为一谈,容易出现“命令显示直连,但浏览器确实在代理”的误判。

终端线路:显式设置代理环境变量

多数命令行工具不会自动读取桌面系统代理。浏览器已经能访问目标站点,终端里的 curl、Git 或包管理器仍然失败,并不矛盾。先使用临时环境变量,不要立即修改全局配置;确认有效后再决定是否写入 shell 启动文件。

macOS 与 Linux:当前 shell 会话

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 -I --connect-timeout 10 --max-time 20 https://example.com

# 查看是否还存在旧配置
env | grep -iE '^(http|https|all|no)_proxy='

https_proxy 的变量名描述目标 URL 的协议,并不要求变量值以 https:// 开头。连接本地 HTTP 代理时使用 http://127.0.0.1:7890,HTTPS 请求通过 CONNECT 建立隧道。把协议头改成 HTTPS,反而可能要求本地端口提供它并未启用的 TLS 代理服务。

curl 出于安全原因不采用大写 HTTP_PROXY 作为 HTTP 代理变量,使用小写写法更稳妥。其他程序的大小写识别规则可能不同;如果已有大写变量或 all_proxy,应一并核对,避免旧端口继续生效。

Windows 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 -I --connect-timeout 10 --max-time 20 https://example.com
Get-ChildItem Env: | Where-Object Name -Match 'proxy'

这些设置只影响当前 PowerShell 和之后从它启动的子进程,不会自动修改已经运行的编辑器或其他终端。Windows Terminal 中先前打开的另一个标签页也不应视为已同步配置。WSL、容器和远程 SSH 会话属于独立环境,其中的 127.0.0.1 未必指向宿主机代理;不要为解决这一点直接把代理开放到所有网卡。

恢复临时环境

# macOS / Linux
unset http_proxy https_proxy all_proxy no_proxy
unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY

# Windows PowerShell
Remove-Item Env:http_proxy, Env:https_proxy, Env:all_proxy, Env:no_proxy -ErrorAction SilentlyContinue

若原先存在公司代理,应恢复记录下来的原值,而不是简单清空。关闭当前 shell 也会丢弃本次临时修改;写入 ~/.zshrc、~/.bashrc 或 PowerShell 配置文件的内容则需要另行修改。

单个工具失败:检查应用级覆盖

环境变量生效后仍只有某个工具失败,应检查该工具自己的代理配置。应用级选项可能覆盖环境变量,后台服务也可能根本没有继承当前 shell 的环境。以 Git 为例,先查询来源,再决定是否改动:

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

# 仅对这一条命令指定代理,不写入全局配置
git -c http.proxy=http://127.0.0.1:7890 ls-remote https://github.com/git/git.git HEAD

命令中使用的是公开仓库。测试私有仓库时,认证错误不能直接归类为代理故障。Git 的 HTTPS 传输可以使用 HTTP 代理,但 git@ 开头的 SSH 远程地址走的是另一条传输路径,不会因设置 http.proxy 就自动通过相同代理。

同样,npm、Python 包管理器、Java 应用和容器构建可能分别读取配置文件、命令参数或服务环境。先用 curl 作为基线验证,再处理具体工具。不要为排查网络而关闭 TLS 证书验证;如果出现证书错误,应核对系统时间、信任链及组织网络中的证书配置。

请求进入 mihomo 后:核对规则与节点

客户端连接列表中已经出现目标域名,只能说明请求进入内核,不能说明它使用了预期节点。规则模式按顺序匹配,前面的 DIRECT 规则、策略组当前选择的 DIRECT,以及末尾的 MATCH 都可能改变出站路径。

  • 检查模式:确认当前是规则模式;如临时切到全局模式对照测试,还要确认全局策略实际选择了代理节点,结束后恢复原模式。
  • 检查命中规则:记录目标域名、匹配规则和最终策略链。订阅中引用的策略组名称必须与实际定义一致。
  • 检查节点:延迟测试成功只代表测试 URL 在当时可达,不保证所有域名、端口和协议都可用。
  • 检查错误阶段:本地连接失败、节点拨号超时、DNS 解析失败、TLS 握手错误应分别处理,不要用同一个“代理失效”结论覆盖。

需要比较出口时,可对同一个 IP 查询服务分别运行直连与代理请求,再和连接记录对照。两次出口相同不必然说明系统代理没生效:规则可能直连该查询域名,TUN 也可能接管看似直连的请求。测试时记录 TUN 状态和策略,避免同时改变多个变量。

# 不使用 curl 的应用层代理;TUN 开启时仍可能接管此请求
curl --proxy "" --noproxy "*" --max-time 20 https://api.ipify.org

# 显式使用本地 HTTP 代理
curl --noproxy "" -x http://127.0.0.1:7890 --max-time 20 https://api.ipify.org

何时使用 TUN,何时继续修系统代理

如果故障只发生在浏览器,且显式代理已经成功,应先修复浏览器配置;如果终端工具支持代理变量,按工具配置通常更容易定位。TUN 适合需要接管不读取系统代理的应用,或需要覆盖更多 IP 流量的场景,但它不是排查所有问题的第一步。

TUN 模式通过虚拟网卡和路由接管流量,通常还涉及权限、DNS 与路由设置。它不会自动修复失效节点、错误订阅或错误规则,也不能保证绕过其他 VPN 和安全软件的网络策略。先关闭其他同类接管程序,记录当前路由与 DNS 状态,再按客户端说明启用。

如需进一步反馈问题,保留操作系统版本、客户端与 mihomo 内核版本、实际监听端口、失败命令和错误时间段。分享日志前移除订阅 URL、访问令牌及节点凭据。完整配置项可查阅完整文档;基础导入与接管步骤见使用教程。