典型现象:Windows 能翻墙,WSL2 里 apt 与 git 却像「没代理」

Clash 在 Windows 上工作正常时,浏览器往往已经走了系统代理或 TUN。但 WSL2 运行在轻量级虚拟机与虚拟网卡背后,默认并不共享你对「本机环回地址」的直觉。在子系统的 shell 里写 export https_proxy=http://127.0.0.1:7890,请求会打到 WSL 自己的环回接口,而不是 Windows 上正在监听的那个端口,于是表现为超时、连接被拒绝,或仍然按直连去访问被墙资源。

另一方面,aptgit 并不总是尊重你在交互式 shell 里临时 export 的变量:sudo 会清掉部分环境;apt 还有独立的 Acquire::http::Proxy 系列配置;git 则常用 http.proxy / https.proxy。只有把宿主地址、Clash 监听范围、变量名与持久化位置对齐,才能稳定复现「同一份 Clash,Windows 与 WSL2 共用」的体验。

先建立心智模型:127.0.0.1 在 WSL2 里指向谁

在经典 WSL2 NAT 网络模型下,子系统有独立的网络栈。127.0.0.1 指向的是 Linux 发行版自身,而不是 Windows 宿主。要让流量进入 Windows 上的 Clash,必须让 TCP 连接的目标地址变成「从 WSL 能路由到的、Windows 一侧的 IP」,通常是默认网关或微软文档中描述的宿主机地址。社区里最常用的做法之一,是读取 /etc/resolv.conf 里的 nameserver 字段——在不少构建中它与通往宿主的地址一致(请以你当前 WSL 版本为准,升级后若行为变化应重新核对)。

你也可以用 ip route show default 查看默认路由的下一跳,把该地址当作 WIN_HOST 使用。下文示例统一写作 <WIN_HOST>,请替换为你机器上实测的值。取得地址后,用 curl -v --proxy http://<WIN_HOST>:端口 https://www.example.com 做一次探活,比盲目改配置更快定位问题。

与「Linux 无头部署」的区别 本站Linux 无头部署文讲的是代理进程直接跑在 Linux 里;本文则是代理在 Windows、消费端在 WSL2,端口与监听地址的约束完全不同。

Windows 侧 Clash:混合端口、允许局域网与绑定地址

即使 WSL2 已经能 ping 通宿主 IP,若 Clash 只在 127.0.0.1 上监听、且未开启「允许局域网」(Allow LAN),来自 WSL 网段的入站连接仍会被拒绝。请在图形客户端或配置中确认:HTTP(S) 或 mixed 端口对局域网开放,且防火墙规则未拦截该端口(首次开启时 Windows 防火墙可能弹出提示,需要允许专用网络访问)。

混合端口(mixed-port)同时承载 HTTP CONNECT 与 SOCKS,适合作为 ALL_PROXY 的统一入口。若你分别暴露 HTTP 与 SOCKS,请在环境变量里对应填写 http://...socks5://...,避免协议与端口错配。Clash 规则本身仍只在 Windows 内核或 WinTun 路径上生效;WSL2 通过 HTTP 或 SOCKS 把流量主动送给宿主上的 Clash 后,再由 Clash 按规则出网,这与「在 Linux 里直连 TUN」是两条链路。

若你使用 TUN 模式接管 Windows 全局流量,仍可为 WSL2 单独保留上述「显式代理端口」方案;TUN 不会自动让 WSL2 里的未配置进程 magically 走代理。更系统的模式对比见TUN 专文

Shell 环境变量:http_proxy、HTTPS_PROXY、ALL_PROXY 与 no_proxy

大多数命令行工具会识别小写与大写两套变量,为减少歧义,建议成对写入 http_proxy / HTTP_PROXYhttps_proxy / HTTPS_PROXY。若工具走 SOCKS,可设置 ALL_PROXY=socks5://<WIN_HOST>:端口,并同样提供大写形式。对于仅需 HTTP CONNECT 的场景,只设 http_proxy 指向混合端口通常也可工作,具体取决于工具实现。

