记录一次 Windows + WSL2 网络异常:WSL 无法访问局域网节点的排查与修复
一、问题背景
我的服务部署结构大致是:
Windows 主机 ├─ WSL2:运行管理平台 / 调度服务 / worker / 数据库 ├─ Windows 本机:运行一个计算节点,端口 NODE_PORT ├─ 局域网其他机器:也运行计算节点,端口 NODE_PORT └─ WEB_PORT:管理平台端口,通过 Windows portproxy 暴露出去正常情况下,WSL2 里的主服务需要访问:
Windows 本机节点:HOST_LAN_IP:NODE_PORT 局域网其他节点:PEER_LAN_IP:NODE_PORT之前这些访问都是正常的。
二、问题现象
某次 Windows 重启以及执行过网络相关命令后,出现了异常。
Windows 本机访问局域网节点正常:
ping PEER_LAN_IP curl.exe -v http://PEER_LAN_IP:NODE_PORT/但 WSL2 访问同一个节点超时:
wsl -d YOUR_DISTRO -- bash -lc "curl --noproxy '*' -v --connect-timeout 5 http://PEER_LAN_IP:NODE_PORT/"表现为:
Windows -> PEER_LAN_IP:NODE_PORT 正常 WSL2 -> PEER_LAN_IP:NODE_PORT 超时同时,WSL2 访问 Windows 本机节点时,使用HOST_LAN_IP:NODE_PORT也不稳定。
三、关键排查
1. 查看 WSL2 当前 IP 和路由
wsl -d YOUR_DISTRO -- bash -lc "hostname -I" wsl -d YOUR_DISTRO -- bash -lc "ip route"NAT 模式下,通常会看到类似:
WSL_IP default via WSL_GATEWAY dev eth0 WSL_SUBNET dev eth0 scope link src WSL_IP例如:
WSL_IP = 172.20.10.5 WSL_GATEWAY = 172.20.0.1 WSL_SUBNET = 172.20.0.0/20这时,WSL2 访问 Windows 宿主机服务,应该优先使用:
http://WSL_GATEWAY:NODE_PORT而不是:
http://HOST_LAN_IP:NODE_PORT2. 验证 WSL2 到 Windows 本机节点
wsl -d YOUR_DISTRO -- bash -lc "curl --noproxy '*' -v --connect-timeout 5 http://WSL_GATEWAY:NODE_PORT/"如果返回404或其他应用层响应,说明网络已经通了,只是访问的路径不是有效接口。
3. 检查 Windows 到 WSL2 的端口转发
如果要让局域网或外部访问 WSL2 里的管理平台,需要 Windows 端做 portproxy:
netsh interface portproxy show all重建转发示例:
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=WEB_PORT netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=WEB_PORT connectaddress=WSL_IP connectport=WEB_PORT放行防火墙:
New-NetFirewallRule -DisplayName "MyApp-WEB_PORT" -Direction Inbound -Protocol TCP -LocalPort WEB_PORT -Action Allow四、中间踩过的坑
1. WSL2 mirrored 模式
曾尝试过配置:
[wsl2] networkingMode=mirrored dnsTunneling=true autoProxy=true firewall=truemirrored 模式会让 WSL2 更接近 Windows 主机网络,有时可以改善局域网访问问题。
但它也会改变 WSL2 访问宿主机服务的行为,并可能引入代理变量,例如:
HTTP_PROXY=http://127.0.0.1:PROXY_PORT如果服务端或 worker 继承了这些代理变量,内部请求可能被代理污染。
最终为了恢复原有稳定状态,我删除了.wslconfig,让 WSL2 回到默认 NAT 模式:
Remove-Item "$env:USERPROFILE\.wslconfig" -Force wsl --shutdown2. TUN / 虚拟网卡模式
Clash / Mihomo / Verge 这类工具开启 TUN 模式后,会接管系统路由、DNS 或默认出口。
这可能影响:
客户端 -> 域名:WEB_PORT -> Windows -> portproxy -> WSL2 WSL2 -> Windows -> 局域网其他节点所以,如果 Windows 主机本身是客户访问入口,不建议在这台机器上开启全局 TUN。
如果必须开启,需要给管理平台域名、内网网段、WSL 网段配置直连规则。
五、真正原因
最终定位到的核心原因是:
WSL2 出站 SNAT / Masquerade 状态丢失正常情况下,WSL2 访问局域网其他节点时,目标节点看到的来源 IP 应该是:
HOST_LAN_IP也就是 Windows 宿主机的局域网 IP。
异常时,目标节点看到的来源 IP 变成了:
WSL_IP也就是 WSL2 自己的 NAT 网段 IP。
这会导致目标节点无法正确回包,因为它通常不知道如何返回到:
WSL_SUBNET最终表现就是 WSL2 访问局域网节点超时。
六、解决方法
方案一:在目标节点加回程路由
在局域网目标节点上添加回程路由:
route -p add WSL_SUBNET mask WSL_SUBNET_MASK HOST_LAN_IP示例:
route -p add 172.20.0.0 mask 255.255.240.0 10.10.10.5含义是:
如果要回到 WSL2 网段,就走 Windows 宿主机 IP。这个方法适合目标节点数量较少的情况。
方案二:在 Windows 主机恢复 WSL2 SNAT
更接近原始状态的修复方式,是在 Windows 主机上恢复 WSL2 出站 SNAT:
New-NetNat -Name "WSL-SNAT" -InternalIPInterfaceAddressPrefix "WSL_SUBNET_CIDR"示例:
New-NetNat -Name "WSL-SNAT" -InternalIPInterfaceAddressPrefix "172.20.0.0/20"查看:
Get-NetNat如果同名规则已经存在,需要先删除:
Remove-NetNat -Name "WSL-SNAT" -Confirm:$false然后再重新创建。
恢复后,WSL2 访问局域网节点时,对方看到的来源 IP 会重新变成 Windows 宿主机 IP:
HOST_LAN_IP这就是之前的正常状态。
七、最终稳定结构
最终稳定后的访问关系如下:
客户端/局域网 -> Windows:WEB_PORT -> portproxy -> WSL2:WEB_PORT WSL2 -> Windows 本机节点 -> WSL_GATEWAY:NODE_PORT WSL2 -> 局域网其他节点 -> PEER_LAN_IP:NODE_PORT -> 通过 Windows SNAT,对外表现为 HOST_LAN_IP八、建议保留的运维命令
查看 WSL 状态
wsl -d YOUR_DISTRO -- bash -lc "hostname -I; ip route"查看 SNAT
Get-NetNat查看 portproxy
netsh interface portproxy show all重建 WEB_PORT 转发
netsh interface portproxy delete v4tov4 listenaddress=0.0.0.0 listenport=WEB_PORT netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=WEB_PORT connectaddress=WSL_IP connectport=WEB_PORT恢复 WSL2 SNAT
New-NetNat -Name "WSL-SNAT" -InternalIPInterfaceAddressPrefix "WSL_SUBNET_CIDR"九、总结
这次问题不是应用服务损坏,而是 Windows、WSL2、WinNAT、portproxy、TUN 之间的网络状态被打乱。
核心原因是:
WSL2 出站 SNAT/Masquerade 状态丢失导致 WSL2 访问局域网节点时,来源 IP 从:
HOST_LAN_IP变成了:
WSL_IP目标节点无法回包,所以连接超时。
最终通过恢复 Windows 上的 WSL2 SNAT:
New-NetNat -Name "WSL-SNAT" -InternalIPInterfaceAddressPrefix "WSL_SUBNET_CIDR"成功恢复到之前的网络状态。
