Skip to content

从 GFW 到 WSL2:代理架构完全解析 ​

本文系统性地解释「为什么国内访问不了外网」「Clash 如何解决这个问题」以及「WSL2 为何需要特殊配置」,帮你真正理解整个网络代理的工作原理。


一、国内为什么访问不了外网? ​

1.1 正常的网络访问流程 ​

在没有任何干预的情况下,你访问 google.com 的过程是这样的:

你的电脑
  │
  │  ① 问:google.com 是哪个 IP?
  ▼
本地 DNS 服务器
  │
  │  ② 答:142.250.x.x
  ▼
你的电脑
  │
  │  ③ 向 142.250.x.x 发起连接
  ▼
Google 服务器  ✓

1.2 GFW 的拦截方式 ​

GFW(防火长城)在这个流程里设置了两道关卡:

你的电脑
  │
  │  ① 问:google.com 是哪个 IP?
  ▼
┌─────────────────────────────────┐
│           GFW                   │
│  DNS 污染:返回假 IP 或不响应    │  ← 第一道关卡
└─────────────────────────────────┘
  │
  │  ② 答:错误的 IP(或超时)
  ▼
你的电脑
  │
  │  ③ 向错误 IP 发起连接
  ▼
┌─────────────────────────────────┐
│           GFW                   │
│  IP 封锁:直接丢弃数据包         │  ← 第二道关卡
└─────────────────────────────────┘
  │
  ✗  连接失败

两种主要拦截手段

  • DNS 污染:篡改 DNS 查询结果,让你拿到错误的 IP
  • IP 封锁:直接封禁目标服务器的 IP 段,数据包到达 GFW 就被丢弃

二、Clash 如何绕过 GFW? ​

2.1 加密隧道:骗过 GFW 的核心手段 ​

要理解 Clash 怎么工作,先要理解它是怎么「骗过」GFW 的。

GFW 是怎么识别流量的? ​

GFW 不只是封 IP,它还会做深度包检测(DPI),也就是分析你发出的数据包长什么样:

你发出的数据包
  │
  ▼
┌─────────────────────────────────────┐
│              GFW · DPI 引擎          │
│                                     │
│  这是 HTTP 流量吗?  → 可以通过      │
│  这是普通 HTTPS?   → 可以通过      │
│  这是 VPN 特征?    → 封锁!        │
│  这是 Shadowsocks? → 封锁!        │
│  这是随机加密数据?  → 可疑,观察…  │
└─────────────────────────────────────┘

早期的 VPN(如 PPTP、L2TP)有非常明显的协议特征,GFW 一眼就能认出来封掉。

现代代理协议如何伪装 ​

Clash 使用的协议(如 VMess、VLESS、Trojan、Shadowsocks)的核心思路是:让流量看起来像普通的 HTTPS 流量。

以最常见的 Trojan 协议为例:

你的电脑(Clash)                    境外服务器
  │                                      │
  │  ① 和境外服务器建立真正的 TLS 连接   │
  │     (和访问普通 HTTPS 网站完全一样) │
  │ ─────────────────────────────────→  │
  │                                      │
  │  ② 在 TLS 加密隧道里面,发送真实请求 │
  │     "帮我访问 google.com"            │
  │  (GFW 只看到加密数据,看不出内容)  │
  │ ─────────────────────────────────→  │
  │                                      │
  │  ③ 境外服务器解密,访问 Google       │
  │     把结果加密传回来                 │
  │ ←─────────────────────────────────  │

为什么 GFW 看不出来?

  • 外层:标准 TLS 加密,和你访问银行网站、淘宝是同一种协议
  • 内层:真实请求被包裹在 TLS 里,GFW 无法解密
  • 目标 IP:境外服务器的 IP 没有被封锁(机场会定期更换)

GFW 看到的只是:「这台电脑在和某个境外服务器做 HTTPS 通信」,和正常上网行为无异。

流量伪装的完整对比 ​

传统 VPN现代代理协议(Trojan/VMess)
GFW 能识别吗能,有明显特征难以识别,像普通 HTTPS
加密方式自有协议标准 TLS(和银行网站一样)
被封风险高低
速度慢(协议开销大)快

2.2 系统代理的基本原理 ​

理解了加密隧道,再看 Clash 整体的工作流程就清晰了。

Clash 启动后会做两件事:

  1. 接管系统代理:告诉 Windows「所有网络请求都先交给我」
  2. 在境外建立中继:通过加密隧道连接到 GFW 外的代理服务器
