WSL2 镜像模式下本机无法通过本机 IP 访问服务 —— 排查与解决全记录
环境:Windows 11 Dev Channel (Build 26200) · WSL 2.7.10 · 镜像网络模式
现象
WSL2 中启动了一个 HTTP 服务(例如 python3 -m http.server 8000 --bind 0.0.0.0),然后:
| 访问方式 | 结果 |
|---|---|
http://localhost:8000/(本机浏览器) |
✅ 正常 |
http://192.168.0.118:8000/(其他电脑) |
✅ 正常 |
http://192.168.0.118:8000/(本机) |
❌ 无法访问 |
服务地址 192.168.0.118 是本机 Wi-Fi 网卡的 IP。在镜像模式下,WSL 共享这个 IP,服务在 WSL 中绑定了 0.0.0.0:8000,外部可访问,自己反而访问不了。
环境确认
# WSL 版本
wsl --version
# → WSL 版本: 2.7.10.0
# → 内核版本: 6.18.33.2-2
# → Windows: 10.0.26200.8655
# .wslconfig 配置
# 文件位置: %UserProfile%\.wslconfig
[wsl2]
networkingMode=mirrored
hostAddressLoopback=true
dnsTunneling=true
autoProxy=true
memory=24GB
swap=12GB
排查过程
第一步:确认服务是否正常
在 WSL 内测试:
curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8000/
# → 404(正常返回,服务运行中)
第二步:从 Windows 侧测试连通性
# localhost 测试 - ✅ 正常
Invoke-WebRequest http://127.0.0.1:8000/
# → 404
# 本机 IP 测试 - ❌ 失败
Invoke-WebRequest http://192.168.0.118:8000/
# → WebException: 操作超时
第三步:检查网络拓扑
# Windows 网卡列表
Get-NetAdapter | Select-Object Name, Status, LinkSpeed
# Windows IP 地址
Get-NetIPAddress -InterfaceAlias "WLAN"
# → 192.168.0.118/24
# WSL 内网络
ip addr show eth3
# → 192.168.0.118/24 ← 镜像模式下与 Windows 共享同一 IP
# 路由表
Get-NetRoute -DestinationPrefix "192.168.0.0/24"
# → ifIndex 10 (WLAN), 默认网关 192.168.0.1
结论:镜像模式正常工作,Windows 和 WSL 共享 192.168.0.118。
第四步:尝试 netsh portproxy
# 添加转发规则(管理员终端)
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8000 connectaddress=127.0.0.1 connectport=8000
# 验证规则
netsh interface portproxy show all
# → 0.0.0.0:8000 → 127.0.0.1:8000
结果:无效。继续超时。
第五步:深入排查 portproxy 是否正常
怀疑 portproxy 本身可能失效,用两个测试验证:
测试 A:纯 Windows 环境测试
用 PowerShell 在 Windows 侧启动一个 TCP 监听(127.0.0.1:18888),添加 portproxy 规则 0.0.0.0:18888 → 127.0.0.1:18888,从本机测试 192.168.0.118:18888。
结果:❌ 仍然失败 → 说明 portproxy 在此 Windows 版本上整体不可用。
测试 B:绑定冲突测试
# 镜像模式下测试能否绑定 192.168.0.118:8000
$s = [System.Net.Sockets.Socket]::new([System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp)
$s.Bind([System.Net.IPEndPoint]::new([System.Net.IPAddress]::Parse("192.168.0.118"), 8000))
# → BIND_FAIL: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次
镜像模式下,WSL 的 0.0.0.0:8000 占用了共享网络栈上的 所有接口 的 8000 端口,Windows 无法再绑定同一个端口。
第六步:查证社区
上网搜索发现这是 WSL2 镜像模式的已知问题:
| GitHub Issue | 描述 |
|---|---|
| #11600 | 镜像模式下宿主机和 WSL 无法双向访问 |
| #40343 | TCP 环回 SYN-ACK 端口错乱 Bug |
| #13868 | 镜像模式下 loopback 接口不可达 |
根因分析
镜像模式下网络架构
┌─────────────────────────────────────────────────────┐
│ Windows 主机 │
│ │
│ Wi-Fi: 192.168.0.118/24 │
│ ┌─────────────────────────────────────┐ │
│ │ WSL 镜像网络命名空间 │ │
│ │ │ │
│ │ eth3: 192.168.0.118/24 (共享) │ │
│ │ 服务: 0.0.0.0:8000 │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
镜像模式下 WSL 和 Windows 共享同一个网络命名空间。服务在 WSL 内绑定 0.0.0.0:8000,相当于在整个共享栈上占用了 8000 端口。
为什么本机访问不了?
当本机请求 192.168.0.118:8000 时,Windows TCP/IP 栈检测到目标 IP 是自己的 IP,走内部环回路径。但这个环回路径并没有到达 WSL 里的服务,而是寻找 Windows 本身上有没有监听 8000 的进程——没有,于是连接失败。
本机 → 192.168.0.118:8000
↓
Windows 内核: "发给自己"
↓
走 loopback 本地投递(绕过了物理网卡和镜像转发路径)
↓
Windows 自身无 8000 监听 ❌
而从其他电脑访问时:
其他电脑 → 192.168.0.118:8000
↓
物理网卡进入
↓
镜像转发到 WSL 命名空间
↓
WSL 服务响应 ✅
而 localhost:8000 能工作是因为 hostAddressLoopback=true 在 Windows 环回接口上做了显式转发。
为什么 portproxy 无效?
netsh portproxy 在 Windows TCP/IP 栈的"将发往自身 IP 的包短路到环回"这个决策点之前拦截流量。但在镜像模式下:
-
0.0.0.0:8000已经被 WSL 在共享栈上占用 - portproxy 无法绑定到同一个地址端口
- 即使配置了规则也无法生效
此外,在 Windows Dev Channel Build 26200 上,portproxy 在纯 Windows 场景下也失效,可能是系统版本的 Bug。
解决方案
最终方案:切回 NAT 模式 + portproxy(确定有效)
既然镜像模式有环回访问的死结,而 portproxy 又在这个 Windows 版本上不可用,最可靠的方案是切回 WSL2 默认的 NAT 模式,然后手动配置端口转发。
步骤 1:修改 .wslconfig
# 文件位置: %UserProfile%\.wslconfig
[wsl2]
# networkingMode=mirrored ← 注释掉,回到默认 NAT 模式
hostAddressLoopback=true
memory=24GB
swap=12GB
步骤 2:重启 WSL
wsl --shutdown
重新打开 WSL 终端。
步骤 3:获取 WSL IP
hostname -I
# → 172.29.212.65
步骤 4:添加端口转发(管理员终端)
netsh interface portproxy add v4tov4 `
listenaddress=0.0.0.0 `
listenport=8000 `
connectaddress=172.29.212.65 `
connectport=8000
步骤 5:验证
Invoke-WebRequest http://192.168.0.118:8000/
# → 404(成功到达 WSL 服务)
NAT 模式下网络架构:
┌────────────────────────────────────┐
│ Windows 主机 │
│ │
│ Wi-Fi: 192.168.0.118/24 │
│ Portproxy: 0.0.0.0:8000 ───┐ │
│ │ │
│ vEthernet (默认交换机) │ │
│ 172.26.192.1/20 │ │
│ │ │ │
└───────┼──────────────────────┘ │
│ NAT │
┌─────┴────────────────────┐ │
│ WSL 命名空间 │ │
│ │ │
│ eth0: 172.29.212.65/20 │ │
│ 服务: 0.0.0.0:8000 ◄────┘────────┘
└──────────────────────────┘
自动化脚本
每次都手动敲命令太麻烦,写了一个批处理脚本 wsl-port.bat:
:: 用法(管理员终端)
wsl-port 8000 # 添加端口转发
wsl-port 8000 /d # 删除端口转发
脚本会自动获取 WSL IP、添加/删除 portproxy 规则。
其他的尝试(不成功但值得记录)
| 尝试 | 结果 |
|---|---|
使用 hostAddressLoopback=true
|
只对 localhost 有效 |
netsh portproxy(镜像模式) |
portproxy 在此 Windows 版本上整体失效 |
Set-NetFirewallHyperVVMSetting |
本机无此命令 |
firewall=false(.wslconfig) |
无效 |
| 添加特定 IP 路由 | 需要路由器支持 hairpin NAT |
iptables DNAT(WSL 内) |
流量未进入 WSL 命名空间就短路了 |
| 安装 Npcap / 开启 WiFi 热点 | 社区报告有效,但非正规方案 |
总结
| 要点 | 内容 |
|---|---|
| 问题性质 | WSL2 镜像模式的已知内核级 Bug,非操作失误 |
| 根因 | 本机访问自身 IP 时,Windows TCP/IP 栈将流量短路到环回,不经过 WSL 命名空间 |
| 最佳方案 | 切回 NAT 模式 + 手动 portproxy |
| 长期建议 | 等微软修复镜像模式的环回问题后再切回去 |
| 参考链接 | Issue #11600 · Issue #40343 |
记录于 2026-07-09