Appearance
从 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 启动后会做两件事:
- 接管系统代理:告诉 Windows「所有网络请求都先交给我」
- 在境外建立中继:通过加密隧道连接到 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 refused | Clash 未启动或 Allow LAN 未开 | 检查 Clash 设置 |
| SSL 握手失败 | Fake IP 导致 DNS 异常 | 改用 socks5h 协议 |
| git 卡住不动 | git 未单独配置代理 | git config --global http.proxy socks5h://... |
| Chrome 正常但 WSL2 不行 | WSL2 不读系统代理 | 手动设置 socks5h 环境变量 |
理解了这套架构,遇到任何代理问题都能自行排查。