你的电脑(浏览器)
  │
  │  ① 发起请求:我要访问 google.com
  ▼
Clash(本地代理,127.0.0.1:7897)
  │
  │  ② 判断规则:google.com → 走代理
  │
  │  ③ 将请求包裹进加密隧道
  ▼
GFW(只看到加密的 HTTPS 流量,放行)
  │
  ▼
境外代理服务器
  │
  │  ④ 解密,代为访问 Google
  ▼
Google 服务器  ✓  结果原路返回

2.3 Fake IP 详解 ​

为什么需要 Fake IP? ​

正常代理还有一个问题:DNS 查询本身也会被 GFW 污染。如果 Clash 等 DNS 查询完成再代理,DNS 这一步就已经失败了。

Fake IP 是 Clash 的解决方案:跳过真实 DNS 查询,直接用假 IP 占位。

Fake IP 工作流程 ​

浏览器输入 google.com
  │
  │  ① DNS 查询:google.com 是哪个 IP?
  ▼
Clash(接管了 DNS)
  │
  │  ② 立刻返回一个假 IP:198.18.0.9
  │     (不做真实 DNS 查询,速度极快)
  ▼
浏览器
  │
  │  ③ 向 198.18.0.9 发起连接
  ▼
Clash(拦截到这个连接)
  │
  │  ④ 认出 198.18.0.9 对应 google.com
  │     自己去查真实 IP(走加密隧道)
  │
  │  ⑤ 通过境外服务器连接真实的 Google
  ▼
Google 服务器  ✓

Fake IP 的核心思想

Fake IP 相当于一个「内部暗号」系统:

  • Clash 给每个域名分配一个假 IP 作为暗号
  • 浏览器拿着暗号来找 Clash
  • Clash 认出暗号,知道你真正要去哪里
  • 整个过程对浏览器完全透明

Fake IP 的优势 ​

对比项传统方式Fake IP
DNS 查询先查询再连接,可能被污染跳过,直接返回假 IP
连接速度多一次 DNS 往返更快
DNS 污染风险有无

三、WSL2 为什么不能像浏览器一样直接用代理? ​

3.1 浏览器 vs WSL2 的本质区别 ​

这是理解整个问题的关键。

浏览器(Chrome)的行为 ​

Chrome 是一个 Windows 原生应用,它懂得读取 Windows 系统代理设置:

Chrome 输入 google.com
  │
  │  读取 Windows 系统代理设置
  │  发现:代理 = 127.0.0.1:7897
  │
  │  直接把「google.com」这个域名交给 Clash
  │  ← 注意:Chrome 自己完全不做 DNS 解析
  ▼
Clash  →  境外服务器  →  Google ✓

Chrome 从不自己做 DNS 解析,域名直接交给 Clash,Fake IP 对它没有任何影响。

WSL2 的行为 ​

WSL2 是一个完整的 Linux 虚拟机,它:

  • 不知道 Windows 系统代理是什么
  • 有自己独立的网络栈
  • 像真正的 Linux 系统一样自己做 DNS 解析
WSL2 中执行 curl google.com
  │
  │  ① Linux 网络栈:先做 DNS 解析
  │     "google.com 是哪个 IP?"
  ▼
Clash 的 DNS(因为 WSL2 网关指向 Clash)
  │
  │  ② 返回 Fake IP:198.18.0.9
  ▼
curl
  │
  │  ③ 自己向 198.18.0.9 发起 TCP 连接
  │     ← 注意:没有经过 Clash 代理!
  ▼
  ✗  失败(198.18.0.9 只是个假 IP,没人响应)

根本原因

  • Chrome:把域名交给代理,代理来处理 DNS → 成功
  • WSL2:自己先做 DNS,拿到 Fake IP,再自己连接 → 失败

WSL2 的问题在于「多走了 DNS 这一步」,而这一步拿到的是假 IP。

3.2 架构对比图 ​

┌─────────────────────────────────────────────────────┐
│                    Windows 主机                       │
│                                                       │
│  ┌──────────┐    系统代理     ┌───────────────────┐  │
│  │  Chrome  │ ─────────────→ │                   │  │
│  └──────────┘                │   Clash Verge     │  │
│                              │   127.0.0.1:7897  │  │
│  ┌──────────────────────┐    │                   │  │
│  │       WSL2           │    └────────┬──────────┘  │
│  │  (独立 Linux 虚拟机)  │             │              │
│  │                      │    加密隧道  │              │
│  │  curl google.com     │             ▼              │
│  │    ↓ 自己做 DNS      │    境外代理服务器           │
│  │    ↓ 拿到假 IP       │             │              │
│  │    ↓ 自己连接 → ✗   │             ▼              │
│  └──────────────────────┘    Google 服务器 ✓        │
└─────────────────────────────────────────────────────┘

