Ryan Shang

生死看淡,不服就干

0%

WSL2设置镜像网络模式

一、背景

WSL2在去年下半年时候更新了2.0的Pre-Relese版本,详细更新内容:https://github.com/microsoft/WSL/releases/tag/2.0.0

总结一下主要是:

  • 支持自动回收内存
  • 支持自动释放 WSL2 虚拟硬盘空间
  • 支持和 Windows 使用相同的网络(镜像网络)
  • 支持 DNS Tunneling
  • 支持 Windows 设置的代理
  • 支持 Windows 防火墙
  • 支持 Multicast

终于,WSL2可以和宿主机的Windows共用一套网络端口了。

之前的的方式是使用桥接模式给WSL2配置静态IP,现在可以设置镜像网络,直接通过127.0.01来访问WSL2中的服务。这样也能解决当网络环境变化时候,需要重新配置IP的问题。

Note:

  • Windows系统版本需要至少 Windows 11 23H2
  • WSL最新正式版本为2.0.14

二、配置过程

1. 在Windows宿主机上修改WSL的config

在当前用户目录(C:\Users\xxx)下修改.wslconfig,内容:

1
2
3
4
5
6
7
8
9
10
11
12
[wsl2]
# networkingMode=bridged
# vmSwitch=Home # 此处的名称和指定的虚拟网络交换机一致
# dhcp=false # 禁用DHCP,在WSL2系统中通过设置Linux的静态IP实现获取IP
networkingMode = mirrored # 端口自动转发,Windows和WSL共享端口,都使用127.0.0.1
dnsTunneling = true # WSL的DNS请求通过Windows转发
firewall = true # WSL同步Windows防火墙规则
autoProxy = false # Windows设置代理时自动同步给WSL

[experimental]
sparseVhd = true # 自动清理磁盘空间
autoMemoryReclaim = disabled # 可以在gradual 、dropcache 、disabled之间选择,开启会造成WSL中Docker启动异常

Note:

  • 如果你在WSL里使用docker,需要将 autoMemoryReclaim配置为dropcache或者disabled否则无法启动Docker

  • 如果你在WSL里使用docker,需要在/etc/docker/daemon.json 里添加一句 “iptables”: false,否则你可能无法在Windows中连接Docker容器。

2. 在WSL2中增加网络相关的配置

修改下WSL2下/etc/wsl.conf,修改内容:

1
2
3
[network]
generateResolvConf = true
generateHosts = true

4. 在WSL2中配置DHCP自动获取IP

修改WSL2下的/etc/network/interfaces,修改内容:

1
2
3
4
5
6
7
8
9
10
11
12
# The primary network interface
# 开机自动连接网络
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp

# 注释掉wsl bridged配置
# auto eth0
# iface eth0 inet static
# address 192.168.3.2
# netmask 255.255.255.0
# gateway 192.168.3.1

5. 重新启动WSL2

在powershell中输入:

1
wsl --shutdown

再次打开WSL2,使用ip addr命令查看IP地址,已经和宿主机Windows的IP一致了:

1
2
3
4
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
inet 192.168.3.3/24 brd 192.168.3.255 scope global noprefixroute eth1
valid_lft forever preferred_lft forever

已经成功设置完成。

三、端口冲突问题

配置完成后,发现docker中在运行的服务有些挂掉了,重启提示端口冲突,在Windows中使用netstat -aon | findstr "3306"查看进程,也没有查到相关端口。

1. 原因

查阅资料后发现,这个问题的原因分为两部分:

  1. Windows 中有一个TCP 动态端口范围,处在这个范围内的端口,有时候会被一些服务占用。在 Windows Vista(或 Windows Server 2008)之前,动态端口范围是 10255000;在 Windows Vista(或 Windows Server 2008)之后,新的默认起始端口为 49152,新的默认结束端口为 65535
  2. 如果安装了 Hyper-V,那么 Hyper-V 会为容器宿主网络服务(Windows Container Host Networking Service)随机保留一些端口号使用。

正常情况下,Hyper-V 虽然会在TCP 动态端口范围中随机挑一些端口号保留(占用),不过保留的端口号普遍比较大,就算保留几百、几千个也影响不大。但是,Windows 自动更新有时会出错,导致这个范围的起始端口被重置为 1024。这就会导致一些常用端口因为被保留而无法使用。

使用命令 netsh int ipv4 show dynamicport tcp 可以查看目前TCP 动态端口的范围:

1
2
3
4
5

协议 tcp 动态端口范围
---------------------------------
启动端口 : 1024
端口数 : 13977

这只是一个待选择范围,并不代表其中的所有端口都会被保留,只是有一部分会被 Hyper-V 征用。使用 netsh int ipv4 show excludedportrange protocol=tcp 命令可以查看当前所有已经被征用了的端口:

1
2
3
4
5
6
7
8
9

协议 tcp 端口排除范围

开始端口 结束端口
---------- --------
3296 3334
5357 5357
27339 27339
50000 50059

这些端口有时候会随机到一些常用端口,比如3000、3306、8080等,导致这些常用端口无法使用。

2. 解决方案

可以通过重启网络来重设随机预留的端口,但是这就和开盲盒一样,随机性太高。正确的解决思路,因该是调整TCP 动态端口范围,避开常用的端口区间。

使用管理员权限运行Powershell,执行:

1
2
3
4
5
netsh int ipv4 set dynamic tcp start=50000 num=15536
netsh int ipv6 set dynamic tcp start=50000 num=15536
# 重启网络
net stop winnat
net start winnat

TCP 动态端口范围限定在50000-65535,重启网络,再次查看目前TCP 动态端口的范围:

1
2
3
4
5

协议 tcp 动态端口范围
---------------------------------
启动端口 : 50000
端口数 : 15536

这样就可以成功避开日常使用的端口,保证不会因为端口冲突导致docker等服务无法运行的问题。