no_proxy(或 NO_PROXY)应列出无需走代理的主机与域,例如 localhost,127.0.0.1,::1,以及公司内网后缀。否则访问本地构建的 registry、Kubernetes API 或私有 Git 时,请求会被错误转发到 Clash。与 Node、pnpm 等开发工具链协同设置时,可参考《Cursor 与 npm 开发者代理》中的 NO_PROXY 思路,在 WSL 侧同样适用。

将 export 写入 ~/.bashrc~/.zshrc 可实现登录自动生效。注意:sudo apt 默认会重置环境,下一节单独处理。

# Replace <WIN_HOST> and <PORT> with your values (example: 7890)
export HTTP_PROXY="http://<WIN_HOST>:<PORT>"
export http_proxy="$HTTP_PROXY"
export HTTPS_PROXY="$HTTP_PROXY"
export https_proxy="$HTTP_PROXY"
export ALL_PROXY="socks5://<WIN_HOST>:<PORT>"
export all_proxy="$ALL_PROXY"
export NO_PROXY="localhost,127.0.0.1,::1"
export no_proxy="$NO_PROXY"

apt:sudo 场景与 Acquire::http::Proxy

Debian 系发行版中,apt 优先读取 /etc/apt/apt.conf/etc/apt/apt.conf.d/ 下的指令。仅对当前用户 export 变量,在执行 sudo apt update 时常常传不进去。稳妥做法是在 /etc/apt/apt.conf.d/ 中 drop 一份仅包含代理的小文件,例如 95proxy,内容指向 http://<WIN_HOST>:<PORT>。使用 HTTP 代理访问 HTTPS 软件源是常见模式,apt 会通过 CONNECT 建立隧道。

若你同时使用国内镜像与海外源,可在规则层用 Clash 分流;apt 侧仍建议保持单一代理出口,由 Clash 决定直连或走节点,避免在 apt 配置里硬编码多套代理。编辑完配置后执行 sudo apt update 观察是否还有 「Could not resolve」 或 「Connection timed out」;DNS 若仍走不理想的路径,可结合 Clash 的 DNS 与 fake-ip 设置统筹,详见《DNS fake-ip 与 redir-host》中与解析相关的讨论。

# File: /etc/apt/apt.conf.d/95proxy (example)
Acquire::http::Proxy "http://<WIN_HOST>:<PORT>/";
Acquire::https::Proxy "http://<WIN_HOST>:<PORT>/";

不需要代理时,删除该文件或注释其中行即可恢复直连,避免长期把 apt 绑在已关闭的 Clash 端口上。

git:http.proxy、https.proxy 与 SSH 的界限

https://http:// 远程仓库,git 通常遵循 http.proxyhttps.proxy。推荐用 git config --global 写入,地址仍填 http://<WIN_HOST>:<PORT>。若仅克隆公开仓库,HTTP 代理足够;若遇到大仓库低速,多半是出口节点或单一连接带宽问题,而非 git 配置语法本身。

[email protected]:... 这类 SSH 协议不会自动消费 http_proxy,除非通过 nc 等工具配置 ProxyCommand 或在 SSH config 中指向专用跳板。许多用户误以为设置了 ALL_PROXY 后 SSH 一定走代理,实际上要区分协议栈。若你希望统一走 Clash 提供的 SOCKS,可在高级场景中让 SSH 经过 ProxyCommand 连接 <WIN_HOST> 上的 SOCKS 端口,具体命令因客户端而异,此处不展开,以免与入门清单混淆。

# Git reads http(s) proxy for HTTPS remotes
git config --global http.proxy  http://<WIN_HOST>:<PORT>
git config --global https.proxy http://<WIN_HOST>:<PORT>

镜像网络(mirrored):让 localhost 与 Windows 端口对齐

