Files
pangolin/docs/vpn-test-plan.md
wangjia 98ba2b411e test: VPN 黑盒测试工具改用 Python(零依赖)+ HTML 报告 + 国内外站点矩阵
- scripts/vpn_test.py:替换 vpn_test.sh。纯标准库(socket/ssl/urllib),覆盖国内外
  常见站点矩阵(google/youtube/github/x/fb/ig/wiki/cloudflare/openai/reddit;
  百度/腾讯/淘宝/京东/B站/微博/网易/知乎/阿里云),测连通+延迟+TTFB+DNS+出口IP+吞吐,
  本机连通性(tun/系统扩展),生成自包含 HTML 报告(-o)。
- 延迟标准 = TLS 握手耗时(ssl 握手,纯链路往返),报告里标注 "TTL=按 TLS 计算、非 IP TTL";
  TTFB 作参考。禁用 ping/tcp_connect(经 TUN 本地应答失真)。
- 删除 scripts/vpn_test.sh;文档引用同步更新为 .py。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JEHzjEcFzvGwgbxT6Wbt6c
2026-06-22 09:43:46 +08:00

173 lines
9.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pangolin VPN 测试方案 + 报告
> 两个方向:**黑盒**(用户视角,只看输入→输出)+ **白盒**(利用我们对客户端/节点/sing-box
> 的完全可见性,拆链路、看协议、做稳定性)。日期 2026-06-22。配套:`scripts/vpn_test.py`、
> 调研见 `docs/vpn-testing-research.md`。
---
## 一、测试方向总览
| | 黑盒 | 白盒 |
|---|---|---|
| 视角 | 用户视角,不看内部 | 工程视角,看内部链路/协议/状态 |
| 目的 | 能不能用、快不快(可用性 + 体验) | 慢在哪、走什么协议、稳不稳(定位 + 稳定性) |
| 数据源 | `curl` / `ping` 黑盒探测 | sing-box Clash API、libbox 命令服务、curl 五段拆解、节点侧探测、长跑监控 |
| 工具 | `scripts/vpn_test.py`(已实现) | 待实现:`scripts/vpn_whitebox.sh` + 稳定性长跑 |
---
## 二、黑盒测试方案
**对象:国内外常用站点矩阵**,开/关分流各测一遍,多时段(白天 / 晚高峰 20:0024:00)。
### 指标
- **连通性**:HTTP 状态码(能否访问)
- **延迟**:**TLS 握手时间(`curl time_appconnect`)= 统一延迟口径**;TTFB(`time_starttransfer`)作参考。见下方「延迟口径定义」。
- **下载速度**:固定大小下载 `speed_download`
- **上传速度**:POST 固定大小 `speed_upload`(待补)
- **DNS 解析时间**:`curl time_namelookup`
- **出口 IP**:是否 = 节点(走隧道)/ 本地(直连)
### 延迟口径定义(统一标准 ⚠️ 必读)
> **本项目所有"延迟"一律指 TLS 握手时间(`time_appconnect`);TTFB 仅作参考。
> 严禁用 `ping` 或 `tcp_connect` 当延迟** —— 经 TUN 代理时它们被隧道本地协议栈
> 就地应答(几 ms 的假象),不反映真实到目标的 RTT。
curl 各时间点都是**从请求开始累计**(非各段独立):
```
开始 → DNS解析 → TCP连接 → [TLS握手完成] → 发请求 → [收到首字节=TTFB] → 传输完 → 总时长
namelookup connect time_appconnect time_starttransfer time_total
```
| | **TLS 握手(`time_appconnect`)= 延迟口径** | **TTFB(`time_starttransfer`)= 参考** |
|---|---|---|
| 测到哪 | TLS/REALITY 握手协商**完成** | 收到响应的**第一个字节** |
| 含义 | TCP 连接 + TLS 协商往返;握手时服务器只做加密协商、**不碰业务逻辑** → **纯网络链路往返**(client→隧道→节点→目标 的 RTT × 握手轮数) | TLS 握手 + 发请求 + **目标服务器后端处理** + 回首字节 |
| 比对方多 | — | 比 TLS 握手多 **≈1 个 RTT(请求-响应)+ 目标站后端处理时间** |
| 受谁影响 | 只受**网络链路**影响 → 跨站可比、稳定 | 网络 **+ 目标站后端快慢/CDN** → 含站点自身因素 |
| 为何选它 | 不被目标后端污染,横向比较公平,衡量"我们隧道有多快"最干净 | 反映"打开体感",但混入站点因素,不当基准 |
**实测印证**(节点在洛杉矶):`google` TLS握手 424ms、TTFB 640ms,差 ~216ms ≈ 一个
中国→LA→google 往返(generate_204 后端处理≈0)。换 github 这类后端重的站,TTFB 会被
明显拉大,而 TLS 握手仍稳定反映链路。
**判定参考**(单程经隧道到国外):TLS 握手 <500ms 优 / 5001000ms 偏高 / >1000ms 差。
**真实到节点的直连 RTT**:须在 **VPN 全关后 `ping` 节点**测(开着 TUN ping 是本地假象)。
> 注:TLS 1.3 握手 1-RTT、TLS 1.2 为 2-RTT,故 TLS 握手 ≈ 链路 RTT × 握手轮数;同隧道内横向对比目标站公平。
### 站点矩阵
- **国外(应经隧道)**:google、youtube、github、cloudflare(speed.cloudflare.com)、netflix、openai
- **国内(开分流应直连)**:baidu、qq、bilibili、aliyun/清华镜像、taobao
- **测速点**:Cloudflare(国外)、清华/阿里镜像(国内,用 `-r 0-N` range 取固定大小)
### 方法
-**裸连基线**(不开 VPN 跑一遍存档)→ 再开 VPN 对比衰减。
- 每站取 中位数(多次),记录时段。
- 一条命令产报告:`vpn_test.py`(现覆盖连通/出口/DNS/可达/延迟/下载/IPv6;**待补:上传、ping TTL、站点矩阵扩展、多时段 cron**)。
---
## 三、白盒测试方案(重点,更细)
我们同时掌握**客户端(libbox 命令服务)+ 节点(sing-box Clash API :19090/:19091)+ 配置**,
可做黑盒做不到的链路拆解。
### 3.1 链路五段拆解(每个请求耗时花在哪)
`curl -w` 拆解一次请求的五个阶段,定位瓶颈在接入段还是出海段:
| 阶段 | curl 字段 | 含义 |
|---|---|---|
| DNS 解析 | `time_namelookup` | 域名→IP |
| TCP 连接 | `time_connect` | 到隧道/目标的 TCP 握手 |
| TLS 握手 | `time_appconnect` | TLS/REALITY 握手完成 |
| 首字节 TTFB | `time_starttransfer` | 服务器开始回数据(含出海往返) |
| 总时长 | `time_total` | 整体 |
→ TTFB 高 = 出海段慢;connect 高 = 接入段/节点慢;namelookup 高 = DNS 慢。
### 3.2 协议与出站选择
- 当前激活出站:`reality-out`(VLESS/REALITY,TCP 443)还是 `hy2-out`(Hysteria2,UDP 443)。
- `urltest`(auto)各成员探测延迟(决定选谁)。
- **数据源**:sing-box Clash API `GET /proxies`(看 `auto` 组的 `now` 与各成员 `history` 延迟);
或客户端 libbox 命令服务的 group/outbound 状态。
### 3.3 分段 RTT(定位瓶颈)
- **接入段**:客户端 → 节点 REALITY 端口 TCP RTT(`curl time_connect``节点:443`)。
- **出海段**:在**节点上**直接 `ping`/`curl` 目标站(节点 → 目标 RTT)。
- 对比:接入段快 + 出海段慢 → 节点出海链路是瓶颈;反之亦然。
### 3.4 流量与连接(实时内部状态)
- **Clash API `GET /connections`**:活跃连接列表,每连接的 目标 / 上下行字节 / 走哪个出站 / 命中哪条规则 / 建连时长 → 看分流是否如预期(国内直连、国外走代理)。
- **Clash API `GET /traffic`(SSE)**:实时上下行速率。
- **客户端 libbox**:`writeConnectionEvents` / `writeGroups` / 流量统计(stats EventChannel)。
### 3.5 sing-box 内部决策日志(debug)
- 路由命中:`router: match ... => route(outbound)` → 验证分流规则。
- DNS:`dns: exchange/exchanged ...` → 验证 hijack-dns + 解析路径。
- 连接生命周期:建连/关闭/错误。
- **方法**:配置 `log.level=debug` + `log.output` 落盘读(排障期已用过)。
### 3.6 路径 MTU / 分片
- `ping -D -s <size>` 二分探测路径 MTU,评估 TUN `mtu 9000` 是否导致分片/卡顿
(调研:运营商对大包敏感,业界常 clamp 到 1350)。
### 3.7 节点侧资源(瓶颈定位)
- 节点 CPU/内存/带宽(单核 512MB 是硬约束)、sing-box 进程占用、网卡流量。
- agent / 控制面健康。
### 3.8 稳定性测试(白盒重点)
- **长跑**:cron 每 15 分钟探测(出口 IP + 可达 + 延迟 + 丢包),持续数小时~数天,出趋势曲线。
- **掉线 / 重连**:监测 `NEVPNStatus` 变化,记掉线次数、自动重连耗时。
- **Kill switch**:强杀扩展进程 / 断节点,验证 `strict_route` 把流量掐断(不裸奔),恢复后能重连。
- **GFW 存活**:多日连续可达性;监测**三元组封锁特征**(突然全断 + 120–180s 后恢复);
REALITY 端口被动探测(用普通 TLS 客户端连 :443,应表现得像伪装站 www.apple.com)。
- **热重载**:节点 agent `SIGHUP` 重载 sing-box 后,客户端是否断流 / 平滑。
- **协议切换**:reality-out 不可用时是否切到 hy2-out(urltest 容灾)。
---
## 四、当前测试报告(2026-06-22,初轮)
### 4.1 黑盒(cara,macOS 15.3.2 Intel,白天)
`scripts/vpn_test.py` 全量:**15 PASS / 0 WARN / 0 FAIL**
- 连通性:扩展 `activated enabled`、tun `172.19.0.1`
- 出口 IP:`103.119.13.48`(= 节点,确实走隧道)✅
- DNS:github/google 解析+连通正常 ✅(服务端 `hijack-dns` 已生效)
- 国外可达:google/youtube/github/gstatic HTTP 200/204 ✅
- 国内可达:baidu/qq ✅
- 延迟:**真实 RTT 看 TLS 握手 / TTFB**。实测国外 TLS 握手 **~420490ms**、TTFB ~600715ms
(节点在洛杉矶,中国→LA→目标多次往返,符合预期)。
- IPv6:无泄漏 ✅
> ⚠️ **延迟测量教训(重要)**:经 TUN 代理时,`ping` 和 `curl time_connect` 会被隧道的
> 本地协议栈**就地应答**(0.3ms / 2-4ms 的假象),**不反映真实到目标的 RTT**。初轮误把
> `time_connect` 当延迟(2-4ms),实为本地值。真实延迟必须看 **TLS 握手(`time_appconnect`)**
> 或 **TTFB(`time_starttransfer`)**,或在 **VPN 全关后 ping 节点**测直连 RTT。`vpn_test.py`
> 已据此修正。
### 4.2 吞吐对比(关键)
| 路径 | 速度 | 说明 |
|---|---|---|
| **国外(经隧道)** Cloudflare 10MB | **~1017 Mbps**(多次波动:7.66 / 10.6 / 17.4) | 走 REALITY→节点→出海 |
| **国内(直连)** 清华镜像 10MB | **74.28 Mbps** | geoip-cn 命中 → 直连,不经隧道 |
| 国内 阿里云镜像 | 未测到(URL 失效) | 待换有效测速 URL |
**结论:**
1. **分流生效**:国内直连(74 Mbps)远快于国外经隧道(~10-17),说明 geoip-cn 直连正常。
2. **瓶颈在出海段**:国外吞吐受限于隧道——单核 512MB 联调节点 + 出海带宽 + 可能晚高峰。不是客户端/隧道软件问题。
3. **波动大**(7.66→17.4):需按调研文档**多时段、多次取中位数**,单点不可靠。
### 4.3 待补
- 黑盒:上传速度、ping TTL、站点矩阵扩展、**晚高峰复测**、裸连基线对比。
- 白盒:Clash API 拉连接/出站/urltest 延迟、五段拆解、分段 RTT(接入 vs 出海)、稳定性长跑、Kill switch、GFW 存活。
---
## 五、工具落地计划
1. **扩展 `scripts/vpn_test.py`(黑盒)**:加 上传测速 / ping TTL / 站点矩阵 / `--baseline` 基线 / 多时段 cron。
2. **新增 `scripts/vpn_whitebox.sh`(白盒)**:读节点 Clash API(连接/出站/延迟)+ curl 五段拆解 + 接入/出海分段 RTT + 路径 MTU。
3. **新增稳定性长跑**:cron 周期探测落 CSV,出趋势;Kill switch / 重连 / GFW 存活脚本。