四、为什么 socks5h 能解决问题? ​

4.1 三种代理协议的 DNS 处理方式 ​

协议DNS 由谁解析遇到 Fake IP 的结果
http://本地(WSL2 自己)拿到假 IP → 失败 ✗
socks5://本地(WSL2 自己)拿到假 IP → 失败 ✗
socks5h://代理服务器(Clash)Clash 自己查真实 IP → 成功 ✓

h 的含义是 host,即「把主机名(域名)交给代理处理」。

4.2 socks5h 的完整流程 ​

WSL2 中执行 curl --proxy socks5h://127.0.0.1:7897 google.com
  │
  │  ① curl 不做 DNS 解析
  │     直接连接 127.0.0.1:7897(Clash)
  │     告诉 Clash:"我要访问 google.com"
  ▼
Clash(收到域名,而不是假 IP)
  │
  │  ② Clash 自己查 DNS(走加密隧道,不被污染)
  │     得到真实 IP:142.250.x.x
  │
  │  ③ 通过境外服务器连接 Google
  ▼
Google 服务器  ✓

socks5h 让 WSL2 的行为变得和 Chrome 一样

  • Chrome:把域名交给 Clash → Clash 处理 DNS
  • WSL2 + socks5h:把域名交给 Clash → Clash 处理 DNS

两者现在行为完全一致,Fake IP 问题彻底绕开。


五、Clash 在整个架构中的角色 ​

Clash 不只是一个简单的「翻墙工具」,它同时扮演了以下几个角色:

┌─────────────────────────────────────────────────────────┐
│                      Clash Verge                         │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │  DNS 服务器   │  │  代理服务器   │  │  规则引擎      │  │
│  │              │  │              │  │               │  │
│  │ 接管系统 DNS  │  │ 监听 7897 端口│  │ 判断哪些流量  │  │
│  │ 返回 Fake IP  │  │ 接收代理请求  │  │ 走代理/直连   │  │
│  │ 记录域名映射  │  │ 转发到境外    │  │ 国内直连      │  │
│  └──────────────┘  └──────────────┘  │ 国外走代理    │  │
│                                       └───────────────┘  │
│  ┌──────────────────────────────────────────────────┐    │
│  │                  TUN 虚拟网卡                      │    │
│  │  在系统层面拦截所有流量(包括不支持代理的程序)      │    │
│  └──────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

五个核心角色 ​

① DNS 服务器 接管本地 DNS 查询,实现 Fake IP 机制,防止 DNS 污染。

② 代理服务器 监听本地端口(7897),接收来自各程序的代理请求,通过加密隧道转发到境外。

③ 规则引擎 根据规则判断每个请求的处理方式:国内网站直连(不走代理,更快),国外网站走代理。

④ TUN 虚拟网卡(虚拟网卡模式)

TUN 是整个架构里最底层、最强力的机制,值得单独详细说明。

系统代理的局限性

系统代理(① ② ③)依赖程序「主动配合」——程序必须知道系统代理是什么,并且自愿把请求交给 Clash。Chrome 懂这套规则,但很多程序不懂:

不支持系统代理的程序(如某些命令行工具、游戏客户端)
  │
  │  直接发起网络连接,完全不看系统代理设置
  ▼
操作系统网络层
  │
  ▼
GFW  →  ✗ 被拦截

TUN 的解决思路:在更底层拦截

TUN(Network Tunnel)是操作系统提供的一种虚拟网卡机制。Clash 创建一个虚拟网卡,把自己插入到操作系统的网络栈里,在数据包离开电脑之前就拦截它:

任何程序(不管它懂不懂代理)
  │
  │  发起网络请求
  ▼
操作系统网络栈
  │
  │  ← Clash TUN 虚拟网卡在这里拦截
  ▼
┌─────────────────────────────────┐
│         Clash TUN 虚拟网卡       │
│                                 │
│  拦截所有流出的数据包             │
│  交给 Clash 规则引擎判断         │
│  国内 → 放行直连                 │
│  国外 → 加密转发到境外服务器      │
└─────────────────────────────────┘

