典型现象:Windows 正常、WSL2 里命令行仍「像没开代理」

很多人第一次把 Clash Verge RevClash for Windows 系客户端在 Windows 11 上配好:系统代理或 TUN 一开,浏览器立刻能打开外站。随后打开 WSL2 里的 Ubuntu,照旧执行 sudo apt updatecurl https://www.google.com,却发现仍然卡住、超时,或报「Could not resolve host」。这类问题在中文社区里被反复提问,本质往往不是订阅坏了,而是双栈网络视角没对齐:Windows 侧的「本机回环」与 WSL2 里的「本机回环」不是同一个地址空间;系统代理也不会自动灌进 WSL 里的每个 shell。

本文假设你已在 Windows 上能稳定使用 Clash(含节点选择与规则),只解决「子系统里显式把 TCP 流量送进 Windows 上 Clash 入站」这一条链路。若你怀疑是节点 TLS 或 timeout,请先对照 Clash 连不上?从日志读懂 timeout 与 TLS,再回到本文核对「WSL 是否真的连到了 Windows 的代理端口」。

为什么 127.0.0.1 在 WSL2 里不是 Windows 上的 Clash

WSL2 使用轻量虚拟化:Linux 发行版跑在虚拟网卡背后,通过 NAT 访问外网。你在 WSL 里看到的 127.0.0.1,只代表这台 Linux 虚拟机自己的回环接口。Windows 上监听在 127.0.0.1:7890Clash mixed-port,从 WSL 视角是「另一台机器上的端口」,不会 magically 映射过来。于是把代理写成 http://127.0.0.1:7890 时,要么连到空端口,要么连到 WSL 里别的进程——这就是「Windows 明明能上,WSL 却像没代理」的头号误区。

要让 WSL 里的 curlaptgit 走 Clash,必须把代理目标写成「从 WSL 路由可达的 Windows 宿主机地址 + 与 Clash 配置一致的端口」。端口通常就是你在配置里写的 mixed-port,或界面上的「混合端口」数字;地址则需要用下面一节的方法求出来,而不是拍脑袋写 localhost

第一步:拿到 Windows 宿主机在 WSL2 视角下的 IP

最常见、也最省事的做法是读 WSL 自动生成的 /etc/resolv.conf:其中的 nameserver 一行,在默认网络模型下往往就是 Windows 宿主机面向 WSL 虚拟网卡的地址。在 shell 里执行 grep nameserver /etc/resolv.conf,记下那个 IPv4(常见形态为 172.x.x.x)。随后用 ping -c 1 对该地址做一次连通性探测,确认不是陈旧缓存。

若你的发行版启用了 systemd-resolved 或自定义脚本改写 resolv.confnameserver 可能指向 127.0.0.53 这类本地 stub,此时不宜再把它当作 Windows IP。可改用路由表:ip route show | grep -i default,默认网关那一行的「via」地址,在不少环境里同样是 Windows 侧在 WSL 网段中的接口。两种方法取到的地址应一致或同属一段私网;若互相矛盾,以「能 nc -vz 地址 7890 连上 Clash 端口」的一方为准。

Read Windows host IP from resolv.conf (typical WSL2)
grep -m1 nameserver /etc/resolv.conf | awk '{print $2}'
Quick TCP check to Clash mixed-port on Windows (replace IP:PORT)
nc -vz 172.24.160.1 7890

不建议把该 IP 当作永久常量写死在团队文档里:休眠恢复、切换网络或 WSL 大版本升级后,虚拟网段可能变化。更稳妥的做法是在 ~/.bashrc 里用一行命令动态解析出 WINDOWS_HOST 变量,再拼到 HTTP_PROXY 里;下文给出模板。

命名与版本:下文 YAML 键名以 Meta 系(Mihomo)常见写法为例;图形客户端可能在界面中显示为「允许局域网连接」「混合端口」等。若你使用分离的 portsocks-port,把示例中的端口号拆成两套 URL 即可,逻辑不变。

Clash 侧:mixed-portallow-lan 与监听地址

当代理入口写在「Windows IP」而不是 127.0.0.1 时,Clash 必须在 Windows 上对该地址监听,否则 SYN 包根本到不了进程。实践中最省脑的配置组合是:开启 mixed-port(同一端口同时接受 HTTP 与 SOCKS5),设置 allow-lan: true,并把 bind-address 设为 '*' 或明确绑定到包含 WSL 网卡的接口。仅监听 127.0.0.1 时,来自 WSL 虚拟网段的连接会被操作系统直接拒绝,表现为 Connection refused

Illustrative YAML fragment (adapt port and keys to your core)
mixed-port: 7890
allow-lan: true
bind-address: '*'

allow-lan 与绑定地址的语义,与「手机连电脑热点共享代理」是同一类问题:本质是「非本机回环的客户端能否连到入站端口」。更完整的防火墙与网段说明,可交叉阅读 Clash 局域网共享后手机连不上?防火墙、绑定地址与网段一次查清,把其中的「局域网设备」 mentally 换成「WSL2 虚拟网卡」即可。

Windows 防火墙与「仅本机」入站:连不上的头号外因

即使 Clash 已 allow-lanWindows Defender 防火墙仍可能拦截从 WSL 虚拟网卡进入的 TCP 7890。症状是 WSL 里 nc 超时或握手立即失败,而 Windows 本机浏览器访问外站正常。处理思路与放行局域网入站相同:为 Clash 主程序添加入站规则,允许专用子网或「来自 WSL 网段」的 TCP 到达 mixed-port;修改后务必在 WSL 里重新跑一次端口探测。

部分公司安全软件会额外挂钩 Winsock 或过滤环回以外流量,若你已放行防火墙仍不通,可临时退出第三方套件做 A/B 对比。生产环境请遵守单位安全策略,仅在授权设备上操作。

