在上一篇文章《搭建免安装客户端的 IKEv2 隧道,解决 Cursor 地区限制》中,我们介绍了如何使用 IKEv2 三层隧道来绕过 Cursor 等软件的地理位置限制。虽然 IKEv2 方案具有免安装客户端的优势,但三层隧道本身存在一些固有的性能问题。
本文将介绍一种更高效的替代方案:使用 Clash Verge 的 TUN 模式 配合 VLESS 协议,在保持对应用透明的同时,避免三层隧道带来的性能损耗。
三层隧道的性能陷阱
上一篇文章中的 IKEv2 + VLESS/WebSocket 架构存在三个主要的性能问题:
- TCP over TCP:应用层 TCP 被封装在隧道的 TCP(WebSocket)中传输,两层 TCP 状态机相互干扰
- Head-of-Line Blocking:多个应用连接复用同一条隧道,一个连接的丢包会阻塞所有连接
- 长连接 QoS 限制:单一长连接容易被网络中间设备限速
TCP over TCP 问题
在上一篇文章的架构中,我们使用 VLESS over WebSocket over TLS 来封装 IKEv2 的 UDP 流量。虽然 IKEv2 本身使用 UDP,但当上层应用使用 TCP 协议时,整个数据链路会出现 TCP over TCP 的情况:
1 2 3 4 5 6 7
| 应用层 TCP 连接(如 Cursor 的 HTTP/2) ↓ 封装 IKEv2 隧道(ESP over UDP) ↓ 封装 VLESS over WebSocket over TLS(底层是 TCP) ↓ 物理网络传输
|
这种嵌套的 TCP 连接会导致严重的性能问题:
重传风暴:当底层网络出现丢包时,外层 TCP(WebSocket 连接)和内层 TCP(应用连接)都会触发重传机制。外层 TCP 重传的数据包中可能包含内层 TCP 已经成功传输的数据,导致大量无效重传。
拥塞控制冲突:两层 TCP 各自维护独立的拥塞窗口和 RTT 估计。当网络状况变化时,两层拥塞控制算法可能做出相互矛盾的决策,导致带宽利用率下降。
延迟叠加:每层 TCP 都有自己的确认机制和超时重传,延迟会层层叠加。
Head-of-Line Blocking(队头阻塞)问题
当多个上层连接复用同一条隧道时,会出现 Head-of-Line Blocking 问题:
1 2 3 4 5 6 7
| 连接 A 的数据包: [A1] [A2] [A3] 连接 B 的数据包: [B1] [B2] 连接 C 的数据包: [C1] ↓ 复用到同一条隧道 ↓ 隧道数据流: [A1] [B1] [A2] [C1] [A3] [B2]
|
如果隧道中的某个数据包(比如 A2)丢失,整个隧道的 TCP 连接会暂停等待重传。即使 B1、C1、A3、B2 这些数据包已经到达,也无法被上层应用读取,因为 TCP 保证有序交付。这意味着:
- 连接 B 和 C 被连接 A 的丢包所阻塞
- 即使连接 B 和 C 的数据完整无损,也必须等待
在高延迟、高丢包的跨国网络环境下,这个问题尤为严重。
长连接的 QoS 限制问题
网络中的 middlebox(如运营商的流量管理设备、防火墙等)通常会对长时间存在的连接或传输大量数据的连接进行 QoS(Quality of Service)限速:
连接时长检测:某些 middlebox 会标记存活时间超过阈值(如 30 分钟)的连接,并降低其优先级或限制带宽。
流量特征识别:持续高带宽的单一连接容易被识别为”异常流量”,触发限速策略。
公平性调度:为了保证网络公平性,运营商可能会限制单个连接占用过多带宽。
三层隧道通常维护一条或少数几条长连接来承载所有流量,这使得它们特别容易触发这些限制。
Clash Verge TUN 模式的设计原理
Clash Verge 的 TUN 模式提供了一种巧妙的解决方案,它在保持对应用透明的同时,避免了上述性能问题。
什么是 TUN 模式?
TUN(网络隧道)是操作系统提供的虚拟网络设备。当启用 TUN 模式时:
- Clash 创建一个虚拟网卡(如
utun 或 tun0)
- 修改系统路由表,将流量导向这个虚拟网卡
- 所有经过虚拟网卡的流量都会被 Clash 捕获和处理
这意味着任何应用的网络流量都会被透明代理,无需配置浏览器代理或应用级代理设置。
关键设计:用户态协议栈
Clash 的 TUN 模式使用了 用户态 TCP/IP 协议栈(如 gVisor 的 netstack),这是避免 TCP over TCP 问题的关键:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 传统三层隧道: ┌─────────────────────────────────────────┐ │ 应用 TCP 连接 │ │ ↓ │ │ 内核 TCP/IP 协议栈 │ │ ↓ │ │ 隧道封装(保留完整 TCP 头) │ │ ↓ │ │ 隧道 TCP 连接 │ │ ↓ │ │ 内核 TCP/IP 协议栈 │ └─────────────────────────────────────────┘
Clash TUN 模式: ┌─────────────────────────────────────────┐ │ 应用 TCP 连接 │ │ ↓ │ │ TUN 虚拟网卡捕获 IP 包 │ │ ↓ │ │ 用户态协议栈解析,提取 TCP 载荷 │ │ ↓ │ │ 建立新的代理连接(VLESS/WebSocket) │ │ ↓ │ │ 只传输应用层数据,不传输 TCP 头 │ └─────────────────────────────────────────┘
|
一对一连接映射
Clash TUN 模式的另一个关键设计是上层连接与底层隧道连接的一对一映射:
- 每个应用的 TCP 连接对应一个独立的代理连接
- 每个应用的 UDP 会话对应一个独立的代理连接
这种设计带来了显著的优势:
消除 Head-of-Line Blocking:连接 A 的丢包不会影响连接 B 和 C,因为它们使用独立的底层连接。
避免 TCP over TCP:用户态协议栈在本地终结了应用的 TCP 连接,提取出应用层数据后,通过一个新的 TCP 连接(VLESS/WebSocket)传输。虽然底层仍然是 TCP,但应用的 TCP 状态机(序列号、确认、重传)不会被封装传输,因此不存在两层 TCP 状态机相互干扰的问题。
规避长连接限制:每个应用连接独立存在,连接的生命周期与应用行为一致,不会出现单一超长连接。
更好的拥塞控制:终结应用层 TCP 的另一个重要好处是将长跨国链路拆分成多段较短的链路。在三层隧道中,应用的 TCP 拥塞控制需要感知从客户端到美国服务器再到目标网站的整条链路,RTT 很长,带宽利用率低。而在 Clash TUN 模式下,由于 Clash 终结了应用层的 TCP 连接,每段链路的 RTT 都较短,拥塞控制可以更快地收敛到最优带宽,整体吞吐量更高。
对应用透明
与传统的 HTTP/SOCKS 代理不同,TUN 模式对应用完全透明:
| 特性 |
HTTP/SOCKS 代理 |
TUN 模式 |
| 需要应用支持 |
是 |
否 |
| 需要配置代理 |
是 |
否 |
| 支持 TCP |
是 |
是 |
| 支持 UDP |
部分(SOCKS5) |
是 |
| 支持 ICMP |
否 |
是 |
| 支持 HTTP/2 |
取决于应用 |
是 |
这意味着各种难以配置代理的应用都可以正常工作:
- Cursor / Claude Code:这些 AI 编程工具使用 HTTP/2 长连接,且没有提供代理配置选项
- Docker Container:使用 Dev Container 模式开发时,容器需要从 GitHub、npm、PyPI 等源下载依赖,配置代理非常麻烦
- 命令行工具:
git clone、npm install、pip install 等命令行工具,虽然可以通过环境变量配置代理,但每个工具的配置方式不同,且容易遗漏
TUN 模式在系统网络层工作,对所有应用透明,无需逐个配置。
DNS 的工作原理
DNS 处理是 Clash TUN 模式的另一个关键组件。
为什么需要特殊处理 DNS?
在传统的 HTTP/SOCKS 代理中,应用通常会先进行 DNS 解析,然后将解析得到的 IP 地址发送给代理服务器。这会导致两个问题:
- DNS 泄露:DNS 查询直接发送到本地 DNS 服务器(通常是运营商的),暴露了你要访问的域名
- DNS 污染:某些域名会被返回错误的 IP 地址,导致无法访问
Fake IP 模式
Clash 的 TUN 模式默认使用 Fake IP 模式来解决这些问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 1. 应用请求解析 google.com ↓ 2. 系统 DNS 请求被 Clash 劫持 ↓ 3. Clash 返回一个假 IP(如 198.18.0.5) 并记录映射关系:198.18.0.5 → google.com ↓ 4. 应用使用 198.18.0.5 发起 TCP 连接 ↓ 5. 连接被 TUN 虚拟网卡捕获 ↓ 6. Clash 根据目标 IP 198.18.0.5 反查出域名 google.com ↓ 7. Clash 通过代理服务器连接 google.com (真正的 DNS 解析在代理服务器端进行)
|
这种设计的优势:
- 零 DNS 泄露:本地完全不进行真实的 DNS 解析
- 绕过 DNS 污染:DNS 解析在代理服务器所在的网络环境进行
- 支持基于域名的分流:即使应用只发送 IP,Clash 也能知道原始域名
- 减少延迟:省去了本地 DNS 解析的往返时间
DNS 劫持
为了让 Fake IP 模式工作,Clash 需要劫持系统的 DNS 请求。在 TUN 模式下,这通过以下方式实现:
- TUN 虚拟网卡接管所有网络流量
- 发往任何 DNS 服务器(端口 53)的请求都会被 Clash 拦截
- Clash 内置的 DNS 服务器处理这些请求
这就是为什么启用 TUN 模式后,无论系统 DNS 设置为什么,DNS 请求都会被 Clash 处理。
架构设计
延续《巧用香港中转,搭建丝滑稳定的中美三层隧道》的思路,我们同样采用三级跳架构,但全程使用 VLESS 协议:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| +---------------------------+ | Your Device | | (Clash Verge TUN Mode) | +---------------------------+ | VLESS over WS+TLS (TCP 443) | v +---------------------------+ | China Server | | (cn-gw.01.me) | |---------------------------| | Xray: | | In: VLESS/WS/TLS | | Out: VLESS/WS/TLS | +---------------------------+ | VLESS over WS+TLS (TCP 443) | v +---------------------------+ | Hong Kong Server | | (hk.01.me) | |---------------------------| | Xray: | | In: VLESS/WS/TLS | | Out: VLESS/WS/TLS | +---------------------------+ | VLESS over WS+TLS (TCP 443) | v +---------------------------+ | US Server | | (us-west.01.me) | |---------------------------| | Xray: | | In: VLESS/WS/TLS | | Out: freedom | +---------------------------+ | v <-- Internet -->
|
为什么使用三级跳?
与 IKEv2 方案相同,三级跳架构的优势在于:
- 国内 -> 香港:利用云服务商的优化线路,延迟低、稳定性高
- 香港 -> 美国:香港作为亚洲网络枢纽,拥有优质的国际出口
- 美国出口:最终 IP 位于美国,绕过地理位置限制
为什么全程使用 VLESS?
- 协议统一:简化配置和维护
- 性能优秀:VLESS 是轻量级协议,开销小
- WebSocket 传输:伪装成普通 HTTPS 流量,穿透性强
- TLS 加密:端到端加密,安全性高
准备工作
1. 服务器要求
- 国内服务器(本文以
cn-gw.01.me 为例)
- 香港服务器(本文以
hk.01.me 为例)
- 美国服务器(本文以
us-west.01.me 为例)
2. 域名和证书
为每台服务器准备域名并申请 SSL 证书:
1 2 3 4 5 6 7 8 9 10 11 12
| sudo apt update sudo apt install -y certbot
sudo certbot certonly --standalone -d cn-gw.01.me --non-interactive --agree-tos -m [email protected]
sudo certbot certonly --standalone -d hk.01.me --non-interactive --agree-tos -m [email protected]
sudo certbot certonly --standalone -d us-west.01.me --non-interactive --agree-tos -m [email protected]
|
3. 生成 UUID
为每一跳的 VLESS 连接生成 UUID:
1 2 3 4 5 6 7
| export UUID_CLIENT_CN=$(uuidgen) export UUID_CN_HK=$(uuidgen) export UUID_HK_US=$(uuidgen)
echo "客户端 -> 国内: ${UUID_CLIENT_CN}" echo "国内 -> 香港: ${UUID_CN_HK}" echo "香港 -> 美国: ${UUID_HK_US}"
|
第一步:配置美国出口服务器
1.1 安装 Xray
1 2 3 4 5 6 7 8 9 10 11 12
| sudo apt update sudo apt install -y curl
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
sudo tee -a /etc/sysctl.conf > /dev/null << EOF net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr EOF sudo sysctl -p
|
1.2 配置 Xray
创建 /usr/local/etc/xray/config.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| sudo tee /usr/local/etc/xray/config.json > /dev/null << EOF { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 443, "protocol": "vless", "settings": { "clients": [ { "id": "${UUID_HK_US}", "level": 0 } ], "decryption": "none" }, "streamSettings": { "network": "ws", "security": "tls", "tlsSettings": { "certificates": [ { "certificateFile": "/etc/letsencrypt/live/us-west.01.me/fullchain.pem", "keyFile": "/etc/letsencrypt/live/us-west.01.me/privkey.pem" } ] }, "wsSettings": { "path": "/wss_us" } } } ], "outbounds": [ { "protocol": "freedom", "tag": "direct" } ] } EOF
|
1.3 启动服务
1 2
| sudo systemctl enable --now xray sudo systemctl status xray
|
第二步:配置香港中转服务器
2.1 安装 Xray
1 2 3 4 5 6 7 8 9
| sudo apt update bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
sudo tee -a /etc/sysctl.conf > /dev/null << EOF net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr EOF sudo sysctl -p
|
2.2 配置 Xray
创建 /usr/local/etc/xray/config.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| sudo tee /usr/local/etc/xray/config.json > /dev/null << EOF { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 443, "protocol": "vless", "settings": { "clients": [ { "id": "${UUID_CN_HK}", "level": 0 } ], "decryption": "none" }, "streamSettings": { "network": "ws", "security": "tls", "tlsSettings": { "certificates": [ { "certificateFile": "/etc/letsencrypt/live/hk.01.me/fullchain.pem", "keyFile": "/etc/letsencrypt/live/hk.01.me/privkey.pem" } ] }, "wsSettings": { "path": "/wss_hk" } } } ], "outbounds": [ { "tag": "proxy-us", "protocol": "vless", "settings": { "vnext": [ { "address": "us-west.01.me", "port": 443, "users": [ { "id": "${UUID_HK_US}", "encryption": "none" } ] } ] }, "streamSettings": { "network": "ws", "security": "tls", "wsSettings": { "path": "/wss_us" } } } ], "routing": { "rules": [ { "type": "field", "network": "tcp,udp", "outboundTag": "proxy-us" } ] } } EOF
|
2.3 启动服务
1 2
| sudo systemctl enable --now xray sudo systemctl status xray
|
第三步:配置国内入口服务器
3.1 安装 Xray
1 2 3 4 5 6 7 8 9
| sudo apt update bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
sudo tee -a /etc/sysctl.conf > /dev/null << EOF net.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr EOF sudo sysctl -p
|
3.2 配置 Xray
创建 /usr/local/etc/xray/config.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| sudo tee /usr/local/etc/xray/config.json > /dev/null << EOF { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 443, "protocol": "vless", "settings": { "clients": [ { "id": "${UUID_CLIENT_CN}", "level": 0 } ], "decryption": "none" }, "streamSettings": { "network": "ws", "security": "tls", "tlsSettings": { "certificates": [ { "certificateFile": "/etc/letsencrypt/live/cn-gw.01.me/fullchain.pem", "keyFile": "/etc/letsencrypt/live/cn-gw.01.me/privkey.pem" } ] }, "wsSettings": { "path": "/wss_cn" } } } ], "outbounds": [ { "tag": "proxy-hk", "protocol": "vless", "settings": { "vnext": [ { "address": "hk.01.me", "port": 443, "users": [ { "id": "${UUID_CN_HK}", "encryption": "none" } ] } ] }, "streamSettings": { "network": "ws", "security": "tls", "wsSettings": { "path": "/wss_hk" } } } ], "routing": { "rules": [ { "type": "field", "network": "tcp,udp", "outboundTag": "proxy-hk" } ] } } EOF
|
3.3 启动服务
1 2
| sudo systemctl enable --now xray sudo systemctl status xray
|
第四步:配置 Clash Verge 客户端
4.1 安装 Clash Verge
从 Clash Verge Rev 下载适合你操作系统的版本并安装。
4.2 创建配置文件
Clash Verge 的配置非常简洁,只需要定义代理服务器和规则即可,TUN 模式和 DNS 等设置可以在 GUI 中开启,可以不写入配置文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| proxies: - name: "xray-cn-hk-us" type: vless server: cn-gw.01.me port: 443 uuid: xxx tls: true udp: true network: ws ws-opts: path: /wss_cn
proxy-groups: - name: Auto type: select proxies: - "xray-cn-hk-us"
rules: - MATCH,Auto
|
配置说明:
- type: vless:使用 VLESS 协议
- tls: true:启用 TLS 加密
- udp: true:支持 UDP 转发(DNS、QUIC 等需要)
- network: ws:使用 WebSocket 传输
- rules: MATCH,Auto:所有流量都走代理
如果需要国内直连,可以添加分流规则:
1 2 3
| rules: - GEOIP,CN,DIRECT - MATCH,Auto
|
4.3 启用 TUN 模式
- 打开 Clash Verge
- 导入上述配置文件
- 在设置中启用 TUN 模式(Clash Verge 会自动配置 DNS 劫持和 Fake IP)
- macOS/Linux 用户需要授予管理员权限
- Windows 用户需要以管理员身份运行
启用 TUN 模式后,Clash Verge 会自动:
- 创建 TUN 虚拟网卡
- 配置系统路由表
- 启用 DNS 劫持和 Fake IP 模式
验证与测试
1 2 3 4 5
| curl ifconfig.me
curl -I --http2 https://api.anthropic.com
|
与 IKEv2 方案的对比
| 特性 |
IKEv2 + VLESS/WS 隧道 |
Clash Verge TUN + VLESS |
| 安装客户端 |
不需要 |
需要 |
| TCP over TCP |
存在(应用TCP经IKEv2再经WebSocket) |
不存在(用户态协议栈终结应用TCP) |
| HOL Blocking |
存在(多连接复用同一隧道) |
不存在(一对一连接映射) |
| 长连接限制 |
容易触发(单一长连接) |
不易触发(独立短连接) |
| 拥塞控制 |
端到端长链路,RTT 长 |
分段短链路,RTT 短,带宽高 |
| 支持 HTTP/2 |
是 |
是 |
| 支持 UDP |
是 |
是 |
| 对应用透明 |
是 |
是 |
| 分流规则 |
不支持 |
支持 |
| 适用场景 |
免安装客户端 |
高性能 |
总结
Clash Verge 的 TUN 模式 + VLESS 方案,通过用户态协议栈和一对一连接映射的设计,巧妙地避免了传统三层隧道的 TCP over TCP 和 Head-of-Line Blocking 问题。更重要的是,终结应用层 TCP 将长跨国链路拆分成多段较短的链路,每段链路独立进行拥塞控制,RTT 更短,带宽利用率更高。同时,独立的短连接也不容易触发网络中间设备的 QoS 限制。
相比 IKEv2 方案,这种方案需要安装客户端,但换来了更好的性能和灵活的分流规则支持。对于需要高性能代理的开发者(特别是使用 Cursor 等工具的用户),这是一个值得考虑的选择。
两种方案各有优劣:
- IKEv2:适合不想安装额外软件的场景
- Clash Verge TUN:适合追求性能、需要分流规则的场景
根据你的实际需求选择合适的方案即可。