为什么 WSL2 里「开了系统代理」也形同虚设
WSL2 运行在轻量级虚拟机里,拥有独立的网络命名空间与默认路由。Windows 侧「设置 → 网络和 Internet → 代理」或 Clash 写入的系统代理,主要影响 Win32 应用;WSL2 内的进程除非自己读取某类互操作配置,否则不会自动把流量交给宿主机的 127.0.0.1 代理端口。更棘手的是:即使在 WSL2 里写 127.0.0.1,它指向的也是子系统自己的回环,而不是 Windows 上正在监听的 Clash,因此会出现「宿主机浏览器正常、WSL2 里 curl 连本地代理却连不上」的典型现象。
解决思路只有一类:让 WSL2 把代理指向「能路由到 Windows 宿主机」的地址,再加上正确的端口号(常见为 Clash 的 mixed-port,例如 7890)。这与在纯 Linux 里配置 HTTP_PROXY 没有本质区别,只是「网关 IP」换成了虚拟网卡上的宿主机地址。若你还希望 GitHub、npm 等域名按规则分流而不是「全局一锅端」,可继续对照 Cursor / GitHub / npm 分流 一文,在 Clash 规则侧做精细命中;本文专注如何把 WSL2 接到 Windows 上已经开着的代理端口。
在 WSL2 中获取 Windows 宿主机 IP
最稳妥的做法之一,是读取 WSL2 为访问 Windows 而配置的 DNS 转发地址。在子系统终端执行:
grep nameserver /etc/resolv.conf | awk '{print $2}'
输出通常是一个形如 172.x.x.x 的地址,它在多数环境下即为当前会话下 WSL2 视角里的宿主机 IP。你也可以在 Windows 的 PowerShell 里用 ipconfig,找到「vEthernet (WSL)」或「默认交换机」对应网段的地址,与上面结果交叉验证。若你启用了 Windows 11 的「镜像网络模式」(Mirrored networking),部分版本下 localhost 互通行为会变化,此时仍以发行版文档与实际测试为准;通用做法仍是显式使用解析到的宿主机 IP,避免依赖隐式行为。
注意:休眠、切换网络或 WSL 重启后,该 IP 偶发变化。若代理突然失效,先重新取一次宿主机 IP,再更新环境变量或 Git 配置。
1在 Clash(Windows)侧:确认端口并允许局域网
打开 Clash 系图形客户端(如 Verge Rev)或核对配置文件,确认 mixed-port(或分别的 port / socks-port)数值。下文以 7890 为例,请替换成你的实际端口。关键点:WSL2 访问宿主机属于跨网络命名空间访问,Clash 必须在该端口上监听0.0.0.0 或至少包含 WSL 网段,且多数客户端需要勾选「允许局域网连接」类选项;否则即使 IP 正确也会被拒绝连接。安装与系统代理总览可参考 Windows 下 Clash 完整安装与配置教程。
若你使用 TUN 模式 接管 Windows 全局流量,WSL2 内的包默认仍从子系统网卡发出,未必自动进 TUN;此时「环境变量 + 混合端口」路径依然是最可预期的开发机方案。TUN 细节见 Clash Verge Rev TUN 模式教程。
2Shell 环境变量:HTTP_PROXY 与 ALL_PROXY
将上一步得到的宿主机 IP 设为变量(示例用 172.24.160.1,请替换),在 ~/.bashrc 或 ~/.zshrc 末尾追加:
export HOST_IP=$(grep nameserver /etc/resolv.conf | awk '{print $2}')
export HTTP_PROXY="http://${HOST_IP}:7890"
export HTTPS_PROXY="http://${HOST_IP}:7890"
export ALL_PROXY="socks5://${HOST_IP}:7890"
export NO_PROXY="localhost,127.0.0.1,::1"
执行 source ~/.bashrc(或重开终端)后,用 curl -I https://www.google.com 等命令验证。若你的 Clash 仅提供 HTTP 代理、未在同一端口提供 SOCKS,可把 ALL_PROXY 改为与 HTTP_PROXY 一致的 http:// 形式,或单独指定 socks-port。许多工具只认大写变量,也有工具认小写 http_proxy;为省事可同时导出两套,避免个别 CLI 不认大写。
提示:NO_PROXY 中保留 localhost,可避免本机仅监听 127.0.0.1 的服务误走代理。
3Git:全局或按仓库指定 HTTP 代理
Git 不会永远继承 shell 的全部环境行为(尤其在部分 GUI 或子进程中),建议显式配置:
git config --global http.proxy http://172.24.160.1:7890
git config --global https.proxy http://172.24.160.1:7890
将示例 IP 换成你的宿主机地址。若仅代理 GitHub,可使用 http.https://github.com.proxy 等形式缩小范围,避免公司内网 Git 仓库被误送代理。使用 SSH 协议([email protected]:)时,流量不经过上述 HTTP 代理,需改用 HTTPS 远端,或单独配置 ProxyCommand / nc 走 SOCKS,这已超出新手最短路径,可按团队规范选型。
4npm:registry、proxy 与镜像取舍
npm 会读取环境变量,也可单独设置:
npm config set proxy http://172.24.160.1:7890
npm config set https-proxy http://172.24.160.1:7890
国内环境常配合淘宝等镜像源;若镜像已能满速直连,可不必让 registry 流量再绕代理,以减少故障面。若慢的是 github.com、raw.githubusercontent.com 等依赖,问题往往在 DNS 或规则分流,可结合 Meta 内核 DNS 防泄漏 与上文 GitHub/npm 分流文一并排查。npx、yarn、pnpm 通常继承同类环境变量;若仍有漏网之鱼,用 npm config list -l 查看实际生效项。
关于「localhost 转发」与端口映射的认知纠偏
搜索「WSL2 localhost 转发」时,容易与 Windows 的端口转发或 localhost 复用混淆。对 Clash 而言,核心不是把 WSL2 的某个端口映到 Windows,而是WSL2 作为客户端,主动连接宿主机 IP 上的代理监听端口。只有在少数集成场景(例如在 Windows 浏览器访问 WSL2 内起的开发服务器)才强调反向的 localhost 转发;与「让 Git/npm 走 Clash」的目标方向相反,不要混用两套话术,以免排错时改错设置。
Windows 防火墙与快速自检清单
若 curl 报连接超时或拒绝,依次检查:① Clash 是否运行、端口是否为 7890(或你的自定义值);② 是否开启「允许局域网」;③ Windows Defender 防火墙是否拦截了该端口的入站(可为 Clash 可执行文件放通专用规则);④ 宿主机 IP 是否已更新;⑤ 是否误把代理指向了 WSL2 内的 127.0.0.1。也可用 Windows 侧 netstat -an | findstr 7890 确认监听地址是否为 0.0.0.0:7890 或包含局域网网段。
当命令行已通而 Git 仍失败时,优先 git config --list --show-origin | grep -i proxy 查残留配置;当 npm 异常时,查 ~/.npmrc 与项目内 .npmrc 是否覆盖全局设置。保持「宿主机 IP + 正确端口 + 防火墙 + 客户端允许局域网」四件事一致,绝大多数「WSL2 不走代理」类问题都能收敛。
合规提醒:请仅在法律与网络使用政策允许的范围内使用代理;企业或校园网络可能对绕行有明确禁止,违者后果自负。
关于获取软件:Clash 系客户端在 GitHub 等平台可查阅开源与更新记录;若你需要Windows 安装包与集中下载入口,请优先使用 本站下载页,与源码仓库用途区分理解。
小结
WSL2 与 Windows 代理是两条网络栈:Clash 在宿主监听混合端口后,只要在 WSL2 内用宿主机 IP 代替 127.0.0.1,并配好 Git、npm 与 shell 环境变量,就能让终端工具链与浏览器侧体验对齐。与 UWP Loopback 不同,本文面向子系统与开发者命令行;规则与 DNS 仍可交给 Meta 内核侧持续打磨。
相比临时 export 一堆变量却找不到失效原因,先固定「取 IP → 开局域网 → 配三处(shell、Git、npm)」的顺序,排错成本更低;在稳定性与规则生态上,Clash 系仍是多数开发者的务实选择。