- 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
9.7 KiB
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:00–24: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 优 / 500–1000ms 偏高 / >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-Nrange 取固定大小)
方法
- 先 裸连基线(不开 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,评估 TUNmtu 9000是否导致分片/卡顿 (调研:运营商对大包敏感,业界常 clamp 到 1350)。
3.7 节点侧资源(瓶颈定位)
- 节点 CPU/内存/带宽(单核 512MB 是硬约束)、sing-box 进程占用、网卡流量。
- agent / 控制面健康。
3.8 稳定性测试(白盒重点)
- 长跑:cron 每 1–5 分钟探测(出口 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、tun172.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 握手 ~420–490ms、TTFB ~600–715ms (节点在洛杉矶,中国→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 | ~10–17 Mbps(多次波动:7.66 / 10.6 / 17.4) | 走 REALITY→节点→出海 |
| 国内(直连) 清华镜像 10MB | 74.28 Mbps | geoip-cn 命中 → 直连,不经隧道 |
| 国内 阿里云镜像 | 未测到(URL 失效) | 待换有效测速 URL |
结论:
- 分流生效:国内直连(74 Mbps)远快于国外经隧道(~10-17),说明 geoip-cn 直连正常。
- 瓶颈在出海段:国外吞吐受限于隧道——单核 512MB 联调节点 + 出海带宽 + 可能晚高峰。不是客户端/隧道软件问题。
- 波动大(7.66→17.4):需按调研文档多时段、多次取中位数,单点不可靠。
4.3 待补
- 黑盒:上传速度、ping TTL、站点矩阵扩展、晚高峰复测、裸连基线对比。
- 白盒:Clash API 拉连接/出站/urltest 延迟、五段拆解、分段 RTT(接入 vs 出海)、稳定性长跑、Kill switch、GFW 存活。
五、工具落地计划
- 扩展
scripts/vpn_test.py(黑盒):加 上传测速 / ping TTL / 站点矩阵 /--baseline基线 / 多时段 cron。 - 新增
scripts/vpn_whitebox.sh(白盒):读节点 Clash API(连接/出站/延迟)+ curl 五段拆解 + 接入/出海分段 RTT + 路径 MTU。 - 新增稳定性长跑:cron 周期探测落 CSV,出趋势;Kill switch / 重连 / GFW 存活脚本。