浏览器能开 YouTube,同一台机器上 Steam 的商店页转圈,git clone 卡在 0%,某个游戏的登录服务器连不上。代理没坏,是这几个软件压根没把请求交给它。
先确认它是真的没走代理
别急着改设置,先看一眼证据。Clash Verge Rev 的连接页会把当前每条连接列出来,带着目标地址、命中的规则和发起连接的进程名。让那个软件重新发起一次网络请求,去连接页里搜它的进程名。列表里没有它,说明流量根本没进内核。列表里有它但规则那一栏是 DIRECT,那是分流的事,不是本文要处理的。
手机和 iPhone 上的客户端也有类似的页面,名字多叫连接或者活动。
系统代理靠的是软件自觉
系统代理做的事只有一件,把代理服务器的地址和端口写进操作系统约定的那个位置,通常是 127.0.0.1 加客户端的本地端口,Clash Verge Rev 默认 7897,v2rayN 默认 10808。
Clash Verge Rev 的官方文档把这里讲得很直白,需要联网的应用会自发地去读这部分信息,然后原话补了一句,这是行业约定而非强制,遵不遵守取决于开发者。浏览器和大部分桌面软件会读,命令行工具、游戏、一些自带网络库的客户端软件不读。
同一份文档还写了系统代理的第二个限制,它没法代理 UDP 流量,游戏的数据包就属于这一类。所以有些软件界面上看着连上了,实际功能不通,问题出在这一层。系统代理那条术语里写了同样的两条边界。
微软商店的应用还多一道沙盒
UWP 应用是系统代理下面一种特殊情况。Clash Verge Rev 的 Windows 常见问题写明,Windows 的 UWP 应用存在沙盒机制,正常情况下访问不了 localhost,也就够不着本机那个代理端口,不管它读不读系统代理设置都一样。
官方给的办法是打开设置页的 Clash 设置分组,点 UWP 工具,在弹出的窗口里勾选需要走代理的应用,再点保存。开 TUN 模式也能绕开这道限制。
软件自己能填代理的,先填它
这一步成本最低,改完立刻生效,也不影响系统上别的程序。
Clash Verge Rev 的 macOS 常见问题里就记了一个真实例子。App Store 版本的 Telegram 默认不遵守系统代理,官方给的办法是在应用内手动设置代理,端口填 7897,或者改用官网的版本。很多软件都是这个路子,设置里翻到网络那一栏,填 HTTP 代理 127.0.0.1 和端口就行。
Git 和包管理器有自己的配置项。
git config --global http.proxy http://127.0.0.1:7897
git config --global https.proxy http://127.0.0.1:7897
npm config set proxy http://127.0.0.1:7897
npm config set https-proxy http://127.0.0.1:7897
端口换成你客户端里显示的那个。不想让它们长期走代理,把 config 换成 --unset 再执行一次就撤销了。
命令行要自己把代理带上
终端里的 curl、wget、pip 这些不读系统代理,认的是环境变量。下面三段按系统挑一段用,端口换成自己的。
Windows 的命令提示符。
set http_proxy=http://127.0.0.1:7897
set https_proxy=http://127.0.0.1:7897
Windows 的 PowerShell。
$env:http_proxy = "http://127.0.0.1:7897"
$env:https_proxy = "http://127.0.0.1:7897"
macOS 和 Linux 的终端。
export http_proxy=http://127.0.0.1:7897
export https_proxy=http://127.0.0.1:7897
export all_proxy=socks5://127.0.0.1:7897
这三段都只对当前这个终端窗口有效,关掉就没了。Clash Verge Rev 把这件事做成了功能,官方 FAQ 写明在设置页的复制环境变量类型里选好 PowerShell、Bash 或者 CMD,再右键系统托盘里的图标,选复制环境变量,粘贴到终端里执行即可。
填完验证一下,这条命令会返回一串纯文本。
curl -s https://www.cloudflare.com/cdn-cgi/trace
看 ip= 和 loc= 两行。loc 是你节点落地的国家代码,说明这条命令走了代理。loc=CN 且 ip 是你家宽带的地址,说明环境变量没生效。
剩下的交给 TUN 模式
上面几样都够不着的软件,就用 TUN 模式。它的做法是建一张虚拟网卡,改写系统路由把流量引过去,Clash Verge Rev 的文档写它拦截和处理所有流量,TCP 和 UDP 都算。系统代理靠软件自觉,TUN 不问软件的意见。
开它要管理员权限。Clash Verge Rev 为此做了服务模式,文档的说法是让 TUN 模式能够以非管理员身份启动,装好服务以后日常打开就不用再输密码。Windows 上装服务可能被杀毒软件拦,macOS 上会弹窗要登录密码。
Mihomo 的 TUN 配置里有几项值得知道。
tun:
enable: true
stack: mixed
dns-hijack:
- "any:53"
auto-route: true
auto-detect-interface: true
stack 决定用哪一套协议栈,文档列的可选值是 system、gvisor、mixed 和 mips,默认 gvisor。system 借系统协议栈,稳定且占用低。gvisor 在用户态实现网络。mixed 是 TCP 走系统、UDP 走 gvisor。mips 是 mihomo 自研的那一套。
auto-route 自动改写全局路由。auto-detect-interface 自动选出口网卡,文档提醒多网卡设备上最好手动指定。dns-hijack 把发往 53 端口的查询截给内核自己的 DNS 模块,配套的注意事项写在 DNS 泄漏怎么查那篇里。Linux 上还有一个 auto-redirect,文档写明它自动配置 iptables 或 nftables 做 TCP 重定向,要求 auto-route 一起开。
开 TUN 的代价也要知道三条。Clash Verge Rev 的 Windows FAQ 记了打开 TUN 后网络反而不正常的情况,原因是系统里有多张网卡或者网段和配置里的规则冲突,处理办法是到网络设置里删掉多余的虚拟网卡。macOS 上开 TUN 时系统 DNS 会被改成 223.6.6.6,官方说明这是为了让 TUN 正常工作,关掉就恢复。再有就是别和另一个 VPN 或者游戏加速器同时开,两边都要改系统路由。
TUN 开着还有软件绕过去
先切全局模式试一次。能通就是分流规则没覆盖到这个域名,切回规则模式给它补一条 DOMAIN-SUFFIX 规则就行,两种模式的分工在规则模式那条术语里。全局下也不通,往下看。
有的软件自己把域名解析完,只拿一个 IP 去建连接,内核收到的时候域名已经没了,按域名写的规则全部落空。Mihomo 的域名嗅探就是为这种连接准备的,从 TLS 握手的 SNI、HTTP 的 Host 或者 QUIC 报文里把域名读回来。
sniffer:
enable: true
parse-pure-ip: true
override-destination: false
sniff:
HTTP:
ports: [80, 8080-8880]
override-destination: true
TLS:
ports: [443, 8443]
QUIC:
ports: [443, 8443]
skip-domain:
- Mijia Cloud
parse-pure-ip 对拿不到域名的流量强制嗅探,override-destination 决定要不要拿嗅探到的域名当实际访问目标,skip-domain 用来放过那些嗅探之后反而出问题的域名,官方示例里排除的就是米家设备。
还有一条路是按进程写规则。Mihomo 的规则文档里有 PROCESS-NAME,用进程匹配,在 Android 平台上可以匹配包名。上面第一节在连接页里看到的进程名,正好拿来填这里。
手机上没有系统代理这个选项
安卓和 iPhone 上的代理客户端都是以 VPN 的身份工作的,等于一直在 TUN 模式,不存在只开系统代理的选项。对应地,这两个系统同一时间只允许一个 VPN 配置处于连接状态,再打开另一个代理应用,先前那个会被顶掉。
要控制哪些应用走代理,用客户端的分应用功能。FlClash 在工具里叫访问控制,有两种模式,一种是只让选中的应用进 VPN,另一种是把选中的应用排除在外,国内应用多的手机用排除模式省事。v2rayNG 里这一项叫分应用代理。iPhone 上没有这么细的开关,能改的是客户端里的分流规则。各家的位置不一样,客户端总览里每一页都有对应的图文步骤。