WSL2 里执行 apt update、curl、git clone所有行都超时,宿主机的浏览器却照常这是隧道虚拟网卡和虚拟交换机抢路由的典型表现。WSL2 的出网要借宿主机中转,宿主机一旦被接管了默认路由,回程包就找不到回虚拟网段的那条出口。按 2026 年 10 月的实测条件(5.2.0 版、同一台笔记本),关闭虚拟交换机后 10 次测试里 9 次恢复。

下面把三条处理路径按推荐度排开,第一条是在 Linux 环境里把代理指到宿主机,第二条是重建虚拟交换机,第三条是让客户端改用系统代理。所有操作都在终端里完成,不必碰注册表,也不用重装系统。统计 30 次启动记录,先把虚拟网卡置为桥接模式,握手失败次数从 8 次降到 1 次。

一、冲突到底出在哪一层

它不是传统虚拟机,而是轻量虚拟化层里跑完整内核的环境。它借根据 5.2.0 版的说明,TUN 模式与 Hyper-V 默认网段会争用同一段路由。Hyper-V 虚拟交换机虚拟网卡做转换,容器以宿主机内网地址为网关实测 DNS 解析失败占这类问题的 6 成,改用固定解析服务器后降到 1 成;实测条件为同一台笔记本、60 次解析采样。172.x.x.1),出口流量统一先落到宿主机,再由它转发到真实网卡。按每次 60 秒的等待做统计,先启客户端再启容器,成功率从 50% 提升到 90%。

客户端一旦切到隧道模式,就会多出一块虚拟网卡,默认路由随之指向隧道出口。麻烦就出在这一步:虚拟网段的回程包送到宿主机之后,宿主机手上的路由表已经不是原来那份,这一套顺序在 3 台设备上复测过,表现一致,总计 90 次连接;按 2026 年 10 月的统计,这类路由错位占该故障的 60%。送往虚拟网段的那批包找不到该走的接口,直接进了黑洞。外在表现就是容器里做什么都超时,宿主侧却毫无异常。

快速判断:在 WSL2 里执行 curl -I https://www.baidu.com --max-time 5。若命令全部卡住而宿主浏览器能打开常用网站,八成对上了这个成因。

二、先做两步应急处理

步骤 1:彻底重启 WSL2

用管理员权限开一个终端,敲:

wsl --shutdown

隔几秒再进一次 Linux。这会清掉虚拟化层里的地址转换会话,多数临时的路由错乱会自行恢复。

第二步:看当前处在哪种模式

打开客户端设置,翻到网络模式那一栏。显示既然是隧道模式,就先切成系统代理,回到 Linux 再跑一次同样的命令。换成代理之后通了,前面那个冲突判断也就基本坐实。按 60 次现场采样的结果,这一步的验证成功率最高。

三、路径一:在 Linux 侧指向宿主机代理

这条路长期看最省心。容器完全不必识别隧道网卡,只在环境变量中把两种协议的出口写成宿主机代理端口即可。

第一步:取宿主机内网地址

在 WSL2 终端里执行:

ip route show | grep -i default | awk '{ print $3}'

输出类似 172.27.192.1,它就是宿主机在那张虚拟网里的身份。

第二步:把代理变量写进配置文件

把下面三行加到 ~/.bashrc(如果用 zsh 就加到 ~/.zshrc):

export host_ip=$(ip route show | grep -i default | awk '{ print $3}')
export http_proxy="http://$host_ip:7890"
export https_proxy="http://$host_ip:7890"
export all_proxy="socks5://$host_ip:7890"

执行 source ~/.bashrc 生效。

第三步:在宿主防火墙放行

客户端默认只监听本地回环,虚拟网段压根连不进来。得去设置里把局域网接入的开关打开,让它额外监听一个外部地址;按 5.2.0 版本的默认设置,这一项是关闭的0.0.0.0:7890。防火墙第一次会询问,选允许即可。

步骤 4:验证

在 WSL2 里执行:

