WSL开发系列-网络篇(wsl固定ip)

wsl网络情况较复杂,本篇除了官方的网络配置事项,主要添加了:
1.wsl自动获取宿主机ip的脚本。
2.wsl设置固定(静态)ip的配置方法。

2023.4更新:因wudo异常,wsl网段的windows静态ip的设置使用bat脚本+任务计划程序实现

导航

一 基于官方说明

建议先阅读官方文档:https://learn.microsoft.com/zh-cn/windows/wsl/networking

通过官方配置和以下教程,可以达到如下效果,无需记住任何ip

  • windows访问wsl:使用localhost即可(但是不能使用127.0.0.1)
  • wsl访问windows:使用自动配置的my.win即可(见下)

如果系统是专业版(可开启Hyper-V),可参考 https://github.com/luxzg/WSL2-fixes 配置wsl桥接网络。
本文相关配置在使用wsl桥接网络的情况下可能无效或没必要,不过桥接网络本身还没有被wsl正式支持的。
且我用的是家庭版,虽然也可以开启,但可能有风险,故暂不使用。

注意:这篇文章都是针对wsl网络模式为默认的nat模式而作的,新版已经出现了 镜像网络模式(mirrored),见
https://learn.microsoft.com/zh-cn/windows/wsl/networking#mirrored-mode-networking
但截至到24年1月份个人使用起来仍有坑,在使用代理的时候代理ip得写真实网卡的ip,所以最终没用上

1 wsl自动获取宿主机ip

注意:如果采用了下面设置静态ip的方法,会一并设置windows静态ip,就不需要使用这里的脚本了!

见:https://learn.microsoft.com/zh-cn/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip

这里的脚本主要是负责自动获取win-ip、添加host映射:
1.wsl的hosts文件默认情况下是从windows继承过来的,每次都会重新生成(可通过wsl.conf控制),所以需先删除原来的my.win配置
2.sed结果需要使用/tmp/hosts作为中转,不能直接输出到/etc/hosts,否则/etc/hosts会被清空

1
2
3
4
5
6
7
cat << 'EOF' >> /etc/profile
host_ip=$(cat /etc/resolv.conf |grep "nameserver" |cut -f 2 -d " ")
sed -e "/my.win/d" /etc/hosts > /tmp/hosts
cat /tmp/hosts > /etc/hosts
echo "$host_ip my.win" >>/etc/hosts
EOF

另外在windows的hosts文件中配置 127.0.0.1 my.win,
这样,在windows上启动的服务,不管在wsl还是windows上,都可以通过my.win访问到了

2 局域网访问wsl2的操作示例

见:https://learn.microsoft.com/zh-cn/windows/wsl/networking#accessing-a-wsl-2-distribution-from-your-local-area-network-lan

需要使用netsh interface portproxy功能,按照help提示操作就行

以下为示例,局域网其他机器只需要连接宿主机的19909端口即可访问wsl2内19909端口的内容:

在powershell管理员模式下执行命令,

1
2
3
4
5
6
7
8
# 重置端口代理
netsh interface portproxy reset
# 最好一并设置v4tov6,例如springboot网络默认是v6的
netsh interface portproxy add v4tov6 listenport=19909 listenaddress=0.0.0.0 connectport=19909 connectaddress=localhost
netsh interface portproxy add v4tov4 listenport=19909 listenaddress=0.0.0.0 connectport=19909 connectaddress=localhost
# 查看端口配置
netsh interface portproxy show all

二 wsl配置固定ip

除了docker访问wsl,其他大部分场景下不需要这个功能

windows的docker不支持使用host网络,也就是不能通过localhost访问wsl
ip是可以的,但wsl的ip每次启动都会变,所以比较麻烦,这里通过使用固定ip解决

参考:https://www.cnblogs.com/Likfees/p/16750300.html

2023.4更新:wudo有bug,不推荐使用,WIN_IP的设置还是放到windows下去执行

1 使用Shell启动脚本设置wsl静态ip

注意此处调用了wudo(见WSL开发系列-基础篇)以使用管理员权限调用netsh工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cat << 'EOF' > setup-static-ip.sh 
#!/bin/bash

WSL_IP=192.168.95.100
WIN_IP=192.168.95.101
WSL_BROADCAST=192.168.95.255

WSL_IP_SET_RESULT=$(ip addr show eth0 | grep -sc "$WSL_IP/24" )
if [ $WSL_IP_SET_RESULT == 0 ]; then
ip addr add $WSL_IP/24 broadcast $WSL_BROADCAST dev eth0 label eth0:staticip
echo "set WSL_IP $WSL_IP success "
fi
echo "check and set WSL_IP($WSL_IP) WIN_IP($WIN_IP) success "
EOF

# 2023.4更新:以下内容已移除,WIN_IP的设置放到windows下去执行

#WIN_IP_SET_RESULT=$(/mnt/c/WINDOWS/system32/netsh.exe interface ip show addresses "vEthernet (WSL)" | grep -sc "$WIN_IP" )
#if [ $WIN_IP_SET_RESULT == 0 ]; then
# wudo /mnt/c/WINDOWS/system32/netsh.exe interface ip add address "vEthernet (WSL)" address=$WIN_IP/24
# echo "set WIN_IP $WIN_IP success "
#fi
1
2
3
4
5
6
7
8
9
10
11
# 设置权限
chmod a+x setup-static-ip.sh
# 测试执行
source setup-static-ip.sh
# 验证结果:wsl
ip addr show eth0
# 拷贝到系统路径下
mv setup-static-ip.sh /usr/bin/
# 再次测试
setup-static-ip.sh
echo "setup-static-ip.sh" >> /etc/profile

2 使用Bat启动脚本设置win静态ip

2024.1 更新:使用powershell(ps1)而非cmd(bat)实现

1 新建winip.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 运行 netsh 命令并获取包含 "WSL" 的行
$wslOutput = netsh interface ip show addresses | Select-String -Pattern 'WSL' -AllMatches

# 使用正则表达式提取双引号中间的内容
if ($wslOutput -match '"([^"]+)"') {
$networkAdapterName = $matches[1]
Write-Host "wsl networkAdapter: $networkAdapterName"
} else {
Write-Host "wsl networkAdapter not found !"
return
}
# 检查宿主机有没有我需要的IP
$WinIP = "192.168.95.101"

$ipInfo = netsh interface ip show addresses $networkAdapterName | Select-String $WinIP

if ($ipInfo) {
Write-Host "Windows IP has been set."
} else {
# IP不存在则绑定IP
netsh interface ip add address $networkAdapterName address=$WinIP/24
Write-Host "Set Windows IP success: $WinIP"
}

2 配置开机执行

打开“任务计划程序”,创建任务,重要的配置项如下:

  • 常规-更改用户或组-高级-立即查找-选择“SYSTEM”用户-确定:使用SYSTEM而非当前用户运行就不会有个cmd黑框一闪而过
  • 常规-勾选使用最高权限运行
  • 触发器-新建-启动时
  • 触发器-新建-登陆时-配置:勾选延迟任务时间并设置为1分钟,勾选重复任务间隔并设置为5分钟,持续时间为15分钟:多次触发执行避免因意外执行失败
  • 操作-启动程序-“程序或脚本”设置为 powershell.exe ,添加参数设置为:-NoProfile -ExecutionPolicy Bypass -File "D:\Program1\winip.ps1"

创建完可选择任务右键点击运行,状态会变成“正在运行”,刷新一下即恢复“准备就绪”说明执行完成

3. 验证结果

1
ipconfig

3 配置hosts文件

现在直接在windows配置hosts就行了(wsl默认情况下会复制windows的hosts)

1
2
3
192.168.95.101 my.win
192.168.95.100 my.wsl

4 验证

分别在windows/wsl下ping my.win和my.wsl即可,然后重启,再测试一次,看能否自动设置
my.wsl需启动wsl实例后才会自动配置,才能ping通

1
2
3
ping my.win
ping my.wsl


WSL开发系列-网络篇(wsl固定ip)
https://linshenkx.github.io/wsl-dev-static-ip/
作者
John Doe
发布于
2023年2月11日
许可协议