Win10 与 WSL2 间的网络和文件互访

2020-06-02T01:45:00

与 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
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »