Windows子系统(WSL)通过桥接网络实现被外部局域网主机直接
实现方法
思路就是将wsl2自建的虚拟NAT网络桥接到windows主机网卡上,主要参考这篇文章
1、开启hyper-v
桥接功能需要windows的hyper-v组件支持,但是win10/11家庭版是不包含hyper-v的,专业版才包含。网上也有文章提到家庭版安装hyper-v的方法,但是我没有测试,以下内容都是在win11专业版上进行的测试,win10专业版应该也是一样的。
首先,进入控制面板—程序—启用或关闭windows功能,勾选hyper-v,确认后重启电脑。
2、桥接网络
WSL2 默认采用了一个 NAT 网络,这对于大多数情况而言都是没有问题的,但是如果想要把 WSL 中的服务直接暴露出来,就不得不考虑做端口转发等问题。以及如果要使用 IPv6,自带的 NAT 方案也不能满足。
因此,这种时候如果能让 WSL2 使用直接接在 NIC 上自然是最好的,可惜 Windows 中没有直接提供这样的配置选项,如果在 Hyper-V 管理器中配置 WSL 网卡为外部网络则会直接报错。
万幸的是,可以使用 PowerShell 直接进行配置,本文则记录使用 PowerShell 让 WSL2 用上桥接网络的方法。
以下内容需要以管理员身份在PowerShell内执行。
一切开始之前首先需要启动 WSL,直接运行 wsl 即可,这样 WSL 的网卡才会被自动创建出来。
重启后首先运行wsl2(这样才能出现WSL的虚拟网卡),以管理员方式打开powershell,执行Get-NetAdapter,可以列出系统所有的网卡,记住想要桥接的网卡名称,比如我想桥接到有线网络其名称为“以太网”。
桥接网卡输入以下代码:
Set-VMSwitch WSL -NetAdapterName 以太网
将wsl虚拟网络和主机有线网络桥接起来。
3、手动修改WSL网络
接下来进入 WSL 配置 IP 地址和网关,假设WSL的有线网络为eth0,网关为 192.168.1.1,IP 设置为 192.168.1.150/24:
ip addr del $(ip addr show eth0 | grep 'inet\b' | awk '{print $2}' | head -n 1) dev eth0
ip addr add 192.168.148.64/24 broadcast 192.168.148.255 dev eth0
ip route add 0.0.0.0/0 via 192.168.148.1 dev eth0
接下来更新名称解析服务器地址,执行 nano /etc/resolv.conf,修改其中内容为 nameserver 192.168.1.1,然后按 Ctrl+X保存退出即可。
4、取消桥接
在windows中管理员方式打开powershell,执行以下指令:
Set-VMSwitch WSL -SwitchType Internal
然后执行 wsl --shutdown 重启wsl,即可恢复原有的虚拟内部网络。
一键脚本
上述步骤太繁琐,为了简单操作,我编写了两个powershell脚本,可以一键执行网络桥接和取消网络桥接
1、wsl linux配置网络脚本
进入wsl,在wsl的home目录下新建一个脚本文件,例如set_eth0.sh,其内容如下:
#!/bin/bash
new_ip=192.168.148.64
brd=192.168.148.255
gateway=192.168.148.1
nameserver=192.168.148.1
net_dev=eth0
echo "password" | sudo -S ip addr del $(ip addr show $net_dev | grep 'inet\b' | awk '{print $2}' | head -n 1) dev $net_dev
sudo ip addr add $new_ip/24 broadcast $brd dev $net_dev
sudo ip route add 0.0.0.0/0 via $gateway dev $net_dev
sudo sed -i "\$c nameserver $nameserver" /etc/resolv.conf
注意将new_ip、brd、nameserver、gateway、net_dev分别修改为实际想要设定的值,另外将echo "password" | 中的password替换为wsl的用户密码。
2、powershell桥接网络脚本
在windows中新建一个ps1文件,例如wsl-bridge-on.ps1(ps1是powershell的脚本,其脚本语言和以前的bat是不一样的)
内容如下:
# 检查并以管理员身份运行PS并带上参数
$currentWi = [Security.Principal.WindowsIdentity]::GetCurrent()
$currentWp = [Security.Principal.WindowsPrincipal]$currentWi
if( -not $currentWp.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
$boundPara = ($MyInvocation.BoundParameters.Keys | foreach{'-{0} {1}' -f $_ ,$MyInvocation.BoundParameters[$_]} ) -join ' '
$currentFile = $MyInvocation.MyCommand.Definition
$fullPara = $boundPara + ' ' + $args -join ' '
Start-Process "$psHome\pwsh.exe" -ArgumentList "$currentFile $fullPara" -verb runas
return
}
#首先随意执行一条wsl指令,确保wsl启动,这样后续步骤才会出现WSL网络
echo "正在检测wsl运行状态..."
wsl --cd ~ -e ls
echo "正在获取网卡信息..."
Get-NetAdapter
echo "`n正在将WSL网络桥接到以太网..."
Set-VMSwitch WSL -NetAdapterName 以太网
echo "`n正在修改WSL网络配置..."
wsl --cd ~ -e sh -c ./set_eth0.sh
echo "`ndone"
pause
最前面那一段是用来检查运行脚本的powershell有没有管理员权限,如果没有,则重新打开一个需要申请管理员权限的powershell;
然后随意执行一条wsl指令,这样如果wsl在后台未启动的情况下会自动启动,确保出现WSL的虚拟网卡;接下来就是网络桥接指令,注意把Set-VMSwitch WSL -NetAdapterName 以太网中的“以太网”改为你自己机器的网卡名称。最后是用到了windows和wsl混合命令,直接调用wsl执行linux脚本修改linux的网络配置。这里linux脚本就是步骤1中新建的set_eth0.sh,保存在home路径下。
3、powershell取消桥接脚本
在windows中新建一个ps1文件,例如wsl-bridge-off.ps1
# 检查并以管理员身份运行PS并带上参数
$currentWi = [Security.Principal.WindowsIdentity]::GetCurrent()
$currentWp = [Security.Principal.WindowsPrincipal]$currentWi
if( -not $currentWp.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
$boundPara = ($MyInvocation.BoundParameters.Keys | foreach{'-{0} {1}' -f $_ ,$MyInvocation.BoundParameters[$_]} ) -join ' '
$currentFile = $MyInvocation.MyCommand.Definition
$fullPara = $boundPara + ' ' + $args -join ' '
Start-Process "$psHome\pwsh.exe" -ArgumentList "$currentFile $fullPara" -verb runas
return
}
echo "正在解除wsl桥接..."
Set-VMSwitch WSL -SwitchType Internal
echo "正在重启wsl"
wsl --shutdown
wsl --cd ~ -e ls
echo "`ndone"
pause
最前面一段同样是检查管理员权限,然后执行解除桥接指令,最后重启wsl,就完成了
4、配置脚本属性
分别右键wsl-bridge-on.ps1和wsl-bridge-off.ps1这两个脚本,在打开方式中选择其它应用,找到powershell安装路径下的可执行文件pwsh.exe,勾选始终使用此应用打开.ps1文件,这样就可以直接双击运行了。不过,默认情况下windows powershell不允许执行自定义脚本,所以需要修改设置打开执行权限。管理员方式打开powershell,执行Set-ExecutionPolicy Unrestricted 或 Set-ExecutionPolicy RemoteSigned ,按y确认即可
5、使用方法
需要桥接wsl网络的时候直接双击运行wsl-bridge-on.ps1,出现申请管理员权限的时候按是确认,然后等待脚本执行完毕即可。取消桥接则运行wsl-bridge-off.ps1,也是同样的流程。