标签 wsl 下的文章

 在这之前先后使用过几个 WSLg/WSL2 的网络配置方案实现了局域网同网域(网段)互联互通,并且也打通了 IPv6,整体上对之前的“桥接网络”方案还算满意。

WSLg/WSL2 通过网桥实现局域网同网域(网段)互通

现在有更优雅的镜像网络可用。

  不过最近一年左右,微软随 Windows 11 23H2 正式释出了一个更加优雅的新解决方案:“镜像网络”,大概率是利用了 Hyper-V 虚拟交换机的“镜像端口”技术,此方案最早出现在预览版的 Windows 11 22H2(Build 22621.2359+) 。
  这就是轻量 VM 的优势,可以和 Windows 系统深度集成(方便快捷的优秀使用体验),同时享受 VM 带来的一切优势,比如嵌套虚拟化、原生 Linux 内核实现、适度的环境隔离等等。
  随着此次更新,微软为 WSL2 带来了其它一系列很有用的功能更新,比如“虚拟硬盘空间自动回收、空闲内存自动回收、DNS 代理隧道、Windows 系统防火墙集成、Windows 代理设置集成”,这些功能极大的方便了对子系统服务发现和暴露管理,深度优化了在子系统进行网络开发方向的体验。
 
  镜像网络和桥接网络,两个方案都具有无需关注端口转发,仅需关注更宏观的路由规则及防火墙设置的优势。不需要在 Windows 上配置各种撩骚的端口转发了,整个世界瞬间就清净了。鉴于 WSLg 已支持 GPU 半虚拟化透传进行 CUDA 开发,若后续 WSL2 子系统再支持下 USB 移动设备集成(方便调试 USB 连接的设备),那 Windows 岂不是最佳 Linux 发行版了?(虽然现阶段,有 USB device over Ethernet/Network 方案,不过比起原生支持,那差距还是有的。/滑稽)
 
版本要求:
OS: ≥ Windows 11 22H2(Build 22621.2359+)
WSLg/WSL2: Windows Subsystem for Linux 2.0.0+ ⇐ 点我更新 WSL2 子系统到较新的版本
截至目前,博主的宿主系统环境

wsl -v

WSL 版本: 2.0.14.0
内核版本: 5.15.133.1-1
WSLg 版本: 1.0.59
MSRDC 版本: 1.2.4677
Direct3D 版本: 1.611.1-81528511
DXCore 版本: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows 版本: 10.0.22631.3155

wsl -l -v

NAME STATE VERSION

  • Ubuntu Stopped 2

此处推荐个 WSLg/WSL2 的 Linux 实例图形化(GUI)管理工具 -> Github / Microsoft Store

 
步骤:
0x01、在满足上述系统要求的情况下,预先使用上述链接安装好子系统 WSL2.0+

设置 WSL2 为默认分发版本

wsl --set-default-version 2

更新子系统内核到较新的版本

wsl --update

安装一个你喜欢的 Linux 子系统发行版

安装完先启动下子系统,完成第一次初始化,防止某些冲突错误,比如:

WslRegisterDistribution failed with error: 0x80070057

wsl --list --online

wsl --install Ubuntu-22.04
或者你已有安装好的本地环境,只需要把子系统更新到 WSL2.0+
并把通过以下命令把 Linux 发行版切换到 WSL2/WSLg 即可

wsl --set-version

wsl --set-version '<发行版名称>' 2
 
0x02、使用 PowerShell 配置 Windows 网卡路由规则及防火墙规则

允许外部设备(含宿主 Windows)路由进站到 WSLg/WSL2 子系统

Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow

允许 WSLg/WSL2 虚拟交换机进行路由转发,主要是一些极特殊环境会用到

好像每次重启都会失效(因此重启后需要再次配置),但是我们可以把它编写成“PowerShell 脚本”放到“本地组策略”里,实现开机自动重新配置

本地组策略 -> 计算机策略 - Windows 设置 -> 脚本(启动/关机)

Get-NetIPInterface -IncludeAllCompartments |

Where-Object { $_.InterfaceAlias -match "^vEthernet\s.*(Default Switch|FSE HostVnic|WSL|WSLCore|LAN).*$" } |
Set-NetIPInterface -Forwarding Enabled -ErrorAction SilentlyContinue

