WSL2 跑起 Web 服务后,本机和局域网设备怎么都能访问?一套两步法彻底搞懂
适用场景:在 WSL2(Debian / Ubuntu 等)里跑 FastAPI、Vue、Vite、Rust(Axum/Actix) 等 Web 服务,想从 Windows 本机浏览器访问,还想让同局域网下的另一台设备(NAS、手机、同事电脑)也能访问。
环境前提:Windows 11(建议 24H2 / Build 26100+),已开启 WSL2 镜像网络模式(
.wslconfig里networkingMode=mirrored)。如果你还在用默认 NAT 模式,本文结论不完全适用,建议先切到镜像模式。
本文讨论的就是在 WSL2 里用下面这条命令启动的 Web 服务(以 FastAPI 为例,结论适用于任何绑定端口的 Web 服务):
bash
uv run uvicorn main:app --host 0.0.0.0 --port 8000
开头先说痛点
很多同学(包括我)在 WSL2 里 uv run uvicorn 起一个服务,本机浏览器死活打不开;好不容易本机通了,同局域网的另一台电脑 / 手机 wget 又连不上。
网上搜到的答案清一色是 netsh interface portproxy 端口转发------那是 NAT 模式 的老黄历。如果你已经用了镜像网络模式(mirrored),这条路不仅多余,还会把你带进坑里。
本文用一站到底的两步法,把"本机访问"和"局域网访问"彻底分开讲清楚。两者管的是不同的层,互不替代。
一、先确认你的网络模式:镜像 vs NAT
打开 Windows 的 .wslconfig(路径 C:\Users\你的用户名\.wslconfig),看有没有这一行:
ini
[wsl2]
networkingMode=mirrored
| NAT 模式(WSL2 默认旧模式) | 镜像模式(本文前提) | |
|---|---|---|
| 网络栈 | WSL 有独立 IP(如 172.25.x.x) | 与 Windows 共用一套网络栈 |
127.0.0.1 含义 |
仅指 WSL 自己 | Windows 和 WSL 是同一个回环 |
| 本机访问 WSL 服务 | 需要查 WSL IP + 端口转发 | 直接 127.0.0.1 访问 |
| 局域网设备访问 | 需要 netsh interface portproxy |
共用 Windows 网卡,无需转发 |
确认命令:
bash
wslinfo --networking-mode # 输出 mirrored 即镜像模式
还在 NAT 模式、且想消除"检测到 localhost 代理未镜像"告警的同学,把上面那行加进
.wslconfig再wsl --shutdown即可切到镜像模式。
二、第 1 步:本机 Windows 浏览器访问 WSL 服务
默认就能用 127.0.0.1
镜像模式下,WSL 和 Windows 共用回环地址。只要你的服务绑在 127.0.0.1 或 0.0.0.0,Windows 本机打开:
bash
http://127.0.0.1:8000/health
# 或
http://localhost:8000/health
就能直接访问,不需要任何额外配置。
服务必须绑
127.0.0.1或0.0.0.0,不能只绑 WSL 自己的具体 IP(镜像模式下一般也不会有人这么干)。
想用本机局域网 IP 访问?开 hostAddressLoopback
有时候本机也想用 http://192.168.1.208:8000 这种"局域网 IP"去访问(比如某些前端项目写死了主机 IP、或你想和真机环境保持一致)。
默认情况下镜像模式只允许本机走 127.0.0.1 回环 ,用本机 LAN IP 会被回环隔离挡住。解锁方法是在 .wslconfig 的 [experimental] 段加一项:
ini
[experimental]
hostAddressLoopback=true
官方说明(WSL .wslconfig 配置文档):该项仅当 networkingMode=mirrored 时生效,设为 True 后允许主机通过分配给它的本地 IP 地址访问 WSL 容器(默认始终可用的是 127.0.0.1)。
⚠️ 改完必须重启 WSL 才生效:
powershell
wsl --shutdown
# 重新打开 WSL,启动你的服务
重启后本机浏览器直接开 http://192.168.1.208:8000/health 就能通(已实测)。
小提醒:如果只是为了本机自己访问,用
127.0.0.1就够了,完全不用动这个配置。hostAddressLoopback是"额外解锁本机用 LAN IP 访问"的开关。
三、第 2 步:让局域网其他设备也能访问
假设你同局域网还有一台 机器(192.168.1.193),想 wget http://192.168.1.208:8000/health,却连不上。
为什么普通防火墙规则不生效(核心坑)
镜像模式下 WSL 监听 0.0.0.0:8000,等价于 Windows 所有网卡(含 192.168.1.208)都在监听------所以不需要 netsh interface portproxy 转发,这一步直接省掉。
但 Windows Defender 防火墙(镜像模式默认启用的是 Hyper-V 防火墙层)对入站默认是拦的。局域网其他机器 发来的包打到 Windows 网卡后,被这一层防火墙挡掉,到不了 WSL。
正确做法:放行 Hyper-V 防火墙层(需管理员)
以管理员身份 打开 PowerShell,执行下面任一命令(来自微软官方 WSL 网络文档):
方案 A:开放 WSL 虚拟机全部入站(家用开发一劳永逸,实测 局域网其他机器 已通)
powershell
Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow
方案 B:更收敛,只放行 8000 一个端口(推荐)
powershell
New-NetFirewallHyperVRule -Name "WSL FastAPI 8000" -DisplayName "WSL FastAPI 8000" `
-Direction Inbound -VMCreatorId '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' `
-Protocol TCP -LocalPorts 8000
- 那串 GUID 是 WSL 的 Hyper-V VM 创建者 ID,所有 WSL 发行版共用,照抄即可。
- 方案 A 重启持久生效;方案 B 是持久规则。
- 收回方案 A:
Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Block - 删除方案 B:
Remove-NetFirewallHyperVRule -Name "WSL FastAPI 8000"
验证请在局域网其他机器上跑:
bash
wget -qO- http://192.168.1.208:8000/health
返回 {"status":"ok"} 即通。
四、两步法速查表
| 访问方 | 配置层 | 怎么配 | 可用地址 |
|---|---|---|---|
| 本机 Windows 浏览器 / 程序 | .wslconfig 的 [experimental] hostAddressLoopback=true(改完 wsl --shutdown) |
文本加一项 | 192.168.1.208:8000 或 127.0.0.1:8000 |
| 本机(没开 hostAddressLoopback) | 无需配置 | --- | 仅 127.0.0.1:8000 |
| 同局域网其他机器 / 手机 / | Hyper-V 防火墙层(管理员 PowerShell) | Set-NetFirewallHyperVVMSetting ... Allow |
192.168.1.208:8000 |
一句话:第 1 步管本机能不能用 LAN IP,第 2 步管局域网其他设备能不能进来,两个互不相干。
总结
- 镜像模式下本机访问用
127.0.0.1(默认就通);想用本机 LAN IP 就开hostAddressLoopback=true。 - 局域网其他设备访问,配置 Hyper-V 防火墙层 (
Set-NetFirewallHyperVVMSetting/New-NetFirewallHyperVRule) - 两个层各管各的,按速查表对症配置即可。
踩了半天坑,记下来希望能帮到同样在 WSL2 里跑前后端、又被网络访问折磨的同学。如果对你有用,欢迎点赞收藏,后续我还会写 WSL2 + Rust/GDB、PyCharm 直连 WSL 等踩坑实录。