安全提示:开启 allow-lan 并把入站绑定到 * 后,同一局域网内的其他设备也可能向你的代理端口发起连接。仅在可信家庭或开发网络使用;公共 Wi‑Fi 上应保持仅本机监听。

第二步:在 WSL2 shell 里写对 HTTP_PROXY / ALL_PROXY

取得 WINDOWS_HOST 后,环境变量模板与纯 Linux 终端相同,只是把 127.0.0.1 换成该地址。HTTP_PROXYHTTPS_PROXY 指向 http://$WINDOWS_HOST:7890;需要远程 DNS 解析的 SOCKS 场景用 socks5h://$WINDOWS_HOST:7890NO_PROXY 仍要列出内网段与本地回环,避免访问公司 Git、私有 PyPI、Kubernetes API 时被误送出境。

Shell snippet — dynamic WINDOWS_HOST for WSL2 bash/zsh
export WINDOWS_HOST=$(grep -m1 nameserver /etc/resolv.conf | awk '{print $2}')
export HTTP_PROXY="http://${WINDOWS_HOST}:7890"
export HTTPS_PROXY="http://${WINDOWS_HOST}:7890"
export ALL_PROXY="socks5h://${WINDOWS_HOST}:7890"
export NO_PROXY="localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"

验证顺序建议固定:先 curl -I https://www.example.com 看是否仍超时;再在 Windows 侧 Clash 连接日志中确认出现来自 WSL 网段的入站记录。若 HTTP 正常而某工具仍不走代理,补 ALL_PROXY 或查阅该工具是否忽略标准变量——与 Docker 与终端走 Clash:mixed-port 与环境变量 中的表格化排查思路一致。

aptgitcurl:各自还认哪些配置

APT 除环境变量外,也认 /etc/apt/apt.conf.d/ 里的 Acquire::http::ProxyAcquire::https::Proxy。在团队镜像或 CI 场景,显式写 apt 配置比依赖 shell 环境更稳定;个人开发机则通常 sudo -E apt update 即可继承当前 HTTP_PROXY。若仍失败,先确认代理 URL 可被 apt 使用的 HTTP 库解析,而不是误填了仅 SOCKS 的 scheme。

Git 可额外设置 git config --global http.proxy http://$WINDOWS_HOST:7890,对 HTTPS 远程往往比单纯依赖 ALL_PROXY 更直观。SSH 远程([email protected]:)不走 HTTP 代理,需要 ProxyCommand 或改用 HTTPS,这与 Windows 侧 Clash 是否工作无关。

curlHTTPS_PROXY-x 参数的行为在手册中有明确说明;排障时建议加 -v 观察 CONNECT 目标是否是 WINDOWS_HOST:7890,避免实际仍直连。

resolv.conf、DNS 与 Clash dns 模块的交叉影响

WSL 里另一个高频坑是 DNS/etc/resolv.conf 里的 nameserver 被你改写成公共 DNS 后,可能仍无法解析某些域名——因为真正决定解析路径的还有 Clash 的 dns 配置、是否 fake-ip、以及规则里对 DNS 服务器的分流。现象常表现为「ping 域名失败但 IP 直连正常」或「浏览器能开、apt 报 Could not resolve」。此时不要只盯着 WSL:应在 Windows 侧打开 Clash 的 DNS 日志,并对照 Clash Meta 如何配置 DNS 检查 nameserverfallbackfake-ip-filter

若你把 WINDOWS_HOST 同时当作 DNS 转发目标使用,请确认 Windows 上是否有服务在该地址提供 DNS,且未被防火墙拦截;多数用户场景下,更简单的做法是保持 WSL 默认解析链,让 HTTP/SOCKS 流量进 Clash,由 Clash 侧统一处理远程解析(尤其在使用 socks5h:// 时)。

可选:Windows 11 的 mirrored / host 网络模式说明了什么

微软在较新的 Windows 11 与 WSL 版本中实验/提供过「镜像网络」「localhost 互通」等能力,使得 127.0.0.1 在部分配置下可以穿透到 Windows 服务。不同机器、不同 WSL 内核与 .wslconfig 组合行为并不完全一致。本文仍以「显式 Windows 宿主机 IP + mixed-port」作为主路径,因为它在版本跨度上最可预测;若你已启用镜像模式且验证 127.0.0.1:7890 可用,可以简化环境变量,但请在升级 Windows 后复查一次。

排障清单:从「能连端口」到「规则命中」

结语:把「宿主机 IP + 端口」固化成可切换片段

WSL2Windows 双栈并存时,记住一句话即可少踩九成坑:127.0.0.1 在子系统里不是宿主上的 Clash。把 宿主机 IP 动态解析出来,对齐 mixed-portallow-lan、防火墙与 HTTP/SOCKS 环境变量,再按需处理 resolv.conf 与 Clash DNSaptcurlgit 就能与桌面侧共享同一套节点与规则。相比每次重装子系统,把这一段写进 ~/.bashrc 并用函数开关代理,长期维护成本更低。

成熟图形客户端能把入站、TUN、DNS 模块放在同一界面里对照,排障时不必在注册表与多份 YAML 之间来回跳转;对需要频繁在 Windows 与 WSL 间切换的开发场景,这种「一眼看清端口与绑定」的体验差异很明显。

相比其它同类工具,把连接日志与策略编辑放在手边、用现代内核承载规则,更容易验证「WSL 里的这条 curl 是否真的进了本机 Clash」。

立即免费下载 Clash,开启流畅上网新体验,在 Windows 上确认 mixed-portallow-lan,再把本文中的 WINDOWS_HOST 片段粘贴进 WSL 的 shell 配置即可闭环。