从较新的 WSL 版本开始,微软提供镜像网络(mirrored / networkingMode=mirrored)选项:在用户目录下的 .wslconfig 中为指定发行版启用后,环回与部分本机端口的语义更接近「与 Windows 共享视图」,从而在不少场景下可以直接用 127.0.0.1:端口 访问 Windows 上监听的 Clash 混合端口,而不必每次解析 <WIN_HOST>。是否启用取决于你的 Windows 与 WSL 版本、以及团队对内网隔离的要求;启用后若出现与 VPN、其他虚拟网卡冲突,应回退到显式宿主 IP 方案并阅读发行说明。

典型 .wslconfig 片段如下(字段名与可用值请以微软当前文档为准,升级 Windows 后宜复查):

# %UserProfile%\.wslconfig (snippet, verify against Microsoft docs)
[wsl2]
networkingMode=mirrored

修改后通常需要执行 wsl --shutdown 再启动子系统。镜像模式与经典 NAT 并存于不同用户配置中,不要假设每台机器行为一致;写成团队文档时,建议同时记录「宿主 IP + 允许局域网」与「镜像 + localhost」两套路径,便于新人按环境选用。

安全提示 开放局域网入站、或在镜像模式下放宽本机边界,都会扩大暴露面。仅在受信任网络启用,并在不使用时关闭 Clash 的 Allow LAN 或收紧防火墙。

验证与快速自检顺序

建议按下列顺序排查,每一步通过后再进入下一步:第一,在 WSL 内 ping 或 curl 宿主机 IP(仅测连通,不代表代理可用);第二,对混合端口做 curl -I --proxy http://<WIN_HOST>:端口 https://example.com;第三,在未 sudo 的 shell 中验证变量是否生效;第四,单独跑 sudo -E apt update(若你坚持用环境变量方式)或改 apt drop-in;第五,git ls-remote https://github.com/... 验证 HTTPS 克隆链路。

若第二步失败而第一步成功,优先回头检查 Clash 是否监听 0.0.0.0 或等价允许远程、以及 Windows Defender 防火墙入站规则。若只有浏览器可用而 curl 不可用,常见原因是浏览器走了系统代理,而终端未 export 变量——这与「WSL2 与 Windows 环回」问题不同,需分开判断。

常见问题对照表

现象 可能原因 建议
127.0.0.1:7890 Connection refused 代理在 Windows 上,WSL2 的 127 不是宿主 改用 <WIN_HOST>;或启用镜像网络后用 localhost
普通用户 curl 可走代理,sudo apt 不行 sudo 丢弃代理环境 使用 apt.conf.d 或 sudo -E 并保留配置
git HTTPS 仍直连失败 未设置 http.proxy / https.proxy git config --global 指向宿主代理
间歇性宿主 IP 变化 路由或 resolv 行为更新 脚本化探测默认网关;或依赖镜像网络固定 localhost
开启 Allow LAN 后仍拒绝 防火墙或监听地址过窄 检查入站规则与 Clash 绑定地址

写在最后:把「宿主 Clash」当成 WSL2 的显式上游

把 Windows 上的 Clash 当作 WSL2 的 HTTP/SOCKS 上游,而不是期待子系统自动继承浏览器代理,是排错时最重要的一步。通过正确的 <WIN_HOST>、允许局域网与(可选的)镜像网络,你可以让 aptgit 与日常脚本共用同一出口,再交给 Clash 做规则分流与 DNS 策略,整体体验会比在 WSL 内再跑一份内核更省维护成本。相比其他同类工具,Clash 在规则可读性、日志与多协议支持上的组合,对需要同时照顾浏览器、终端与子系统的桌面用户往往更顺手。

若你希望少在端口与防火墙细节上反复试错,可以优先选择带图形界面、能一键开关 Allow LAN 与查看 mixed 端口的客户端,把精力放在节点质量与规则命中验证上;全平台安装包可从本站下载中心获取。

立即免费下载 Clash,开启流畅上网新体验;在 Windows 上配好混合端口与局域网访问后,按本文清单对齐 WSL2 的 http_proxyALL_PROXY 与 apt/git,子系统里的更新与克隆也能稳定走同一套规则。

需要深入 YAML 分流与策略组设计时,请继续阅读《Clash YAML 规则分流完全指南》;更多文章见技术专栏