文章目录
- 方案细节
- 1. 编辑配置文件
- 2. 重启生效
- 3. 问题排查
- 探究一个失败的方案
- 误区一:windows 设置界面配置的全局代理并不能在终端中使用 `curl` 命令时生效
- 误区二:WSL 2 中的流量实际绕过了 Windows 网络堆栈的传输层
- 误区三:代理协议的层级决定处理的范围
使 windows 下的 linux 子系统使用代理的方式,有两种思路:
- linux 系统内配置代理
- 通过配置
http_proxy
、http_proxys
环境变量工作 - 通过
proxychains
等代理工具工作
- 通过配置
- linux 系统不特别配置代理,而镜像复制 windows 的网络环境
本文采用第二种思路作为解决方案:
-
windows 设置系统代理
-
wsl 在
.wslconfig
配置文件中设置为镜像模式[wsl2] autoProxy=true networkingMode=mirrored
如果以上已经解决你的问题,就不需要阅读下面的细节和相关知识了
方案细节
检查
后续命令会用到,使用命令查看
wsl -l -v
1. 编辑配置文件
The wsl.conf file supports four sections:
automount
,network
,interop
, anduser
.
由于 wsl.conf
只支持这四种配置 section, 而 autoproxy
属于 wsl2
section, 这里不适用。尽管wsl.conf
的配置只对当前子系统生效,可以避免影响 windows 上其他已安装的 linux 。所以最终选择使用 .wslconfig
文件。
这个方式的前提是它只适用于 WSL 2
版本, 在 windows teminal 上确认自己的版本是否支持:
wsl -l -v
如果是 wsl 1
版本,可以通过下面的命令升级版本:
wsl --set-version <distro name> 2
默认情况下, .wslconfig
文件并不存在,使用 powshell terminal 创建:
cd ~
ls .wslconfig //如果存在不会报错
new-item -path ./.wslconfig -itemtype file
explorer .
编辑该文件
[wsl2]
autoProxy=true
networkingMode=mirrored
2. 重启生效
在 powershell 关闭 linux 并重启以生效配置:
wsl --shutdown
// 你可以使用下面的命令确认是否还有正在运行的 linux
wsl --list --running
// 启动
wsl -d <distro name>
确认网络 ip 是否和 windows 的代理配置相同, 在 linux terminal 上
$ curl http://httpbin.org/get
它应该返回的是翻墙后的 ip 地址。
3. 问题排查
一: 确认是否之前有其他代理配置干扰
$ echo $http_proxy
$ echo $https_proxy
二: 检查 windows 的代理配置页面是否期望, 快捷键 win+I
探究一个失败的方案
在使用 wsl 镜像模式之前,我尝试过一个方案并且在过去也成功实践,这个方案背后的逻辑:
NAT 网络模式下,直接在 windows 上配置全局HTTP代理, windows里面的 ubuntu无论怎样都得走这条链路
奇怪的是这个方案并没有工作起来,于是我开始探究为什么这个方案为什么会失败?
默认情况下, WSL 使用 NAT 模式上网。这种模式的网络拓扑图:
误区一:windows 设置界面配置的全局代理并不能在终端中使用 curl
命令时生效
这个误区往往会给人带来这样的困惑:在 windows 的同一个终端会话内使用 curl
命令和使用 python shell
产生不同的测试结果, 前者返回的结果没有使用代理,而后者使用了代理。
造成这个结果的原因是:
Windows 的图形界面(即“设置”页面)与命令行环境中的行为可能有所不同。而由于 Python 通过 requests
库或其他网络库自动读取系统的代理设置,而 curl
并不会默认遵循这些系统级的代理设置。Python 中的代理设置通常是通过环境变量(如 HTTP_PROXY
、HTTPS_PROXY
)或库内部的配置来实现的,而 curl
需要显式地配置代理或通过环境变量读取。
要么显示的在会话中设置环境变量,要么这样使用 👇
curl --proxy socks5://127.0.0.1:10808 http://httpbin.org/get
因此通过 curl http://httpbin.org/get
的返回结果来对比是否使用了代理会把你带入沟里!
误区二:WSL 2 中的流量实际绕过了 Windows 网络堆栈的传输层
这个方案实际上是基于前提: WSL 直接使用 Windows 的网络堆栈
这在 WSL 1
中就是这样设计的,因此理论上会继承 Windows 系统配置的代理,包括 SOCKS 代理。因此,WSL 1 中的网络请求可以使用 Windows 配置的代理。但是到了 WSL 2
版本中,它有了自己独有的网络堆栈,不再与 windows 共享,你可以理解为原来一家人走一个门出去,现在分家有了各自的门。
graph LR
subgraph netstack[network stack]
direction TB
app[应用层:HTTP代理]
transfer[传输层: socks代理]
app ~~~ transfer
end
在这种架构下,这个方案的思路就是错误的,失败是必然的。
这就导致了即使你在 windows 中配置系统全局代理,也无法使 WSL 2
里的流量经过在 windows 系统配置的代理
误区三:代理协议的层级决定处理的范围
http 代理属于应用层,且它只处理 TCP 协议数据包,对于 UDP 协议数据包无法处理
The type of packet that is sent differs depending on the implementation. By default Windows
tracert
uses ICMP and both Mac OS X and Linuxtraceroute
use UDP. I don’t have BSD or Solaris machines or any other OS on hand to check but the man page for the Mac OS X version mentions its provenance is BSD 4.3.
用来跟踪路由的命令发的协议包是不一样的,极少使用 TCP, 这也导致当我们的流量无法使用 HTTP 代理,而绕过了代理。