为什么 Windows 里 Clash 正常,WSL2 终端却像「WSL2 不走代理」?
这是很多在 Windows 子系统里做开发的人会遇到的割裂:宿主机 Edge 或 Chrome 已经能访问检测站看到节点出口,回到 WSL2 的 Ubuntu 里执行 curl、sudo apt update、git clone,延迟与出口却仍像本地宽带,甚至出现「能 ping 通域名但 HTTPS 握手失败」这类更像 DNS 或证书链问题的现象。搜索里常见「Clash WSL2 代理」「WSL2 不走代理」——根因通常不是订阅坏了,而是WSL2 与 Windows 并不是共享同一个 loopback 视角:你在 Linux 发行版里访问 127.0.0.1:7890,指向的是子系统自己的回环,而不是宿主机上 Clash 监听的端口。
另一方面,Windows 侧若只勾了「系统代理」,主要影响遵循系统代理栈的桌面应用;WSL2 内的命令行工具同样不会自动继承你在图形界面里看到的代理设置,而是依赖 http_proxy、https_proxy、ALL_PROXY 等环境变量,或各自配置(如 git 的 http.proxy)。因此要把「宿主机上的 Clash 入站」桥接到 WSL2,需要三件事对齐:监听地址与防火墙(让子系统网段能连上)、正确的宿主机 IP(不要用错成 127.0.0.1)、与 Clash DNS 模式相匹配的解析路径。下面按可复现实验顺序展开。
若你主要仍在 Windows 桌面浏览器侧排障,可先对照《Clash Windows 11 系统代理不生效》;若你关心 Fake-IP 与 nameserver 细节,可并行阅读《Clash Fake-IP 与 DNS 怎么配》。本文专注 WSL2 与 Windows 宿主机之间的代理桥接,与《macOS 终端与 Homebrew 环境变量》形成平台互补。
先建立心智模型:WSL2 网络边界与「Windows 子系统 代理桥接」
WSL2 运行在虚拟化网络命名空间中,通过虚拟网卡与 Windows 通信。对 Linux 侧来说,「去宿主机上的服务」应理解为:向 Windows 主机在该虚拟网络上的那个 IP 发起 TCP 连接,而不是连本机 127.0.0.1。Clash 在 Windows 上监听的混合端口(常见如 7890,请以你客户端界面为准)若只绑定在 127.0.0.1,从 WSL2 视角是不可达的,这就是大量「明明开了 Clash,子系统却完全不走」的第一道门槛。
因此 Windows 子系统 代理桥接的第一步,是让 Clash 的入站对「来自子系统网卡的连接」开放,并在 Windows 防火墙中放行对应端口的入站规则;第二步才是在 WSL2 内把 http_proxy 指到 http://宿主机IP:端口。部分新版 WSL 支持「镜像网络」等特性,可能让 localhost 语义更接近宿主机,但不同版本与发行版组合差异很大,下文仍以最通用、可移植的「显式宿主机 IP」写法为主,并在后文单独说明镜像模式下的简化可能。
第一步:在 Windows 上让 Clash 监听可对 WSL2 访问的地址
在 Clash Verge Rev、Clash for Windows、Mihomo Party 等客户端中,找到混合端口 / Mixed Port,并确认已开启「允许局域网连接 / Allow LAN」或等价选项,使监听地址包含 0.0.0.0 或至少包含能被子系统访问的接口。仅监听 127.0.0.1 时,WSL2 侧通常无法直连。更完整的局域网与防火墙思路,可参考《Clash 局域网共享与防火墙》中的原则:客户端、系统防火墙、路由器访客网络要一起看。
在 Windows Defender 防火墙中,为 Clash 主程序或对应端口添加入站「允许」规则,避免子系统 SYN 包被静默丢弃。若你使用第三方安全软件,同样需要放行。改完设置后,可在 Windows 上用 netstat 或资源监视器确认端口监听在 0.0.0.0:你的端口 或类似形态,而不是仅 127.0.0.1。
7890 作为混合端口示例,请你替换为自己客户端里实际显示的数字。端口抄错时,后面所有验证都会失败。
第二步:在 WSL2 内获取 Windows 宿主机 IP
在 Ubuntu 等发行版的 shell 中,常用下面两种方式之一获取默认网关地址,它在多数 WSL2 场景下即宿主机在该虚拟网络上的 IP:
# Option A: default gateway from ip route (common on Ubuntu WSL2)
ip route show | awk '/^default/ {print $3; exit}'
# Option B: nameserver line in auto-generated resolv.conf (may vary by WSL version)
grep -m1 '^nameserver' /etc/resolv.conf | awk '{print $2}'
把得到的地址记为 HOST_IP。若两条命令结果不一致,或你启用了 WSL 的 DNS 隧道等新特性,优先以能实际连通混合端口的那条为准:可在 WSL2 内执行 curl -I --connect-timeout 3 "http://${HOST_IP}:7890"(将 IP 与端口替换为你的真实值)观察是否快速返回代理软件的 HTTP 响应头或特征错误页,而不是长时间超时。
若你使用较新的「镜像网络 / localhost 转发」类功能,部分机器上可以直接把代理写成 http://127.0.0.1:7890 也能通,这取决于 Windows 与 WSL 版本组合。为减少文档与读者环境不一致带来的困惑,建议先掌握「宿主机 IP」这条通用路径,再在确认版本支持后尝试简化写法。
第三步:在 WSL2 shell 中导出代理环境变量并验证 curl
在确认 HOST_IP 与端口可从 WSL2 访问后,临时导出:
# Replace HOST_IP and 7890 with your values — test in current shell only first
export HOST_IP="$(ip route show | awk '/^default/ {print $3; exit}')"
export http_proxy="http://${HOST_IP}:7890"
export https_proxy="http://${HOST_IP}:7890"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
export all_proxy="socks5://${HOST_IP}:7890"
export ALL_PROXY="$all_proxy"
说明:HTTP/HTTPS 流量多数 CLI 会读 http_proxy 与 https_proxy;需要 SOCKS 的工具可读 all_proxy。大小写各写一遍,可减少个别程序只认大写环境变量的坑。随后在同一终端执行:
echo "$http_proxy" "$https_proxy"
curl -I --connect-timeout 15 https://www.google.com
若链路正常,curl 应能较快返回 HTTP 头(具体站点策略因地区与节点而异)。若仍卡住,回到 Windows 侧复查监听地址、防火墙,以及公司网络是否阻断子系统访问宿主机该端口。
第四步:让 apt、git 等工具复用同一套变量
sudo apt update 会丢弃普通用户的代理环境,常见做法包括:在 root 环境同样导出变量、为 apt 单独写 /etc/apt/apt.conf.d/95proxy、或使用 sudo -E 保留环境(视发行版与安全策略而定)。对多数个人开发机,可用简单可逆的 apt 配置片段(注意把 IP 与端口改成你的):
# Example apt proxy drop-in — replace IP:port before applying
# echo 'Acquire::http::Proxy "http://YOUR_HOST_IP:7890/";' | sudo tee /etc/apt/apt.conf.d/95clashproxy
# echo 'Acquire::https::Proxy "http://YOUR_HOST_IP:7890/";' | sudo tee -a /etc/apt/apt.conf.d/95clashproxy
对 git,若已正确设置环境变量仍异常,可检查是否曾写入冲突的 git config --global http.proxy;必要时用 git config --global --unset http.proxy 清理后再测 git ls-remote。
第五步:DNS 同步——避免「代理通了但解析仍怪」
当 Clash 使用 Fake-IP 等模式时,解析行为与直连 DNS 明显不同:有些场景下,Windows 浏览器走 Clash 内置 DNS,而 WSL2 仍通过自身 /etc/resolv.conf 走另一路解析,表现为「网页能开、子系统 curl 报证书或解析到奇怪地址」。此时需要把问题拆成两层:流量有没有进 Clash 与 DNS 回答是否由 Clash 参与。更系统的 Fake-IP 与 nameserver 搭配,请对照《Fake-IP 与 DNS 泄漏》中的原则,在 Clash 配置侧先保证逻辑自洽。
在 WSL2 侧,常见排查包括:查看 /etc/resolv.conf 是否由 WSL 自动生成、是否指向宿主机解析器;在需要时通过 /etc/wsl.conf 关闭自动生成并自建 resolv.conf(操作前请备份,且不同 Windows 版本行为可能变化)。若你暂时不想改系统文件,也可以先确保 HTTP(S) 流量确实指向 Clash,再结合 Clash 日志观察域名与解析结果是否一致。
第六步:持久化——profile、/etc/environment 与 systemd(可选)
临时 export 只对当前 shell 有效。个人用户常用做法是写入 ~/.bashrc 或 ~/.zshrc,在文件末尾追加与上文相同的一组变量,并重新登录 shell。对需要全局生效的服务,可考虑在 /etc/environment 写入(修改前备份,语法错误可能导致登录困难)。
若你希望 systemd 管理的服务(如某些后台守护进程)也继承代理,需要 WSL 发行版启用 systemd(在 /etc/wsl.conf 的 [boot] 段配置 systemd=true 等,具体以微软与发行版文档为准),再使用 systemd user 单元或 drop-in 设置 Environment=。systemd 路径与版本差异较大,建议在你确认确实需要「服务级代理」时再深入,普通开发场景多数情况下shell 级环境变量已足够。
备选:从根上减少「每个工具是否认代理变量」的差异
若你希望尽量少配环境变量、让更多进程默认被接管,可在硬件与权限允许的前提下评估 Windows 或 WSL 侧的 TUN / 虚拟网卡类方案,让流量在更底层进入 Clash。适用场景与风险见《Clash TUN 模式详解》。与本文的「显式 HTTP 代理桥接」并不冲突,可按需求二选一或组合使用。
排查清单(简版)
- Clash 混合端口在 Windows 上不是仅监听 127.0.0.1,Allow LAN 已开启。
- Windows 防火墙与第三方安全软件已放行该端口入站。
- WSL2 内用宿主机 IP(或经验证的 localhost 转发)拼出的代理 URL 可被
curl访问。 http_proxy/https_proxy在执行命令的同一 shell 中非空;sudo场景单独处理。- DNS 现象异常时,先对照 Clash 的 Fake-IP 与 nameserver 配置,再决定是否调整 WSL 的
resolv.conf策略。
写在最后
Clash WSL2 代理的本质,是把「子系统发出的 TCP 连接」导向「宿主机上正在监听的 Clash 入站」,因此一定会碰到网络命名空间与回环地址语义不同的问题;把WSL2 不走代理简单归因于订阅或规则,往往会绕远路。按本文顺序检查监听地址、防火墙、宿主机 IP 与环境变量,再配合 DNS 与 Fake-IP 文档对齐解析路径,大多数 curl、apt、git 场景都能稳定下来。
若你刚完成基础安装,建议先通读安装与配置教程确认订阅与规则无误,再回到本文做「双栈环境」下的桥接微调。维护活跃、对 Mihomo 内核兼容友好的客户端可从本站下载页获取。相比零散论坛帖,把 Windows 桌面、WSL2 与 Clash 日志放在同一套心智模型下排查,长期成本更低。→ 立即免费下载 Clash,开启流畅上网新体验。