WSL2 想要连上宿主机 Windows 里设置的网络代理端口很是蛋疼。
前置条件
PS C:\Users\overlord> wsl -l -v
NAME STATE VERSION
* Ubuntu-20.04 Running 2
获取 Host 和 WSL 的 ip
首先咱们须要获取 WSL2 的动静 IP,再每次 Windows 零碎重启之后,它会动静给 WSL2 调配一个新 IP。
所以能够写个脚本 displayip.sh,来动静获取。
#!/bin/bash
echo "Host ip: $(cat /etc/resolv.conf | grep nameserver | awk'{ print $2}')"
echo "WSL client ip: $(hostname -I | awk'{print $1}')"
运行可查看以后 Windows host 主机 ip、WSL 的 ip。
🦄 chmod +x displayip.sh
🦄 ./displayip.sh
Host ip: 172.20.96.1
WSL client ip: 172.20.99.149
Windows 应用的代理程序
我用的 Clash for Windows 反对 http 和 socks5 代理。
代理端口为 1081。
谬误尝试
Windows Defender 里新增入站规定
管理员权限 ps 运行:
New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow
会在 Windows Defender 防火墙里减少开启一条入站规定“WSL”。这条规定容许全副接口名为 vEthernet (WSL) ——也就是 WSL2 的入站连贯。
在 WSL 的 bash 里 ping 宿主主机,测试连通:
🦄 ping 172.20.96.1 -c 4
PING 172.20.96.1 (172.20.96.1) 56(84) bytes of data.
64 bytes from 172.20.96.1: icmp_seq=1 ttl=128 time=0.373 ms
64 bytes from 172.20.96.1: icmp_seq=2 ttl=128 time=0.350 ms
64 bytes from 172.20.96.1: icmp_seq=3 ttl=128 time=0.398 ms
64 bytes from 172.20.96.1: icmp_seq=4 ttl=128 time=0.380 ms
--- 172.20.96.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3114ms
rtt min/avg/max/mdev = 0.350/0.375/0.398/0.017 ms
然而此时通过宿主机的 ip 并不能拜访到代理软件应用的 1081 接口。用 telnet 测试接口可得如下后果。
🦄 telnet 172.20.96.1 1081
Trying 172.20.96.1...
对 1081 的连贯申请会始终停留在尝试连贯的步骤上。
入站规定的用途
减少入站规定其实能够用来让 WSL2 子系统拜访 Windows 宿主机起的 http 服务。
例如我用 node 在 Windows 宿主机的 5000 端口起了一个 node 的 server。
PS D:\Codes\nodejs16\tsrctutorial> pnpm preview
> tsrctutorial@0.0.0 preview D:\Codes\nodejs16\tsrctutorial
> vite preview
> Network: http://172.24.0.1:5000/
> Network: http://192.168.56.1:5000/
> Network: http://192.168.3.130:5000/
> Local: http://localhost:5000/
> Network: http://172.20.96.1:5000/
WSL2 内用 telnet 测试的后果就会变成:
🦄 telnet 172.20.96.1 5000
Trying 172.20.96.1...
Connected to 172.20.96.1.
Escape character is '^]'.
还能够用 curl 测试。
🦄 curl http://172.20.96.1:5000
<!DOCTYPE html>
<html lang="en">
...
</html>
从 Windows 宿主机拜访 WSL2 起的服务
新版 WSL2 里零碎曾经映射,间接用 localhost 即可拜访。
比方在 WLS2 里起个简略的 node 服务器,在 Windows 的浏览器中用 localhost:port 即可拜访。
猜测
可能是 Windows Defender 的入站规定只对它意识的连贯协定放行,而 clash 的混合 http 和 socks5 的协定不在它意识的范畴内。
正确计划
配置 Windows Defender
在“高级平安 Windows Defender 防火墙”— 属性,选项卡“专用配置文件”,状态组里“受爱护的网络连接:”左边的“自定义”按钮,关上爱护的网络连接窗口勾销勾选“vEthernet (WSL)”复选框。
不过配置的毛病是每次重启必须重新配置。起因是 vEthernet 这个服务必须每次登录 WSL2 才会呈现,Windows Defender 会默认将其纳入爱护,我还没有找到 Windows Defender 默认不爱护它的办法。
欢送留言交换重启后也能失效的 WSL 和宿主拜访的配置办法。
测试连贯
telnet
🦄 telnet 172.20.96.1 1081
Trying 172.20.96.1...
Connected to 172.20.96.1.
Escape character is '^]'.
curl
🦄 curl -x "socks5://172.20.96.1:1081" https://www.google.com
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="https://www.google.com.hk/url?sa=p&hl=zh-CN&pref=hkredirect&pval=yes&q=https://www.google.com.hk/&ust=1645782940260650&usg=AOvVaw0PyWu1rzhLahRjGxgRdqPH">here</A>.
</BODY></HTML>
应用场景
先配置好 Windows Defender 的高级平安,再把宿主机的代理端口设置为 WSL2 零碎代理,或者 git 的代理。
clash 或者其余的代理程序须要凋谢局域网拜访(Allow LAN)。
WSL2 里设置零碎代理局部,我应用一个 bash 脚本来做这样的配置。
socks5 协定的 proxy.sh 脚本
#!/bin/bash
hostip=$(cat /etc/resolv.conf | grep nameserver | awk '{ print $2}')
wslip=$(hostname -I | awk '{print $1}')
port=1081
PROXY_SOCKS="socks5://${hostip}:${port}"
function display() {echo "Host ip: ${hostip}"
echo "WSL client ip: ${wslip}"
echo "current PROXY: ${PROXY_SOCKS}"
}
function set_proxy() {export http_proxy="${PROXY_SOCKS}"
export https_proxy="${PROXY_SOCKS}"
echo "env http/https proxy set."
}
function unset_proxy() {
unset http_proxy
unset https_proxy
echo "env proxy unset."
}
function set_git_proxy() {git config --global http.proxy "${PROXY_SOCKS}"
git config --global https.proxy "${PROXY_SOCKS}"
echo "git config proxy set."
}
function unset_git_proxy() {
git config --global --unset http.proxy
git config --global --unset https.proxy
echo "git conffig proxy unset."
}
if ["$1" = "display"]; then
display
elif ["$1" = "set"]; then
set_proxy
elif ["$1" = "unset"]; then
unset_proxy
elif ["$1" = "setgit"]; then
set_git_proxy
elif ["$1" = "ungit"]; then
unset_git_proxy
else
echo "incorrect arguments."
fi
第 4 行 port= 你 Windows 代理程序设置的代理端口。
保留后记得 chmod +x proxy.sh 赋予执行权限。
用法
🦄 ./proxy.sh display
Host ip: 172.20.96.1
WSL client ip: 172.20.99.149
current PROXY: socks5://172.20.96.1:1081
🦄 ./proxy.sh set
env http/https proxy set.
🦄 ./proxy.sh unset
env proxy unset.
🦄 ./proxy.sh setgit
git config proxy set.
🦄 ./proxy.sh ungit
git conffig proxy unset.
set 之后能够 curl 或 wget 拜访须要代理连上的地址;setgit 之后拉 github 上连贯不上的包。
参考资料
Windows Defender Firewall blocks access from WSL2 · Issue #4139 · microsoft/WSL
Add “allow” rule to Windows firewall for WSL2 network · Issue #4585 · microsoft/WSL
Protecting X410 Public Access for WSL2 via Windows Defender Firewall
[WSL 2] NIC Bridge mode 🖧 (Has TCP Workaround🔨) · Issue #4150 · microsoft/WSL
WSL2 中拜访宿主机 Windows 的代理 – ZingLix Blog