其它相关命令(仅作为备注):

Get-NetAdapter -IncludeHidden
Get-VMSwitch
Get-VMNetworkAdapter -All
 
 
0x03、配置~.wslconfig文件,加入以下配置

此 Powershell/Posh/Pwsh 代码块用于创建或打开配置文件 ~.wslconfig

if (-not (Test-Path -Path "~/.wslconfig")) { New-Item -ItemType File ~/.wslconfig }
pushd ~ ; notepad .wslconfig

推荐的一些配置项如下

[wsl2] # 核心配置
autoProxy=false # 是否强制 WSL2/WSLg 子系统使用 Windows 代理设置(请根据实际需要启用)
dnsTunneling=false # WSL2/WSLg DNS 代理隧道,以便由 Windows 代理转发 DNS 请求(请根据实际需要启用)
firewall=true # WSL2/WSLg 子系统的 Windows 防火墙集成,以便 Hyper-V 或者 Windows 筛选平台(WFP)能过滤子系统流量(请根据实际需要启用)
guiApplications=true # 启用 WSLg GUI 图形化程序支持
ipv6=true # 启用 IPv6 网络支持

localhostForwarding=true # 启用 localhost 网络转发支持(新版已不支持在 mirrored 模式下使用,会自动忽略,所以无需注释掉,只是启用会有条烦人的警告而已)

memory=4GB # 限制 WSL2/WSLg 子系统的最大内存占用
nestedVirtualization=true # 启用 WSL2/WSLg 子系统嵌套虚拟化功能支持
networkingMode=mirrored # 启用镜像网络特性支持

pageReporting=true # 启用 WSL2/WSLg 子系统页面文件通报,以便 Windows 回收已分配但未使用的内存

processors=8 # 设置 WSL2/WSLg 子系统的逻辑 CPU 核心数为 8(最大肯定没法超过硬件的物理逻辑核心数)
vmIdleTimeout=-1 # WSL2 VM 实例空闲超时关闭时间,-1 为永不关闭,根据参数说明,目前似乎仅适用于 Win11+

[experimental] # 实验性功能(按照过往经验,若后续转正,则是配置在上面的 [wsl2] 选节)
autoMemoryReclaim=gradual # 启用空闲内存自动缓慢回收,其它选项:dropcache / disabled(立即/禁用)
hostAddressLoopback=true # 启用 WSL2/WSLg 子系统和 Windows 宿主之间的本地回环互通支持
sparseVhd=true # 启用 WSL2/WSLg 子系统虚拟硬盘空间自动回收
bestEffortDnsParsing=true # 和 dnsTunneling 配合使用,Windows 将从 DNS 请求中提取问题并尝试解决该问题,从而忽略未知记录(请根据实际需要启用)

useWindowsDnsCache=false # 和 dnsTunneling 配合使用,决定是否使用 Windows DNS 缓存池(新版已移除此实验性功能,未能转正)

ignoredPorts=3306 # 见:https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config#experimental-settings

 
 
P.S.:
很多人会遇到下面这个错误,是因为配置了 hostAddressLoopback,但没有配置 networkingMode=mirrored 镜像网络模式,另外务必记得更新子系统到 Windows Subsystem for Linux 2.0.0+ ⇐ 点我更新 WSL2 子系统到较新的版本

wsl: 检测到 localhost 代理配置,但未镜像到 WSL。
NAT 模式下的 WSL 不支持 localhost 代理。
如果遇到以下任意一个错误,请确保 Windows 版本符合要求,并且已更新到 Windows Subsystem for Linux 2.0.0+ ⇐ 点我更新 WSL2 子系统到较新的版本

wsl: 此计算机上不支持嵌套虚拟化。
wsl: 不支持镜像网络模式,正在回退到 NAT 网络
wsl: Hyper-V 防火墙不受支持
wsl: DNS 隧道不受支持
还有就是虚拟硬盘空间自动回收(sparseVhd=true)仅对配置完此项后,新创建的 Version 2 的子系统有效,而刚从 v1 转到 v2,或者已有的旧 v2 子系统 Linux 发行版,需要手动将其所使用的虚拟硬盘(VHDX)转换为稀疏格式
可通过以下命令来进行转化

