WSL2 走不通 Windows 上的 Clash?镜像网络与端口转发逐步修复
很多开发者在 Windows 上已经用 Clash 把浏览器、办公软件走通,但一进 WSL2(Ubuntu 等),apt、curl、git 或 Docker 拉镜像仍然超时或直连失败。根因往往不是「订阅坏了」,而是网络命名空间不同:WSL2 里的 127.0.0.1 指向的是子系统自己,并不等价于你在 Windows 里看到的本机回环;同时 Clash 若只监听 127.0.0.1,从虚拟网段过来的连接会被拒绝。本文按可验证顺序说明如何把 mixed-port、allow-lan、宿主机可达地址、代理环境变量与可选的镜像网络模式、端口转发对齐,让终端与容器与 Windows 侧共用同一套出口策略。
典型现象:只有 Windows「像通了」
Edge 或 Chrome 已能打开境外站点,说明 Windows 上的系统代理或 TUN 大体工作正常。但在 WSL 终端执行 curl https://example.com 仍卡住,或 apt update 报连接超时,Docker 则表现为 docker pull 一直重试。此时若你直接把浏览器里抄来的 127.0.0.1:7890 填进 WSL,大概率无效:对 WSL2 而言,那是「子系统内部的回环」,Windows 上 Clash 监听的端口并不自动出现在那里。
另一条常见弯路是:以为开了「系统代理」就万事大吉。许多命令行工具不读取 Windows 的 IE/系统代理设置,除非你显式配置 http_proxy 等变量,或使用能走 TUN 的全局捕获方案。本文优先走「HTTP/SOCKS 代理 + 环境变量」这条对 apt、npm、pip、git 最直观的路径;若你已在使用 Clash 的 TUN 且希望 WSL 流量也被内核层接管,需要另行核对虚拟网卡、路由与 DNS,复杂度更高,建议先完成 HTTP 代理基线再叠加。
先定一条成功标准
在 WSL 里用 curl -I 或 wget 访问一个需要代理才能打开的 HTTPS 站点,确认返回头正常;再跑 apt update 或一次 docker pull。每一步只改一个变量,避免同时改 DNS、规则与端口。
第一步:让 Clash 对「局域网/WSL 侧」可达
默认情况下,部分客户端会把入站绑定在 127.0.0.1,这意味着只有 Windows 本机进程能连。WSL2 通过虚拟网络访问 Windows 时,源地址不在本机回环上,因此需要让代理监听 0.0.0.0 或明确绑定到包含该网段的接口,并打开允许局域网(常见选项名为 Allow LAN 或在配置里 allow-lan: true)。HTTP 与 SOCKS 若合并在一个 mixed-port,填环境变量时只需记一个端口,具体以你在 YAML 或 GUI 中看到的为准。
更细的 mixed-port、防火墙与「手机连电脑热点」类场景,可参考站内 《Clash 局域网共享代理:mixed-port 与 allow-lan》;Windows 上首次安装与模式切换请对照 《Clash for Windows 安装与配置》。若 Allow LAN 已开仍连不上,请在 Windows Defender 防火墙中为 Clash 可执行文件放行入站规则,或临时关闭防火墙做对比测试(仅用于定位,长期仍建议最小放行)。
Windows 侧快速自检
- 在 Clash 日志或配置中确认 mixed-port(或分别的 HTTP、SOCKS 端口)。
- 确认 allow-lan 已启用,且监听地址不是仅限 127.0.0.1。
- 在 Windows 本机用另一个端口测试工具或
curl指向「局域网 IP:端口」验证入站可达。
第二步:在 WSL2 里用对「宿主机地址」
在经典 NAT 型 WSL2 网络中,Windows 宿主机对应一个从 Linux 视角可达的网关地址。常见获取方式包括查看默认路由网关,或读取 /etc/resolv.conf 中的 nameserver(在不少构建上该地址指向宿主机,用于 DNS 转发)。不同 Windows 版本与小版本下行为可能略有差异,因此不要死记某一个 IP,而应在当前发行版里用命令现查。
# Show default gateway (often the Windows host from WSL2)
ip route show | grep -i default
# Some setups expose host via resolv.conf nameserver
grep -i nameserver /etc/resolv.conf
将查到的地址记为 WIN_HOST,代理 URL 即 http://WIN_HOST:7890(端口换成你的 mixed-port)。若使用 SOCKS5,则使用 socks5://WIN_HOST:7891 等形式,与 Clash 实际监听一致即可。若此处 IP 会随休眠或网络切换变化,可把写入 ~/.bashrc 的脚本改成每次启动 shell 时动态解析,减少「昨天能用今天失效」的困扰。
安全边界
Allow LAN 等于把代理暴露给能路由到你电脑的其他设备。仅在可信网络开启,或配合防火墙限制源网段;不要在公共 Wi‑Fi 上长期打开 broad listen。
镜像网络模式:何时可以让 localhost「对齐」
从 Windows 11 起,WSL 支持镜像网络模式(mirrored),目标之一是让子系统与宿主在网络行为上更一致,其中包括对 localhost 的互通语义(具体行为随版本演进,请以微软文档为准)。若你启用镜像模式后,在 WSL 内访问 127.0.0.1:端口 能直达 Windows 上监听的 Clash,则可以把代理地址简化为本机回环,减少维护宿主机 IP 的成本。
启用方式通常涉及用户目录下的 .wslconfig 与发行版内 /etc/wsl.conf 的组合配置,修改后需要执行 wsl --shutdown 再启动发行版生效。若升级系统后行为变化,优先查阅当前版本的发行说明。镜像模式也可能影响其他依赖虚拟网卡拓扑的工具,若出现新问题,可回退到 NAT + 宿主机 IP + 环境变量的经典方案。
第三步:代理环境变量与 no_proxy
大多数 CLI 与语言包管理器识别 http_proxy、https_proxy、all_proxy(SOCKS 时常用)以及对应的大写形式。建议同时设置大写与小写,减少个别工具只认其中一种的情况。no_proxy 用于内网与本地注册表直连,避免把公司内网 Git、私有 PyPI、Kubernetes API 误送进代理。
# Example — replace host:port with your WIN_HOST and Clash mixed-port
export http_proxy="http://WIN_HOST:7890"
export https_proxy="http://WIN_HOST:7890"
export all_proxy="socks5://WIN_HOST:7890"
export no_proxy="localhost,127.0.0.1,::1,10.0.0.0/8,192.168.0.0/16"
apt 在部分版本上还会参考 /etc/apt/apt.conf.d/ 中的 Acquire::http::Proxy;若你只 export 变量仍不生效,可单独为 apt 写一行配置。git 可使用 git config --global http.proxy,或在需要时只对特定远程生效。持久化时把 export 写入 ~/.bashrc 或 ~/.profile,Zsh 用户则写入 ~/.zshrc。
备选:用 netsh 端口转发做「固定入口」
若你希望 WSL 始终访问某个固定地址(例如固定连 127.0.0.1:17890),可在 Windows 管理员 PowerShell 中使用 netsh interface portproxy,把 WSL 侧发起的连接转发到 Clash 实际监听端口。该方式多一道维护,但在多发行版、多工具硬编码 localhost 时有时更省事。记得在防火墙中放行对应端口,并在升级或重装 Clash 后复查转发规则是否仍指向正确端口。
# Run in elevated PowerShell — illustrative; adjust listen/connect ports
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=17890 connectaddress=127.0.0.1 connectport=7890
Docker:daemon 代理与 build 场景
若使用 Docker Desktop 的 WSL2 后端,镜像拉取可能发生在集成发行版或独立 VM 中,仅在你登录的 shell 里 export 变量未必足够。需要在 Docker daemon 层配置代理(例如 Docker Desktop 设置页中的代理项,或 /etc/docker/daemon.json 配合 systemd drop-in,视安装方式而定)。构建镜像时,BuildKit 阶段还可能需要 docker build 的 --build-arg 传入 HTTP_PROXY,否则 Dockerfile 内的 apt-get 仍直连。
在 Linux 服务器上纯 Docker 部署 Clash 的流程与本文场景不同,可参考 《Clash Meta Docker 部署》;本文聚焦「Windows 跑 Clash、WSL2 跑 workload」这一组合。
DNS 与「能连上代理但仍解析失败」
有时 TCP 已到 Clash,但解析阶段仍走意外路径,表现为间歇性超时。若你在 Clash 中启用了 fake-ip,请确保命令行工具的解析行为与规则一致;更系统的说明见 《DNS 泄漏与 fake-ip 排查》。WSL 内也可临时指定 --dns-servers 或使用公共 DNS 做对比测试,但每次只改一个环节,以免与 Windows 侧策略打架。
常见问题
开了镜像模式仍然连不上 127.0.0.1
核对 Clash 是否仍只监听 127.0.0.1;镜像模式并不替代 allow-lan 与绑定地址。回到「宿主机 IP + 环境变量」路径通常可立即验证。
休眠或换 Wi‑Fi 后失效
宿主机 IP 可能变化。把代理地址改为启动 shell 时动态解析,或改用端口转发固定本地入口。
HTTP 通 SOCKS 不通或反之
核对 mixed-port 与分开端口是否混用;all_proxy 协议前缀必须与 Clash 实际提供的 SOCKS 版本一致。
实操检查清单
- Windows:Clash 已开,mixed-port 已知,allow-lan 与监听地址正确。
- WSL:解析出当前可用的宿主机地址,或确认镜像模式下 localhost 语义。
- export 代理变量并
curl -I验证;再测 apt 或 docker pull。 - 根据需要收紧 no_proxy,避免内网流量误走代理。
- 记录你改动过的防火墙与 portproxy 规则,便于升级系统后复查。
统一出口,从可用的客户端开始
把 Windows 与 WSL2 放在同一套 Clash 策略下,本质是补齐监听地址、可达路由与环境变量三块拼图。拼图对齐后,终端与容器的排障会明显简单:日志里能看到请求是否到达 Clash、命中哪条规则,而不是停留在「莫名其妙连不上」。