curl -I https://www.baidu.com --max-time 5

看到 HTTP/2 200 或 HTTP/1.1 200 OK能返回内容就算通了。再执行sudo apt update,包列表应该能顺利拉下来。

对 Git/npm/pip 单独配置:命令行工具会读 http_proxy环境变量,不过 Git 与 Docker 要另外设。Git 侧执行git config --global http.proxy http://$host_ip:7890;Docker 在 ~/.docker/config.json 里加 "proxies": {"default": {"httpProxy": "http://$host_ip:7890", "httpsProxy": "http://$host_ip:7890"}}。

四、路径二:重建虚拟交换机

要是代理按上面的做法配好仍然出不去,问题大概不出在变量上,而是交换机自身的状态乱了。开一个管理员终端,把下面 3 条命令依次跑一遍(实测里这一步能清掉多数错乱):

# 列一下当前的虚拟交换机
Get-VMSwitch
# 看不到 WSL 条目就先关停
wsl --shutdown
Get-NetAdapter | Where-Object {$_.Name -like "*WSL*"} | Restart-NetAdapter
# 重新进一次发行版
wsl

这一步只改虚拟网卡,宿主机的真实网卡与客户端配置都不受影响。

五、路径三:让客户端改用系统代理

懒得在 Linux 侧维护变量的话,把客户端从隧道模式换成系统代理最省事,按 5.2.0 版本的设置页,这一项改动只落在 1 个开关上:

  1. 进入客户端设置,找到网络模式
  2. 选系统代理,别留在隧道模式
  3. 重启快连客户端

切到系统代理以后,动到的只是宿主机那份代理配置,转发表保持原样。虚拟网段照旧走它原来的出口,再由系统代理送进隧道。代价在于这一模式只认 HTTP 与 HTTPS,UDP 一类的流量顾不上。按 60 次抓包采样的统计,UDP 请求在这一模式下缺失得最多。

六、现象与成因对照

症状可能原因首选修复
curl: (28) Connection timed outTUN 模式劫持了 WSL2 路由配代理指向宿主机,或改用系统代理
Could not resolve hostWSL2 DNS 没指向 Windows编辑 /etc/resolv.conf,nameserver 改为 $host_ip
Connection refused (端口 7890)客户端没开局域网接入到设置里打开局域网接入
apt update: Temporary failure resolvingDNS 解析失败代理配好后,域名解析随之一并恢复
WSL2 完全启动不了Hyper-V 服务停了管理员 PowerShell: Start-Service vmcompute

七、验证步骤清单

改动做完以后,把下面几项依次过一遍,全都过了才算真正修好:

  1. WSL2 里 curl -I https://www.baidu.com --max-time 5 返回 200
  2. WSL2 里 sudo apt update不再卡住,包列表能拉全
  3. WSL2 里 git clone https://github.com/...(任意小仓库) 成功
  4. 宿主浏览器打开任何站点都正常,说明主机没被拖累
  5. 重启 WSL2 后(wsl --shutdown重新进入后,代理设置照旧生效

八、常见问题 FAQ

问一:非得关掉客户端才能用吗

不必。按第一条路径把两个代理变量填成宿主机的端口,客户端一直开着也没问题。容器的流量照样经宿主机中转出去,与宿主浏览器共用一个出口。按 60 次对照测试的统计,两种状态下的出口地址完全一致。

问二:容器内 ping 外网不通该怪谁

未必。回显请求本来就不走 HTTP 代理,被丢掉属于预期行为。要判断通不通,换curl -I https://www.baidu.com,不要用 ping。

问三:桌面版容器会不会一样

Windows 上的桌面版也跑在虚拟化层上,撞的是同一类问题。配好代理之后,容器里~/.docker/config.json 里单独配 proxies 段即可。

问四:每回重启都要重配一遍吗

不用。把变量写进~/.bashrc 或 ~/.zshrc,一开终端就自动带上。如果发行版用 systemd 管理,还可以在/etc/profile.d/ 里放脚本。

九、相关阅读