背景

最近本人尝试搭建几个局域网 Web 服务

考虑到wsl2有以下优势:

  • 可以直接挂载本地硬盘:/mnt/c
  • 可以根据程序需求动态变更所需资源
  • 对外跟宿主机IP是一致的,本机可以通过 127.0.0.1 访问,外部设备可以通过宿主机IP访问

于是尝试采用WSL2搭建 Web 服务...

过程

在搭建好后,发现宿主机需要开启端口转发其他电脑才能访问到,网上教程如下:

netsh interface portproxy add v4tov4 listenport=8001 listenaddress=0.0.0.0 connectport=8001 connectaddress=localhost
侦听 ipv4:                 连接到 ipv4:

地址            端口        地址            端口
--------------- ----------  --------------- ----------
0.0.0.0         8001        localhost       8001

此时一切正常,局域网其他主机可以顺利访问到 WSL2 中的 Web 服务,胜利仿佛在对我挥手

但在重启电脑后,出现以下bug:

  • 其他设备无法访问到WSL2中的 Web 服务
  • 宿主机
    • 127.0.0.1:8001 无法访问
    • localhost:8001 可以访问
    • 172.*.*.*:8001 可以访问

在其他设备和宿主机的 172.0.0.1 尝试连接时,宿主机CPU会跑满,根据相应端口和对应PID,查到此时iphlpsvc 进程会占满CPU,查看此进程为IP Helper 服务

尝试百度无解...GitHub issue区有相同情况WSL 2 Linux host cannot be accessed by a custom domain name or 127.0.0.1 · Issue #5728 · microsoft/WSL · GitHub

于是尝试debug:

  1. 查看宿主机Hosts,发现无异常

  2. 检查宿主机和 WSL2 的系统防火墙,发现无异常

  3. 重启 WSL2,无解

  4. 将Windows宿主机的网络重置:将所有网络适配器重置为出厂设置,无解

  5. 临时启动其他端口的 Web 服务,发现宿主机可以通过127.0.0.1:port进行连接,但之前设置过的端口依旧无法使用,此时考虑到是否是映射环境出现了问题

于是乎,在一位博主的帖子中(Troubleshooting WSL + localhost:3000 'connection refused' issue - DEV Community 👩‍💻👨‍💻)发现,关闭端口转发后,IP Helper 不会高占用,而且本机127.0.0.1:8001 可以正常访问web服务,但其他设备就无法访问到 WSL2 中的 Web 服务

思考:可能是相同端口转发出现了混乱?

解决

自己尝试:将0.0.0.0:7001localhost:8001进行映射,重启服务,发现可用

netsh interface portproxy add v4tov4 listenport=7001 listenaddress=0.0.0.0 connectport=8001 connectaddress=localhost
net stop iphlpsvc
net start iphlpsvc
侦听 ipv4:                 连接到 ipv4:

地址            端口        地址            端口
--------------- ----------  --------------- ----------
0.0.0.0         7001        localhost       8001

或者:将宿主机的对外 IP:Portlocalhost:8001进行映射,重启服务,发现可用(此处IP较为敏感,用 __.__.__.__ 代替)

PS > netsh interface portproxy delete v4tov4 listenport=7001 listenaddress=0.0.0.0

PS > netsh interface portproxy add v4tov4 listenport=7001 listenaddress=__.__.__.__ connectport=8001 connectaddress=localhost

PS > netsh interface portproxy show all

侦听 ipv4:                 连接到 ipv4:

地址            端口        地址            端口
--------------- ----------  --------------- ----------
__.__.__.__     7001        localhost       8001

PS > net stop iphlpsvc
IP Helper 服务正在停止.
IP Helper 服务已成功停止。

PS > net start iphlpsvc
IP Helper 服务正在启动 .
IP Helper 服务已经启动成功。