用一个比喻理解:

TUN 的比喻

系统代理像小区门卫:只拦截主动配合报到的访客(懂代理的程序),翻墙进来的不管。

TUN 虚拟网卡像在小区唯一的出口修了一道闸机:不管你是谁、走哪条路,出小区就必须过闸机,没有例外。

TUN 和系统代理的对比

系统代理TUN 虚拟网卡
拦截方式程序主动配合操作系统层强制拦截
覆盖范围只有懂代理的程序所有程序,无一例外
配置复杂度简单需要管理员权限
典型场景浏览器上网游戏、命令行工具、不支持代理的 App

为什么 TUN 对 WSL2 依然无效?

理论上 TUN 能拦截所有流量,但 WSL2 是一个独立的 Hyper-V 虚拟机,它的网络流量从 Windows 视角来看像是「来自另一台机器的流量」,经由虚拟交换机转发,绕过了 TUN 虚拟网卡的拦截层。这就是即使开了虚拟网卡模式,WSL2 里不设代理仍然访问不了外网的根本原因。

⑤ 系统代理注册 把自己注册为 Windows 系统代理,让 Chrome 等支持系统代理的程序自动走代理。


六、完整架构总览 ​

┌─────────────────────────────────────────────────────────────┐
│                         你的电脑                              │
│                                                               │
│  Windows 应用层                                               │
│  ┌──────────┐  ┌──────────┐  ┌──────────────────────────┐   │
│  │  Chrome  │  │  其他APP  │  │          WSL2            │   │
│  │系统代理  │  │ 系统代理  │  │   独立 Linux 虚拟机       │   │
│  └────┬─────┘  └────┬─────┘  │   curl/git/pip...        │   │
│       │              │        │   设置 socks5h 环境变量   │   │
│       │              │        └───────────┬──────────────┘   │
│       │              │                    │ socks5h           │
│       └──────────────┴────────────────────┘                  │
│                              │                               │
│                              ▼                               │
│               ┌──────────────────────────┐                  │
│               │       Clash Verge        │                  │
│               │     127.0.0.1:7897       │                  │
│               │                          │                  │
│               │  DNS服务器 + 规则引擎     │                  │
│               │  + 代理转发 + TUN网卡    │                  │
│               └─────────────┬────────────┘                  │
│                             │                               │
└─────────────────────────────┼───────────────────────────────┘
                              │ 加密隧道(GFW 看不出来)
                    ┌─────────▼──────────┐
                    │    GFW(防火长城)   │
                    │  看到加密数据,放行  │
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   境外代理服务器     │
                    └─────────┬──────────┘
                              │
                    ┌─────────▼──────────┐
                    │   Google / GitHub  │
                    │   等境外服务器      │
                    └────────────────────┘

七、WSL2 最终配置方案 ​

基于以上理解,WSL2 使用 socks5h 是最合适的方案:

bash
# ~/.bashrc

# Clash Verge 代理配置
export http_proxy="socks5h://127.0.0.1:7897"
export https_proxy="socks5h://127.0.0.1:7897"
export all_proxy="socks5h://127.0.0.1:7897"
bash
# git 单独配置(git 不读取环境变量,需要独立设置)
git config --global http.proxy socks5h://127.0.0.1:7897
git config --global https.proxy socks5h://127.0.0.1:7897

为什么用 socks5h 而不是 http?

  • http://127.0.0.1:7897:WSL2 自己做 DNS → 拿到 Fake IP → 失败
  • socks5h://127.0.0.1:7897:域名交给 Clash 处理 DNS → 拿到真实 IP → 成功

WSL2 镜像网络模式

在 C:\Users\你的用户名\.wslconfig 中配置:

ini
[wsl2]
networkingMode=mirrored

此模式下 WSL2 和 Windows 共享网络,可直接使用 127.0.0.1 访问 Clash,无需查询宿主机 IP。


八、常见问题速查 ​

现象原因解决方案
curl 超时无响应代理端口错误确认 Clash 实际端口(如 7897)
Connection refusedClash 未启动或 Allow LAN 未开检查 Clash 设置
SSL 握手失败Fake IP 导致 DNS 异常改用 socks5h 协议
git 卡住不动git 未单独配置代理git config --global http.proxy socks5h://...
Chrome 正常但 WSL2 不行WSL2 不读系统代理手动设置 socks5h 环境变量

理解了这套架构,遇到任何代理问题都能自行排查。