与 WSL1 翻译内核调用不同,WSL2 完全基于 VM,因此与 HOST 交互时,文件操作效率和网络访问便利性都不及 WSL1,但 VM 内部文件操作效率和内核调用兼容性有了本质提升。此外,计算性能与 WSL1 相当。本文主要介绍一些提高 VM 和 HOST 间操作文件、访问网络便利性的方法。
文件互访
Win10 与 WSL2 的所有文件操作都基于虚拟网络硬盘,速度较慢,尽量在各自系统编辑好后再复制到对方系统。
WSL2 操作 Win10
Windows 文件被挂载到 WSL2 的 /mnt/
目录,直接操作即可。如下命令可在 Windows 桌面创建一个 created_from_wsl
文件夹。
➜ LOGI mkdir /mnt/c/Users/LOGI/Desktop/created_from_wsl
Win10 操作 WSL2
终端登录 WSL2 并 cd 到目标路径,随后执行如下命令,便可通过 Windows 文件管理器打开该地址。
➜ LOGI explorer.exe .
网络互访
在网络上,Win10 是 WSL2 的上级路由,互访需指定目标 IP/域名
并打开目标 防火墙
,涉及第三方时还要做 端口转发
。
WSL2 访问 Win10 本机
以在 WSL2 中使用 Windows 网络代理为例:
第一步,设置代理 允许局域网访问
。该操作背后的细节为,程序监听 Windows 0.0.0.0:1080
并在 Windows 防火墙的 入站规则
中添加一条允许记录。
第二步,在 WSL2 中获取 Windows IP。
➜ LOGI grep -oP '(?<=nameserver ).+' /etc/resolv.conf
172.24.0.1
第三步,通过 IP 使用该代理。
➜ LOGI curl -x 172.24.0.1:1080 google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
由于每次打开 WSL2 都会重新分配虚拟网络,获取 IP 再使用代理将十分繁琐,解决方式是在特定程序,如 git、ssh 等代理配置中填入 Windows 域名
,并通过修改 hosts
动态维护它。
执行以下命令,每次登录 WSL2 都会将 Windows IP 和固定域名绑定,随后便可通过名称 windows
访问 Windows。
➜ LOGI cat >> ~/.profile <<EOF
windows_ip=`grep -oP '(?<=nameserver ).+' /etc/resolv.conf`
if [ "`grep windows /etc/hosts`" ]; then
sed -i "s/.*windows/$windows_ip windows/" /etc/hosts
else
echo $windows_ip windows >> /etc/hosts
fi
EOF
测试连通性。
➜ LOGI source ~/.profile
➜ LOGI curl -x windows:1080 google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
固定 Git 代理配置。
# HTTP 协议
➜ LOGI git config --global http.https://github.com.proxy http://windows:1080
# SSH 协议
➜ LOGI cat >> ~/.ssh/config <<EOF
Host github.com
User git
Hostname github.com
Proxycommand nc -x windows:1080 %h %p
EOF
WSL2 访问 Win10 所在局域网
如目标设备开放了自身的入站防火墙,则 WSL2 可直接通过其 IP 访问。如访问路由器
➜ LOGI curl -i 192.168.0.1/404
HTTP/1.1 302 Moved Temporarily
Content-Type: text/html;charset=UTF-8
Content-Length: 0
Connection: close
Location: http://melogin.cn:80
Cache-control: no-cache
Win10 本机访问 WSL2
对于 WSL2 中监听 0.0.0.0
的程序,Win10 可直接通过 localhost:port
访问。如仅监听 127.0.0.1
,则 WSL2 需转发请求,以下命令可完成该需求。
➜ LOGI cat >> ~/.profile <<EOF
function expose_local()
{
sysctl -w net.ipv4.conf.all.route_localnet=1
iptables -t nat -A PREROUTING -j DNAT --to 127.0.0.1
}
function protect_local()
{
sysctl -w net.ipv4.conf.all.route_localnet=0
iptables -t nat -D PREROUTING 1
}
EOF
➜ LOGI source ~/.profile
➜ LOGI expose_local # 转发
➜ LOGI protect_local# 取消转发
上述设置退出登录后便会失效,如需持久化,则执行以下命令,但更好的做法是直接监听 0.0.0.0
。
➜ LOGI echo 'sysctl -w net.ipv4.conf.all.route_localnet=1' >> /etc/sysctl.conf
➜ LOGI sysctl -p
➜ LOGI iptables -t nat -A PREROUTING -j DNAT --to 127.0.0.1
➜ LOGI service iptables save
Win10 所在局域网设备访问 WSL2
首先需要确保 Windows 可以访问 WSL2,接着在 Windows
中添加 端口转发
和 防火墙入站
规则,将请求转发到 WSL2。以下为 Powershell 命令,需 管理员权限
执行。
# 获取 WSL2 IP
PS C:\WINDOWS\system32> wsl -- hostname -I
172.23.232.213
# Windows 监听 8080,转发到 WSL2 8080
PS C:\WINDOWS\system32> netsh interface portproxy add v4tov4 listenport=8080 connectaddress=172.23.232.213 connectport=8080
# Windows 放行 8080 入站
PS C:\WINDOWS\system32> New-NetFirewallRule -DisplayName "Allow Inbound TCP Port 8080" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8080
Name : {76caa9d2-634a-4489-8f36-6a9ee71c1cd0}
DisplayName : Allow Inbound Port 8080
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Any
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : 已从存储区成功分析规则。 (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
进行完上述配置,便可在局域网其他设备,如手机,通过 Windows IP 访问 WSL2 中的服务。
对应的删除命令为:
# 查看端口转发规则
PS C:\WINDOWS\system32> netsh interface portproxy show v4tov4
侦听 ipv4: 连接到 ipv4:
地址 端口 地址 端口
--------------- ---------- --------------- ----------
* 8080 172.23.232.213 8080
# 删除端口转发规则
PS C:\WINDOWS\system32> netsh interface portproxy delete v4tov4 listenport=8080
# 删除防火墙入站规则
PS C:\WINDOWS\system32> Remove-NetFirewallRule -DisplayName "Allow Inbound TCP Port 8080"
如果经常使用,可将上述命令封装为函数,需要转发某端口时,用 函数名 端口 协议
的方式调用。以下 Powershell 命令向配置文件中写入了函数定义。
PS C:\WINDOWS\system32> @"
function Add-WSLPortProxy (`$Port = '8080', `$Protocol = 'TCP') {
`$wslIP = wsl -- hostname -I
`$wslIP = `$wslIP.Trim()
netsh interface portproxy add v4tov4 listenport=`$Port connectaddress=`$wslIP connectport=`$Port
New-NetFirewallRule -DisplayName "Allow `${Protocol} Inbound Port `${Port}" -Direction Inbound -Action Allow -Protocol `$Protocol -LocalPort `$Port
}
function Remove-WSLPortProxy (`$Port = '8080', `$Protocol = 'TCP') {
netsh interface portproxy delete v4tov4 listenport=`$Port
Remove-NetFirewallRule -DisplayName "Allow `${Protocol} Inbound Port `${Port}"
}
"@ | Out-File -FilePath $PROFILE -Append -Encoding ascii -Force
下面的命令演示了调用方法,需 管理员权限
执行。如忘记函数名,输入 Add-WSL 或 Remove-WSL
后按 Tab 键即可补全。
# 重载配置,如重新打开 Powershell 则自动加载
PS C:\WINDOWS\system32> . $PROFILE
# 无参调用,默认转发 TCP 8080 端口
PS C:\WINDOWS\system32> Add-WSLPortProxy
Name : {8030ce80-7e3d-4b44-bb90-44b211bc434f}
DisplayName : Allow TCP Inbound Port 8080
Description :
DisplayGroup :
Group :
Enabled : True
Profile : Any
Platform : {}
Direction : Inbound
Action : Allow
EdgeTraversalPolicy : Block
LooseSourceMapping : False
LocalOnlyMapping : False
Owner :
PrimaryStatus : OK
Status : 已从存储区成功分析规则。 (65536)
EnforcementStatus : NotApplicable
PolicyStoreSource : PersistentStore
PolicyStoreSourceType : Local
# 无参调用删除函数,默认取消 TCP 8080
PS C:\WINDOWS\system32> Remove-WSLPortProxy
# 指定其他端口,默认 TCP
PS C:\WINDOWS\system32> Add-WSLPortProxy 3306
# 指定端口和协议
PS C:\WINDOWS\system32> Add-WSLPortProxy 3306 UDP
# 根据端口删除,默认 TCP
PS C:\WINDOWS\system32> Remove-WSLPortProxy 3306
# 指定端口和协议删除
PS C:\WINDOWS\system32> Remove-WSLPortProxy 3306 UDP
如有问题请在下方留言,文章转载请注明出处,详细交流请加下方群组!请大佬不要屏蔽文中广告,因为它将帮我分担服务器开支,如果能帮忙点击我将万分感谢。
大佬,如果wsl2里的程序监听是IPv6,例如[::1]。应该怎么转发?
现在可以用桥接模式让 wsl 和 windows 处于同一网段