核心原理
WSL2 是独立 NAT 虚拟机,拥有172.x.x.x内网 IP;默认只监听 127.0.0.1、Windows 防火墙拦截、无端口转发是访问失败三大根源。
一、第一步:WSL 内服务必须监听 0.0.0.0(90% 人踩坑)
1. 检查当前监听端口(WSL 终端执行)
bash
运行
# 替换3000为你的http端口
ss -tulnp | grep 3000
- 正常:
0.0.0.0:3000所有网卡可访问 - 异常:
127.0.0.1:3000仅 WSL 内部能访问,Windows 主机直接连不通
2. 各服务修改监听地址示例
Python 内置 http 服务
bash
运行
# 正确,绑定全部网卡
python3 -m http.server 3000 --bind 0.0.0.0
# 错误(默认只127.0.0.1)
python3 -m http.server 3000
Flask/Django
python
运行
# Flask
app.run(host="0.0.0.0", port=3000, debug=True)
# Django
python manage.py runserver 0.0.0.0:3000
Node/Express
js
运行
app.listen(3000, "0.0.0.0", ()=>{})
Nginx
修改nginx.conf监听行:
nginx
listen 3000; # 等价0.0.0.0:3000,不要写127.0.0.1:3000
3. 获取 WSL 真实 IP(Windows 访问用)
bash
运行
hostname -I | awk '{print $1}'
# 输出示例:172.27.135.66
Windows 浏览器直接访问:http://172.27.135.66:3000
二、第二步:关闭 WSL 内部防火墙(Ubuntu/Debian)
WSL 内置 ufw 拦截外部请求:
bash
运行
# 临时关闭
sudo ufw disable
# 放行端口(推荐)
sudo ufw allow 3000/tcp
三、第三步:Windows 防火墙放行端口(关键)
管理员身份打开 PowerShell,放行你的端口(示例 3000):
powershell
# 创建入站规则,允许TCP 3000
New-NetFirewallRule -DisplayName "WSL HTTP 3000端口" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 3000
验证规则:
powershell
Get-NetFirewallRule -DisplayName "WSL HTTP 3000端口"
四、场景 1:仅 Windows 本机访问(172.x IP)
完成上面三步即可直接用 WSL 的172.x.x.x:端口访问。
测试连通(Windows PowerShell):
powershell
Test-NetConnection 172.27.135.66 -Port 3000
TcpTestSucceeded: True 代表通了。
五、场景 2:局域网手机 / 其他电脑访问(Windows 局域网 IP,如 192.168.x.x)
WSL 的 172 网段是虚拟机内网,局域网其他设备无法直接访问,必须配置 Windows 端口转发:
1. 一键转发命令(管理员 PowerShell)
powershell
# 替换3000为端口,自动获取WSL IP
$wslIp = (wsl hostname -I).Trim()
netsh interface portproxy add v4tov4 listenport=3000 listenaddress=0.0.0.0 connectport=3000 connectaddress=$wslIp
2. 查看 / 删除转发规则
powershell
# 查看所有转发
netsh interface portproxy show all
# 删除转发
netsh interface portproxy delete v4tov4 listenport=3000 listenaddress=0.0.0.0
3. 访问方式
手机 / 另一台电脑打开:http://Windows主机局域网IP:3000(例:192.168.1.105:3000)
六、常见报错排查清单
- Connection refused
- 服务只监听 127.0.0.1 → 改成 0.0.0.0
- 端口写错、服务未启动
- 超时无法连接
- Windows 防火墙未放行端口
- 未做 portproxy 转发(局域网访问)
- WSL ufw 防火墙拦截
- 重启 WSL 后 IP 变了,端口转发失效
- 每次重启重新执行转发命令;或写 PowerShell 开机脚本自动配置
- WSL1 vs WSL2 区分 powershell
wsl -l -v- WSL1:共享 Windows 网络,直接localhost访问,无需转发
- WSL2:独立虚拟机,必须按上面步骤操作
极简快速修复脚本(复制到管理员 PowerShell 运行)
替换端口 3000 为你自己的端口:
powershell
$port=3000
# 放行防火墙
New-NetFirewallRule -DisplayName "WSL HTTP $port" -Direction Inbound -Action Allow -Protocol TCP -LocalPort $port -ErrorAction SilentlyContinue
# 添加端口转发
$wslIp=(wsl hostname -I).Trim()
netsh interface portproxy delete v4tov4 listenport=$port listenaddress=0.0.0.0 2>&1 | Out-Null
netsh interface portproxy add v4tov4 listenport=$port listenaddress=0.0.0.0 connectport=$port connectaddress=$wslIp
Write-Host "WSL IP: $wslIp`nWindows局域网访问地址: http://$((Get-NetIPAddress | Where-Object {$_.AddressFamily -eq 'IPv4' -and $_.InterfaceAlias -notlike 'vEthernet*' -and $_.IPAddress -ne '127.0.0.1'}).IPAddress):$port"
正文完
可以使用微信扫码关注公众号(ID:xzluomor)