做 Web 开发的人应该都有过这种经历Windows 上跑着 WSL2后端服务在 Linux 环境里跑起来了浏览器打开localhost:8080一切正常但想把手机连到同一个 Wi-Fi直接输入电脑的局域网地址加端口死活连不上。页面一直转圈后台管理页面也查不出问题。这篇文章就是来彻底解决“WSL2 设置局域网访问”这个问题的我把最常用的端口转发方案、新出的镜像网络模式、IP 漂移的自动化处理以及我踩过的坑一次说完。先说结论WSL2 默认的网络模型是 NAT不是桥接。局域网里的其他设备根本看不见 WSL2 这台“虚拟机”的内部地址。要让局域网设备访问到 WSL2 里的服务本质上就两条路——要么在 Windows 宿主机上做一层端口转发把流量“送”进去要么把 WSL2 的网络模式改成镜像让 WSL2 和 Windows 共享同一个局域网 IP。这两条路我会各用一整节讲清楚并给出可以直接抄作业的命令和脚本。1. 为什么WSL2默认不能从局域网访问先看懂网络模型1.1 一个关键认知WSL2 在 NAT 后面很多人一开始会想我服务都监听0.0.0.0:8080了为什么局域网还是不通其实问题不在服务监听而在网络拓扑。WSL2 是基于 Hyper-V 虚拟化的它启动后是一台轻量虚拟机通过一个虚拟交换机和宿主机相连。默认情况下WSL2 会从虚拟交换机拿到一个独立私有网段的 IP通常是172.x.x.x或者10.x.x.x。这个 IP 是 NAT 内部的地址只有 Windows 宿主机能直达。你的手机、另一台电脑甚至路由器本身都不知道172.20.10.5这个地址在哪。打个比方WSL2 像是你家里的一间卧室Windows 是客厅。你站在客厅能看见卧室的门但站在小区门口的人看不见卧室的窗户他只能看见整栋房子的大门。想让小区里的人访问卧室里的东西要么让他走后门端口转发要么把卧室的门开到临街镜像模式。所以无论服务监听的是localhost还是0.0.0.0在局域网设备看来WSL2 的地址不可达就永远无法建立连接。这也是排查时最常被忽略的一点很多人反复检查服务配置却忘了先弄清网络可达性。1.2 localhost 能访问的真正原因别把它和局域网混淆另一个让人困惑的点是既然局域网访问不了为什么 Windows 上打开localhost:8080却没问题这是 WSL2 自带的一个便利机制。较新版本的 WSL 会在 Windows 上做一个本机回环转发宿主机访问localhost时流量会被自动重定向到 WSL2 虚拟机的对应端口。你不需要配任何规则打开浏览器输localhost:8080、127.0.0.1:8080甚至[::1]:8080都能通。但这里有一个很容易误解的地方——这个机制只服务于本机回环它不会让局域网设备也跟着享福。手机访问你的电脑局域网 IP192.168.1.100:8080时流量是打到你 Windows 网卡上的Windows 回环转发机制根本不会处理这种从外部网卡进来的流量所以超时是很正常的。理解了这两点后面的操作原理就非常清楚了我们要么让 Windows 把外部进来的流量转交给 WSL2要么让 WSL2 直接暴露在局域网里。2. 经典方案用 netsh 端口转发搞定局域网访问2.1 配置前先做两件事查 WSL2 IP、确认服务监听netsh 端口转发是最经典、最通用的方案Windows 自带不需要装任何额外工具。它的原理是在 Windows 上开一个代理端口把发到这个端口的 TCP 流量转给 WSL2 的 IP。配置前先拿到当前 WSL2 的 IPwsl hostname -I这个命令会输出 WSL2 的 IPv4 地址比如172.24.10.5。注意它可能有多个输出一般取第一个。有些人会用wsl hostname -i但那个在某些环境里返回的是 IPv6别用错。拿到 IP 后进 WSL2 确认你的服务确实在监听0.0.0.0或*。以普通 Linux 服务为例ss -tlnp | grep 8080如果输出里显示的是0.0.0.0:8080或*:8080说明服务对网络接口开放如果显示127.0.0.1:8080那就算配了转发也白搭因为服务只接受本机回环连接。常见软件的改法我给你列一下Node.jsapp.listen(8080, 0.0.0.0)Python Flaskapp.run(host0.0.0.0, port8080)Djangopython manage.py runserver 0.0.0.0:8080nginxlisten 8080;MySQL把bind-address从127.0.0.1改成0.0.0.0或注释掉这一步是很多新手踩坑的地方查了半天的转发规则和防火墙最后发现是服务自己把门锁死了。2.2 添加转发规则与防火墙放行确认服务监听0.0.0.0后在 Windows PowerShell 里以管理员身份运行以下两条命令netsh interface portproxy add v4tov4 listenport8080 listenaddress0.0.0.0 connectport8080 connectaddress172.24.10.5netsh advfirewall firewall add rule nameWSL2 8080 dirin actionallow protocolTCP localport8080两条命令一条都不能少。第一条负责把 Windows 的0.0.0.0:8080端口转发到 WSL2 的172.24.10.5:8080第二条负责在 Windows 防火墙里放行8080端口的入站流量。理解一下参数listenaddress0.0.0.0表示 Windows 在所有网卡接口上监听。如果你想限制只有局域网网卡能访问可以填 Windows 自己的局域网 IP但开发场景通常直接0.0.0.0省事。connectaddress填的必须是 WSL2 当前的 IP这也埋下了重启后配置失效的隐患后面第 4 节我会专门讲自动化方案。防火墙规则建议dirin actionallow意思是允许外部向本机这个端口发起入站连接。查看当前所有转发规则用netsh interface portproxy show all删除某条规则用netsh interface portproxy delete v4tov4 listenaddress0.0.0.0 listenport8080删除防火墙规则netsh advfirewall firewall delete rule nameWSL2 80802.3 从三个角度验证结果配置完之后不要急着拿手机试先分三步验证能帮你快速定位问题出在哪一层。第一步在 Windows 上访问localhost:8080确认回环转发正常工作curl http://localhost:8080第二步在 Windows 上访问自己的局域网 IP比如curl http://192.168.1.100:8080这一步很关键因为它能验证 Windows 防火墙是否放行。如果 Windows 上访问局域网 IP 都失败几乎可以断定是防火墙问题和手机、路由器无关。第三步换到手机或另一台电脑访问http://192.168.1.100:8080。如果这一步能通局域网访问就算正式搞定。如果不通但第二步通优先检查是不是两台设备不在同一网段、路由器开了 AP 隔离客户端隔离或者手机用的是流量而不是 Wi-Fi。我自己的经验是大部分“Windows 上能通、手机不能通”的案例问题都出在手机和电脑不在同一网段或者 WiFi 路由器的 AP 隔离功能被打开。这两点容易被下意识忽略一查一个准。3. 新解法镜像网络模式一条配置省掉端口转发3.1 镜像模式是什么适合什么环境如果你用的是新版 WSL其实还有一个比 netsh 优雅得多的方案——镜像网络模式官方叫 mirrored networking mode。它的思路是让 WSL2 不再使用独立的 NAT 私有 IP而是直接共享 Windows 宿主的网络栈WSL2 里的服务就像跑在 Windows 本机上一样天然拥有同一个局域网 IP。配好后局域网设备直接访问 Windows 的局域网 IP 加端口就能打到 WSL2 的服务不用再单独配转发规则。而且 IPv6 支持、对局域网服务的访问也都变得简单很多。我自己的判断如果只是个人开发系统版本也比较新镜像模式是首选。它的配置成本远低于 netsh而且绕开了 IP 漂移这个最头疼的问题。但在公司办公环境或者对网络隔离要求比较高的场景镜像模式共享网络栈的特性可能会和某些准入软件、安全代理产生冲突这时候用回 NAT 加 netsh 反而更稳。3.2 配置步骤与版本要求先确认你的 WSL 版本支持镜像模式。在 PowerShell 里运行wsl --version如果输出的版本信息是 1.1.3 以上Windows 11 22H2 之后默认带的版本基本都支持就可以直接用。如果没有--version子命令说明 WSL 太旧先升级。配置方法非常简单在 Windows 用户目录下创建或编辑.wslconfig文件写入# .wslconfig [wsl2] networkingModemirrored保存后在 PowerShell 里重启 WSLwsl --shutdown再启动 WSL 2进入之后用ip addr看看网卡信息你会发现 WSL2 的 IP 变成和 Windows 局域网 IP 一致的地址了。这时候如果你的服务监听0.0.0.0局域网设备直接就能访问。放行防火墙这一步仍然需要和上一节第二条命令一样netsh advfirewall firewall add rule nameWSL2 8080 dirin actionallow protocolTCP localport80803.3 镜像模式的坑与注意事项镜像模式不是万能药它有几个我实测遇到的坑。第一服务必须监听0.0.0.0而不是127.0.0.1。镜像模式下 Windows 的localhost访问依然能到 WSL2 服务但局域网访问走的是真实网卡Win 不会帮你做接口转换。所以前面第 2.1 节里“确认服务监听”的步骤在镜像模式下依然要做。第二DNS 解析偶尔有怪问题。我在某些公司网络下遇到过 WSL2 里域名解析变慢或失败的情况当时把原因归到镜像模式上回退 NAT 就好了。如果你也遇到别硬扛换方案。第三部分老版本 Windows 10 的 WSL 不支持镜像模式或者支持了也有兼容问题。如果wsl --version已经是最新还是配置不生效大概率是系统版本受限。3.4 两种方案怎么选一张对照表维度netsh 端口转发镜像网络模式配置成本中等需要两条命令加防火墙规则低改一个文本文件重启即可适用版本几乎所有 WSL2 版本需要较新 WSL 版本建议 Windows 11 22H2IP 漂移问题有WSL2 IP 变化后转发失效无共享 Windows IP网络隔离性好NAT 天然隔离弱共享整个网络栈公司网络兼容性更稳可能和准入代理冲突额外工具不需要不需要选型建议很简单个人开发、设备可控、版本够新直接镜像模式老版本、公司环境、网络复杂就用 netsh 转发。两条都会一点比只会一条强得多。4. 处理最大的隐患WSL2 IP 漂移与自动更新脚本4.1 为什么重启后配置就失效用 netsh 方案的兄弟一定遇到过这个问题昨天还好好的今天开机一访问端口又不通了。一看portproxy show all规则还在但connectaddress指向的 IP 已经变了。WSL2 的 IP 不是固定分配的每次冷启动重启电脑或执行wsl --shutdown后虚拟交换机都可能重新分配一个地址可能还是同一个网段但最后一段十有八九会变。你配好的转发规则像一个写了旧门牌号的快递单地址不对快递自然送不到。解决思路有两个方向一是尽量别让 IP 变但这在 NAT 模式下不太可靠二是每次 WSL2 启动后自动把转发规则更新为新 IP。第二种方向最实用。4.2 自动同步转发规则的 PowerShell 脚本我的做法是写一个 PowerShell 脚本每次 WSL2 启动后跑一遍自动取当前 WSL2 IP删除旧转发规则再添加新规则。脚本核心部分如下# update-wsl-proxy.ps1 # 需要在管理员权限的 PowerShell 中运行 $ports (8080, 3000) # 获取 WSL2 当前 IP取第一个有效地址 $wslIp (wsl hostname -I).Trim().Split( )[0] if (-not $wslIp) { Write-Host 获取 WSL2 IP 失败请确认 WSL2 已启动 exit 1 } Write-Host 当前 WSL2 IP: $wslIp foreach ($port in $ports) { # 删除可能存在的旧规则忽略错误 netsh interface portproxy delete v4tov4 listenaddress0.0.0.0 listenport$port 2$null | Out-Null # 添加新转发规则 netsh interface portproxy add v4tov4 listenaddress0.0.0.0 listenport$port connectaddress$wslIp connectport$port Write-Host 已更新端口转发: 0.0.0.0:$port - $wslIp:$port } # 打印最终规则列表 netsh interface portproxy show all脚本里的$ports (8080, 3000)是你需要暴露的端口列表按实际需求改就行。注意脚本必须以管理员身份运行否则 netsh 会拒绝操作。可以直接右键 PowerShell 以管理员身份打开再执行powershell -ExecutionPolicy Bypass -File .\update-wsl-proxy.ps14.3 做成开机/登录任务一劳永逸手动跑脚本还是麻烦。我把它接入了 Windows 任务计划程序让它在 WSL2 每次启动后自动执行。具体做法打开“任务计划程序”创建基本任务触发器选“登录时”或“系统启动时”操作选“启动程序”程序填powershell.exe参数填-ExecutionPolicy Bypass -File C:\scripts\update-wsl-proxy.ps1这里有个小细节WSL2 可能是在登录之后才被某个终端拉起的所以单纯绑定“登录时”不一定能保证脚本跑到 WSL2 已经就绪。比较保险的做法是额外设置一个“稍后延迟”触发器比如登录后等 30 秒再执行或者直接在你常用的启动脚本里带上这段逻辑。我后来更习惯的做法是在 WSL2 内部的服务启动脚本里加一行通过 PowerShell 调外部脚本的通知但为了简单任务计划已经够用。4.4 关于固定 IP 的几个尝试与结论也有人想直接从根源上解决 IP 漂移给 WSL2 固定一个 IP。我在网上看到各种做法自己也试过一些结论是在 NAT 模式下固定 WSL2 IP稳定性普遍一般。有人会在.wslconfig里试各种键但目前官方并不支持直接指定 NAT 模式下的固定 IP。另有人尝试在 WSL2 内部手动用ip addr add添加一个静态地址但问题是 DHCP 分配随时可能冲突而且每次重启都要重新执行脚本复杂度和风险反而更高。所以在 NAT 模式下我的建议是别和 IP 较劲接受变化用自动化脚本去适应变化。真正想要 IP 稳定用镜像模式是最干净的解法。5. 局域网访问常见问题排查一张速查表5.1 症状、原因、解决办法对照表配置 WSL2 局域网访问说到底就是网络模型、服务监听、防火墙、IP 四件事。我整理了实际排查中最常遇到的几个问题症状最常见原因解决办法Windows 上 localhost 能通局域网 IP端口不通netsh 转发没配、防火墙拦截或 WSL2 IP 变了先看netsh interface portproxy show all的 connectaddress 是否为当前 WSL2 IP再检查防火墙放行手机访问超时但 Windows 本机访问局域网 IP 正常手机和电脑不在同一网段或路由器开了 AP 隔离确认两台设备都连同一个 Wi-Fi登录路由器查看是否启用了“客户端隔离”功能netsh 添加规则提示参数错误或无法绑定端口在 Windows 本机已被占用或 listenaddress 写错netstat -anoWSL2 重启后局域网访问失效WSL2 IP 变化转发规则指向旧地址跑自动更新脚本或改用镜像模式镜像模式开了服务也监听 0.0.0.0但局域网还是不通防火墙未放行或者服务只是监听 IPv6 的 0.0.0.0[::]检查 Windows 防火墙入站规则确认服务同时监听 IPv4 通配地址curl 能通但浏览器打不开或数据库客户端连不上服务自身的访问控制、认证或绑定策略检查应用配置例如 MySQL 的 bind-address、Redis 的保护模式5.2 几个容易忽略的细节排错时我建议先确认一个傻问题你测试访问的 IP到底是不是 Windows 的局域网 IP在 Windows 上用ipconfig看以太网适配器或无线局域网适配器 WLAN下的 IPv4 地址那才是局域网设备该访问的地址。很多人拿 WSL2 的172.x.x.x去给手机访问那当然不通。另一个细节是防火墙规则的配置文件范围。netsh advfirewall firewall add rule默认对所有配置文件生效但如果你在图里操作时只勾选了“专用”而 Windows 当前网络类型是“公用”结果就是规则没生效。开发环境建议把网络配置文件设为“专用”省心。还有一点如果你同时开着多个 WSL 发行版wsl hostname -I返回的可能不是你想要的那个发行版 IP。可以用wsl -d 发行版名 hostname -I指定发行版。这个细节我踩过一次后来写脚本时都会显式加-d参数。6. 我的配置习惯和一点踩坑心得6.1 我会优先选哪条路线接待这个问题的项目后我现在的习惯是分情况选择个人开发、系统版本够新直接上镜像模式只在.wslconfig里加一行重启后服务跑到0.0.0.0就完事。如果是公司环境、老系统或者 WSL2 里跑了一些需要强隔离的服务我会用 NAT 加 netsh 转发配合自动更新脚本把 IP 漂移问题交给任务计划处理。两条路都实践过之后我的体会是netsh 方案更稳但更费事镜像模式更省心但依赖系统版本。关键是要理解背后的原理而不是死记命令。理解了 NAT、端口转发和防火墙任何网络环境你都能很快定位问题。6.2 最后补充几个实用小技巧排查时有个低成本检查命令在手机或另一台电脑上敲nc -zv 192.168.1.100 8080如果返回succeededTCP 层通了问题基本就只剩应用层。如果nc不可用也可以用 nmapnmap -Pn -p 8080 192.168.1.100另外无论用哪种方案我都不建议把所有端口一股脑全暴露。开发时只转发需要用到的端口不用的时候删掉防火墙规则和转发规则。这个习惯不仅能减少安全风险也能避免宿主机和 WSL2 两边端口互相干扰时说不清的问题。最后提一个容易让人迷惑的小知识点WSL2 的localhost自动转发机制是微软帮你实现的本机便利它不是普遍的网络代理。所以即使你已经配好了局域网的转发规则也不要在心里默认“Windows 上 localhost 能通就万事大吉”每次改完配置都拿局域网设备真实访问一次才算真正验证通过。