wsl --manage '' --set-sparse true

wsl --manage 'Ubuntu-24.04' --set-sparse true
 
0x04、WSLg/WSL2 子系统内配置/etc/wsl.conf文件,加入以下配置,推荐一并配置 systemd 支持

此配置文件不能通过符号链接配置(软链接和硬链接都不行),只能通过真实副本拷贝

https://learn.microsoft.com/zh-cn/windows/wsl/wsl-config

[automount]
enabled=true
mountFsTab=true
options="metadata,dmask=0022,fmask=0077,umask=0022"
root=/mnt/

[filesystem]
umask=0022

[interop]
enabled=true
appendWindowsPath=false # 不添加 Windows 环境变量 Path,防止路径变量污染带来的干扰

其它网络配置

[network]
generateHosts=true
generateResolvConf=true

boot command 暂不支持 nohup 后台启动

command=nohup service cron start >/dev/null 2>&1 &

[boot]

command="/sbin/openrc default"

systemd=true
 
0x05、重启 WSLg/WSL2

powershell

wsl --shutdown ; wsl

查询子系统的 IP Address 地址,Just enjoy it!

将能看到一组和 Windows 宿主一致的双栈 IPv4/IPv6 地址及 MAC 地址

ip address show eth0

你可以使用 python 临时启动一个 Web 服务器测试网络连通性

python3 -m http.server -d . -b 0.0.0.0 54321
 
0x06、在镜像网络模式的 WSL2 子系统中使用 Docker 容器运行服务的坑

1、无法在 Windows 使用 localhost 本地回环地址 127.0.0.1 访问运行在容器内的服务

目前有三种解决方案(三选一):

1) 针对使用 Docker Desktop for Windows 用户(使用以下两种解决方法其一):
① 配置 ignoredPorts 端口(不推荐,这方法太 ugly 了)
② 请使用 Docker v27.3.0+ or latter 的版本(推荐)

其实不推荐使用 Docker Desktop for Windows,因为它一启动就会预留(占用)比较多的内存

2) 针对在 WSL2 内 Linux 发行版直接运行 Docker-CE Daemon 服务的用户(根据情况不同,使用以下两种解决方法其一):
① 针对使用 Systemd 的用户,可以使用此仓库提供的服务管理脚本
https://gist.github.com/shigenobuokamoto/b565d468541fc8be7d7d76a0434496a0

② 针对 OpenRC 用户(或不喜欢引入第三方资源的),暂时通过关闭 Docker 的 iptables 模块支持

缺点是会丧失容器的网络隔离性(记得重启 dockerd,必要时可能需要重建容器化服务甚至是重启 WSL2 子系统)

/etc/docker/daemon.json

{
"iptables": false
}

3) 自适应法:在宿主 Windows 访问 WSL 内 Docker 容器化服务时,使用 LAN IP 而不使用 localhost
1、无法在 Windows 使用 localhost 本地回环地址 127.0.0.1 访问运行在容器内的服务

目前有三种解决方案(三选一):

1) 针对使用 Docker Desktop for Windows 用户(使用以下两种解决方法其一):
① 配置 ignoredPorts 端口(不推荐,这方法太 ugly 了)
② 请使用 Docker v27.3.0+ or latter 的版本(推荐)

其实不推荐使用 Docker Desktop for Windows,因为它一启动就会预留(占用)比较多的内存

2) 针对在 WSL2 内 Linux 发行版直接运行 Docker-CE Daemon 服务的用户(根据情况不同,使用以下两种解决方法其一):
① 针对使用 Systemd 的用户,可以使用此仓库提供的服务管理脚本
https://gist.github.com/shigenobuokamoto/b565d468541fc8be7d7d76a0434496a0

② 针对 OpenRC 用户(或不喜欢引入第三方资源的),暂时通过关闭 Docker 的 iptables 模块支持

缺点是会丧失容器的网络隔离性(记得重启 dockerd,必要时可能需要重建容器化服务甚至是重启 WSL2 子系统)

/etc/docker/daemon.json

{
"iptables": false
}

3) 自适应法:在宿主 Windows 访问 WSL 内 Docker 容器化服务时,使用 LAN IP 而不使用 localhost`