现象:Windows 浏览器正常,WSL2 里 apt、curl 却像直连
不少开发者会在同一台机器上遇到一种割裂感:Windows 侧 Edge 或 Chrome 已经能顺畅访问外网,Clash 或 Verge 的连接日志里也能看到规则命中,但一切换到 WSL2 里的 Ubuntu,执行 sudo apt update 或 curl -I https://... 仍然慢到超时,甚至握手失败。有人尝试在子系统里照搬 Windows PowerShell 那一套,把 http_proxy 写成 http://127.0.0.1:7890,结果发现完全无效——这不是端口填错那么简单,而是 WSL2 网络模型里一个常被忽略的事实:子系统里的回环地址与 Windows 宿主机不是同一个网络接口。
本文与站内《Windows 终端与 Clash 混合端口》同属「混合端口 + 显式代理」路线,但场景从宿主机终端换成了 WSL2 全环境:重点放在如何拿到「从 Linux 虚拟机看向 Windows」的正确 IP、如何让 Clash 在宿主机上对来自 WSL 的入站连接开放监听,以及 apt 与 curl 各自吃哪一类配置。若你最终希望由内核侧统一接管路由,可再对照《Windows TUN 与防火墙排查》评估是否上 TUN;这里先不展开驱动与全局路由,先把「子系统 → 宿主机混合端口」这条链路跑通。
为什么 WSL2 里写 127.0.0.1 往往连不到 Windows 上的 Clash
WSL2 的发行版跑在轻量级虚拟机里,拥有独立的网络命名空间。你在 Ubuntu shell 里访问的 127.0.0.1,指的是这台 Linux 自己的环回接口,而不是「正在运行 Clash 的那台 Windows」。因此,即便 Clash 在 Windows 上监听 127.0.0.1:混合端口,WSL2 内的进程把流量送到自己的 127.0.0.1 时,只会撞到 Linux 侧空端口或别的服务,与 Windows 上的 Clash 毫无关系。这也是大量教程里「照抄 127.0.0.1」在 WSL2 下失效的根因。
从 Windows 11 起,部分环境可以启用 mirrored 网络模式 等特性,使 localhost 转发行为更接近直觉;但默认与传统 WSL2 拓扑下,更稳妥、可复现的做法仍是:显式解析 Windows 宿主机在虚拟网卡上的地址,再把代理 URL 指向 http://该地址:混合端口。下文以这一通用路径为主轴,并在单独小节补充「镜像网络 / localhost 转发」的注意点,避免你换机或换版本后配置突然失效。
第一步:在 WSL2 内解析 Windows 宿主机 IP
在经典 WSL2 配置中,Windows 宿主机通常表现为虚拟交换机上的网关地址。最常见、也最便于脚本化的读法是查看 /etc/resolv.conf 中的 nameserver 行:该地址往往就是从子系统视角看到的 Windows 主机。你可以在 Ubuntu 里执行下面命令,把输出记下来,后面所有代理 URL 都会用到它(以下示例仅作演示,请以你机器实际输出为准)。
grep -m1 '^nameserver' /etc/resolv.conf | awk '{print $2}'
若你使用自定义 DNS 或企业策略改写了 resolv.conf,上述值可能不再是宿主机网关。此时可在 Windows PowerShell 中执行 ipconfig,在输出里找到带「vEthernet (WSL)」或类似描述的网络适配器,读取其 IPv4 地址,再回到 WSL2 内用 ping 或 curl 探测连通性。关键是:代理目标必须是「WSL2 路由可达的那张 Windows 网卡地址」,而不是凭感觉猜的公网 IP 或无线网卡段。
若 resolv.conf 由系统自动生成且每次启动变化,可把「动态读取 nameserver」写进 ~/.bashrc 或 ~/.profile,避免硬编码旧 IP 导致某天更新后突然断代理。
第二步:让 Clash 混合端口接受来自 WSL2 的入站连接
当流量从 WSL2 指向 Windows 的宿主机 IP 时,对 Windows 而言这是来自虚拟网段的入站连接,而不是本机进程连 127.0.0.1。因此,若 Clash 仅监听 127.0.0.1,部分客户端等价于「只接受本机环回」,WSL2 侧仍可能连接被拒绝。实务上需要在 Clash 或图形客户端里打开允许局域网连接(或配置里将监听地址设为 0.0.0.0),使混合端口在对应接口上真正可达。具体菜单名称因 Verge、CFW 等壳而异,但语义一致:不要只把代理锁在 loopback。
混合端口的概念与 Windows 终端那篇相同:在同一本地端口上同时承载 HTTP 代理与 SOCKS5,便于统一写 http://...。请始终以当前生效配置或界面展示的 mixed-port 为准,不要照抄文章里的示例数字。若你还希望手机通过同一台电脑上网,监听地址与防火墙策略又与本文略有重叠,可交叉阅读《局域网代理与防火墙》,但 WSL2 场景通常只需放行来自虚拟子网的入站到该端口即可。
第三步:为 shell 与 curl 配置 http_proxy / HTTPS_PROXY
在确认「宿主机 IP + 混合端口」从 WSL2 内可以 curl 通之后,再把代理写进环境变量。下面示例用变量 WIN_HOST 保存上一步得到的 IP,MIXED_PORT 替换为你的混合端口;行内以英文注释说明用途,便于复制到个人脚本时对照。
export WIN_HOST="$(grep -m1 '^nameserver' /etc/resolv.conf | awk '{print $2}')"
export MIXED_PORT=7890
export http_proxy="http://${WIN_HOST}:${MIXED_PORT}"
export https_proxy="http://${WIN_HOST}:${MIXED_PORT}"
export HTTP_PROXY="$http_proxy"
export HTTPS_PROXY="$https_proxy"
# optional: all tools that honor ALL_PROXY
export ALL_PROXY="$http_proxy"
将上述 export 写入 ~/.bashrc 或 ~/.profile 后,执行 source ~/.bashrc 或重新打开终端。随后用 curl -I https://www.google.com 之类命令观察是否仍超时。若此时 Clash 日志出现来自 WSL 对应进程、目标为代理端口的连接记录,说明环境变量链路已通。别忘了按需维护 NO_PROXY,把内网域名、公司 Git、国内镜像主机排除出去,否则会出现「代理开了反而访问变慢」的错觉。
第四步:让 apt 稳定走代理(环境变量与 apt.conf 两种方式)
许多版本的 APT 会继承 shell 的 http_proxy / https_proxy,但为减少「sudo 丢环境变量」一类问题,推荐额外在 apt 专用配置里声明代理。可在 /etc/apt/apt.conf.d/95proxy(文件名可自定)中写入类似内容,把占位符换成你的宿主机 IP 与端口:
Acquire::http::Proxy "http://172.x.x.1:7890/";
Acquire::https::Proxy "http://172.x.x.1:7890/";
使用 sudo apt update 时,若仅用户级 shell 变量生效而 root 环境未带入,容易出现「我 curl 能翻、apt 仍直连」的错位。把代理写进 apt.conf.d 后,apt 与 apt-get 在提权场景下行为更一致。若你更倾向镜像站而非代理,也可以改用国内镜像源;那是另一条成本权衡,本文假设你的目标是让官方源或指定 HTTPS 出口走 Clash。
sudo 与 systemd:别忽略「提权后变量消失」
常见踩坑之一是:普通用户 shell 里 echo $https_proxy 有值,一加 sudo 就变成空。原因是默认 sudo 会重置环境。解决办法包括:在 sudoers 中谨慎放行特定代理变量(需管理员维护)、或在调用 sudo 时显式传入 sudo HTTPS_PROXY=... apt ...、或如前所述让 apt 从配置文件读取代理。对于只在 WSL 里临时调试的场景,优先用 apt.conf.d,比到处放宽 sudo 安全策略更干净。
可选:镜像网络与 localhost 转发何时能简化配置
在较新的 Windows 与 WSL 组合上,若启用了文档所述的镜像网络等实验或正式特性,有时可以直接用 127.0.0.1 访问宿主机服务。但这类行为依赖版本与开关,在团队文档里若写死为唯一路径,同事换一台机器就可能全员踩雷。更推荐把「宿主机 IP + 允许局域网」当作基线方案,把镜像网络视为加速器:能用时更省事,不能用时也不推翻整体架构。
Windows 防火墙与第三方安全软件
即使 Clash 已监听 0.0.0.0:混合端口,Windows Defender 防火墙仍可能拦截来自 WSL 虚拟网卡的入站。若 curl 报超时或连接重置,可在「允许应用通过防火墙」中为 Clash 主程序勾选专用/公用网络,或为对应 TCP 端口添加入站规则。企业环境若装有终端安全代理,也可能改写本地路由或拦截本地端口互访;排错时同样建议先关掉其它全局代理类软件,只保留 Clash 一条链路做最小对照。
验证:用连接日志确认 apt 与 curl 真的进了 Clash
验证阶段不要只看「网页能打开」,而要在 Clash 侧观察连接记录:执行一次 sudo apt update 或 curl 目标站点时,应能看到来自 WSL 对应地址、经本地混合端口转发的会话。若日志里完全没有相关域名或进程,说明流量仍绕开了代理,应回头检查监听地址、防火墙与 IP 是否漂移。确认稳定后,再把临时 export 固化进 shell 配置,并把 apt 代理文件纳入你自己的点文件仓库,便于重装系统后快速恢复。
常见坑速查
- 127.0.0.1 误区:在 WSL2 内把代理指向本机环回,而不是 Windows 宿主机 IP。
- 未开允许局域网:Clash 只监听环回,WSL2 入站被拒绝。
- 端口抄错:把节点远端端口或订阅里的数字当成 mixed-port。
- sudo 丢变量:root 下 apt 不走用户 shell 的 http_proxy。
- HTTPS 仍走直连:只设置了
http_proxy未设置https_proxy。 - NO_PROXY 过宽或过窄:误把需要代理的域名排除,或把内网未排除导致绕远路。
合规提示
请在你所在地区法律法规及服务条款允许的范围内使用代理与访问目标站点。本文仅讨论 WSL2 与 Windows 之间的本地网络参数与排错思路,不构成对任何网络限制或平台政策的规避建议。
结语
WSL2 与 Windows 共享屏幕,却不默认共享「回环意义上的同一台本机」。把 Ubuntu 子系统 apt 走代理的关键,是先用 resolv.conf 或 ipconfig 找准宿主机 IP,再在 Clash 上为Windows 混合端口放开来自虚拟子网的监听,最后用环境变量与 apt 专用配置把 curl、apt 的出口对齐到同一条链路。掌握这套映射后,你在 PowerShell 与 WSL 之间切换时,就不再会被「一边能翻、一边直连」反复消耗耐心。
若你希望与教程使用同一套客户端能力(连接日志、端口展示、允许局域网开关),可从客户端下载页获取适合你系统的版本;更多 YAML 与规则细节见《YAML 配置解析》与博客索引。→ 立即免费下载 Clash,开启流畅上网新体验