起点:目标,和那台标称 30 Mbps 的服务器
目标很朴素:在国内网络环境下稳定访问海外服务,不依赖第三方机场。为此买了一台海外轻量应用服务器,控制台标称 30 Mbps 带宽。
这个数字后来成了整件事的第一个认知陷阱。它的准确含义是实例公网出方向(服务器对外发数据)的峰值速率上限,生效位置在机房一侧的虚拟化出口——承诺的是"这台机器从海外机房往外发数据最快能发到 30 Mbps",在机房本地网络内基本可以兑现。而"从国内访问这台机器"要走跨太平洋出海线路:公众互联网路由的拥塞、丢包、沿途策略限速,全都不在这 30 Mbps 的承诺范围内。标称带宽约束的是服务器那一侧的发送能力,决定实际体验的是中间那条跨境线路的质量,两者是正交变量。
下面按我自己实际折腾的先后顺序记录这四套方案。需要先说明:这个顺序只代表我个人的实验路径,不代表这些技术出现的先后,也不构成任何优劣等级。它们解决的其实是两个完全不同层面的问题——前三套在应用层做特征对抗(能不能通),最后一套在传输层做拥塞控制适配(通得快不快)。分开看,每一步的失败都有明确原因。
第一套方案:OpenVPN Access Server —— 困在"换端口"的循环里
为什么选它,以及它的原理
选型理由是最省事的:OpenVPN 成熟开源,Access Server(AS)在其上提供了 Web 管理台、用户体系、.ovpn 配置文件分发、内置 DNS 与路由控制,几乎不需要自己写运维。
协议原理上,它在 UDP 或 TCP 之上自建了两条通道:控制通道负责密钥协商与会话管理,数据通道承载被封装的 IP 包。控制包带有固定的操作码(opcode),认证依赖静态密钥的 HMAC 签名,载荷再由 TLS 协商出的会话密钥加密。本质是把一个私有协议的结构完整地暴露在链路上——载荷虽然加密了,但"包的形状"是明文可见的。
实际现象
上线后不久开始频繁被阻断,表现是:TCP 三次握手正常完成,隧道协商过程中静默失败,或建立后很快被 RST。更换监听端口后能恢复几天,然后再次中断。如此循环。
归因分析:换端口为什么注定无效
当时把问题理解成"端口被封",所以对策是换端口。这个理解是错的——识别依据从来不在端口上,而在载荷结构与服务器响应行为里。已有的研究给出的指纹相当具体:
- 操作码序列:控制包的 opcode 种类固定、出现次序唯一,取握手前若干个包的 opcode 序列即可做指纹匹配;
- P_ACK 包形态:握手早期的 P_ACK 不携带任何 TLS 载荷,大小一致,且只在握手前期出现——这是一个极强的结构性特征;
- 服务器响应行为:对不含有效 HMAC 签名的包不予回应。主动探测器据此可用两个只差一个字节的构造包,触发"不回应/握手超时"的差异反应来确认目标;OpenVPN 要求 TCP 分片完整到达后才解析的特性,又提供了另一个探测维度。
在 ISP 场景的实测中,这类方法能识别出绝大多数普通 OpenVPN 流,在 41 种混淆配置中认出 34 种,误报率可忽略——XOR 类混淆之所以失效,正是因为混淆没有覆盖 opcode 与 ACK 包长这两个真正的指纹位。
端口只是传输层的一个选择,上述指纹全部位于负载结构与交互行为中,与端口无关。 同样,AS 提供的用户管理、配置分发、DNS 控制都在管理面,不改变线缆上的字节形态。所以换端口、换管理版本,都是在无效维度上做功。
结论只能有一个方向:不要再试图"让加密流量更像另一种加密流量",而要让流量在结构上就是正常的 HTTPS。
转向 V2Ray / VMess —— 特征问题解决了,速度问题浮出水面
原理,以及相对 OpenVPN 的本质改进
VMess 是自定义的二进制协议:以 UUID 做身份认证,配合时间戳校验抵御重放,载荷用 AEAD 加密。传输层做成可插拔(原始 TCP、WebSocket、HTTP/2、gRPC),外层可叠加真实 TLS 与真实站点。
相对 OpenVPN 的本质改进在于结构性指纹的消失:不再有固定 opcode 序列,不再有固定长度的握手 ACK 包,载荷形态可以随传输层伪装而变化。
现象与归因
阻断问题确实解决了,连接稳定。但吞吐远低于预期,跨境场景尤其明显。
当时的归因是协议自身开销:VMess 的握手与校验环节更多,AEAD 加解密在小规格机器上明显吃 CPU,时间戳校验还让两端时钟偏差成为失效因素。社区随后的演进方向也印证了这个判断——VLESS 的设计思路就是把安全完全交给外层 TLS,协议层不再重复加密,理由是底层已有 TLS 加密时,协议层再加密属于重复劳动。
但这个归因只对了一半。它能解释"协议自身成本",解释不了后面看到的两个数量级落差。这一点要到换用 Xray 之后才被证明。
再转向 Xray(VLESS + REALITY)—— 连通性彻底关闭,速度问题被证明与协议无关
原理
三层改进叠在一起:
- VLESS:去掉 VMess 的时间戳校验与协议层加密,安全性完全由外层 TLS 承担,协议头更轻;
- XTLS / Vision 流控:动态调整数据包结构,规避 TLS 内部的特征识别;
- REALITY:握手阶段借用真实知名站点的证书链。主动探测者看到的是真实大站的证书与正常响应,无法证明这台服务器在做代理——补上了自签证书方案最大的软肋(自签证书在主动检查下会直接暴露)。
现象,以及关键的认知转折
抗主动探测的问题解决了,配合路由分层把代理流量与直连流量分开,日常使用稳定正常。
但单流吞吐仍然是 0.17 Mbps。
这一步的价值不在速度,而在排除法:此时协议层开销已经被压到很低(不重复加密 + 流控优化 + 头部精简),吞吐却没有任何量级改善。说明此前归因的"协议开销"不是主因,剩余的差距只能来自路径本身。 问题域从此由"协议"转移到"链路"——后面所有实验都建立在这个转折上。
链路诊断 I:中转路由实验 —— 延迟假设的建立与推翻
假设的来源
用 ping 做基础测量时看到一个很诱人的现象:国内一台服务器到海外落地机的延迟只有约 146 ms 且无丢包,明显优于办公网直连(约 300 ms 量级)。据此形成的假设是——端到端慢是因为 RTT 太高,那就用这台国内机器搭一跳转发,把 RTT 砍到一半,吞吐理应随之改善。
部署与现象
在国内机器上配置转发,形成"办公网 → 国内中转 → 海外落地"的三段式路由。RTT 如预期降到 150 ms 量级。
但吞吐不升反降。同一轮隧道吞吐对比中,走中转约 42 KB/s,直连约 81 KB/s——中转只有直连的一半左右。(这是隧道层的吞吐对比,与前文 0.17 Mbps 的单流基线属不同轮次测量,此处只取相对关系。)
再单独测中转机自身到海外落地机:单流 0.14 Mbps,8 并发 1.9 Mbps。中转机自己走国际段,一样烂。
归因分析
其一,为什么降 RTT 换不来吞吐。 单条 TCP 连接的吞吐上界约为 cwnd / RTT,RTT 减半理想情况下吞吐翻倍。但实测速率比理论值低了两个数量级,说明拥塞窗口根本没涨到 RTT 允许的高度——瓶颈不在分母(RTT),而在分子(窗口)为什么上不去。降延迟是在优化一个不构成实际约束的变量。
其二,为什么多一跳反而更慢。 中转带来三重代价:额外的握手与 RTT、多一层协议封装,以及最关键的一条——两段独立的 TCP 拥塞控制被串联起来。端到端吞吐不是两段相加,而是取两段的最小值;任何一段发生丢包都会独立触发该段的 AIMD 降窗,两段的降窗事件相互叠加,端到端表现只会比单段更差。链路质量本来就差时,中转是纯粹的净损耗。
其三,中转机自身 0.14 Mbps 说明了什么。 "办公网 → 中转机"是国内段,质量没问题;烂的是"中转机 → 海外"这一段,也就是跨境段本身。中转做的事情,只是把跨境的起点从办公网挪到了机房——跨境这个事实一次都没有被消除,而它才是真正的瓶颈所在。
下一步
中转失败了,但失败的方式提供了信息:无论从哪个国内出口走,跨境段都是共同的瓶颈。要弄清它究竟烂在哪里,只能直接测路径质量。
链路诊断 II:163 骨干上 15% 的丢包
进一步测量去程路径质量,拿到关键数据:国内出口到海外落地机的去程途经电信 163 骨干(202.97 段),高峰期拥塞丢包约 15%。
对 TCP 来说这个数字是毁灭性的。Reno/Cubic 家族的基本假设是丢包即拥塞:每检测到丢包,窗口乘性减半,之后每个 RTT 加性增长缓慢爬回。低丢包链路上这个 AIMD 循环工作正常;15% 丢包下,窗口每次爬升没几个 RTT 就再次减半,永远在低位震荡。Mathis 公式给出稳态上界:
吞吐 ≤ MSS / (RTT × √p)
丢包率以平方根落在分母。代入 MSS ≈ 1460 字节、RTT ≈ 150 ms、p = 15%:
≈ 12000 bit / (0.15 s × 0.387) ≈ 0.2 Mbps
理论值 0.2 Mbps,实测 0.17 Mbps,高度吻合——诊断在此闭环:慢是丢失驱动拥塞控制在高丢包链路上的数学必然。 期间排除了 MTU、服务器负载,以及内核 BBR:BBR 确实不以丢包为主要信号,但它的瓶颈带宽估计(BtlBw)取的是滑动窗口内送达速率(delivered / elapsed)的最大值,而送达速率本身受限于出口实际放行的速率——限速器丢弃超额流量后,估计值随之收敛到被限的水平。协议改变不了路径的物理约束。
一个反直觉的机制:去程质量决定回程速度
这 15% 的去程丢包,还解释了中转实验里那个"反而更慢"的现象。
下载时数据流的方向是海外 → 国内(回程),但 TCP 的确认包 ACK 必须反方向走(去程)。去程在拥塞骨干上丢包 15%,意味着大量 ACK 根本到不了海外的发送方;发送方收不到确认就会触发重传与降窗,于是回程的数据吞吐被去程的 ACK 丢失直接拖垮。去程不承载业务数据,却决定了回程能跑多快。
这也解释了为什么 ping 的结果完全不能预示下载性能:ping 是 ICMP 单包回显,没有窗口、没有确认累积、不承载拥塞控制,它只回答"一个包能不能往返",测不出"持续传输时确认流是否稳定"。146 ms 零丢包的 ping 与 0.14 Mbps 的单流吞吐可以同时成立——中转实验的假设正是建立在前者之上,所以注定失败。
当时评估过的两条备选路径
- 云联网打通两地内网:查了产品文档,跨地域跨境流量单独计费且不公开标价,还存在国内站与国际站账号体系不互通、可能根本配不起来的风险,放弃;
- 换更优中转入口(如香港节点走优化线路):本质是花钱买一条质量更好的跨境段,可行但成本不低,而且仍然绕不开办公网出口自身的限制。
两条都属于"换出口 / 买线路"的路子,先搁置——因为还缺一个关键确认:瓶颈究竟在跨境段,还是在办公网出口本身?这个确认动作就是下一节的对照实验。
链路诊断 III:对照实验锁定出口
为此做了一组对照测量,每次只动一个变量——从哪里出去、到哪里去:
| 路径 | 实测 |
|---|---|
| 办公网 → 海外落地机(TCP 单流) | 0.17 Mbps |
| 办公网 → 海外落地机(TCP 8 并发) | ~1 Mbps |
| 国内中转机 → Cloudflare | 42 Mbps |
| 5G 热点 → 海外落地机(同一台电脑直连) | 22.6 Mbps |
最后一条是决定性的:同一台电脑、同一台服务器、同一套协议,仅把出口从办公网换成 5G,吞吐提升约 130 倍。两个嫌疑同时被洗清——落地机不慢,中转机也不慢。瓶颈唯一地锁定在办公网的国际出口:要么被策略性限速(QoS),要么所路由的国际出口本身拥塞;8 并发也只到 1 Mbps,呈现明显的单目标限速特征。
这里需要把诊断 I 的结论对齐一下,否则会出现矛盾:既然中转机自己走国际段只有 0.14 Mbps,为什么 5G 直连同一台落地机能跑到 22.6 Mbps?答案是——"跨境段质量差"不是这条路径的固有属性,而是特定出口的固有属性。中转机走的是拥塞的 163 骨干,5G 走的是另一条国际路由;跨境段烂不烂,取决于你从哪个出口出去、被分配到哪条国际线路上。所以诊断 I 的准确结论应当是:中转没有消除跨境,只是把跨境的起点换成了一个同样糟糕的出口。
为什么 5G 就快?固定宽带与移动网络的国际流量走不同的出口网关和路由路径,办公网这条出口对国际方向施加的限制,在 5G 路径上不存在。由此得出比排查本身更一般的结论:跨境链路的质量由"从哪里出去"决定,而不是"连到哪里"。
顺着这条线,也能解释国内外带宽的价格倒挂。海外机房一侧,带宽供给是充分竞争市场:国际 IP transit 由多家 Tier 1 提供、价格长期下行;更关键的是海外大量跨境流量根本不走运营商国际出口,而是通过 IX 与私有 peering 在 AS 之间直接交换,流量多点自治分流,没有集中排队的位置,边际成本因此很低。国内一侧相反:跨境流量必须经少数集中式国际出口网关转发,容量天然紧张、拥塞集中在这些节点(前文 163 骨干的丢包正发生在这类位置);跨洋海缆单条造价数亿美元、建设周期数年且需定期维修;持有出口资源的一级运营商向下批发时层层加价,云服务商再叠加机房与运维成本。这解释了为什么国内服务器带宽小而贵、跨境优化线路需要单独溢价。购买海外服务器时看到的带宽数字,描述的是它在海外机房那一侧的发送能力;实际用到的,是跨太平洋这条线路的质量——后者不在任何标称数字的承诺范围内。
最终方案:Hysteria2 —— 换掉怕丢包的传输层
原理
前面三套方案都跑在 TCP 上,而 TCP 的死穴正是丢失驱动的窗口收缩。对策是换传输层:QUIC 之上的 Hysteria2。QUIC 跑在 UDP 上,拥塞控制可插拔且能缓解 TCP 的队头阻塞;Hysteria2 的选择由带宽协商决定——客户端不声明带宽时默认 BBR,显式声明后切换为 Brutal:按配置速率硬发、不响应丢包信号,专为高丢包环境设计。
两种哲学一句话:TCP 丢了包就减速,Brutal 丢了包继续冲。 代价是放弃对共享链路上其他流的公平性。这个代价是否值得付,不靠信仰靠数据——这正是预实验要回答的。
UDP 预实验:先验证,再部署
部署前必须验证一个前提:出口对 UDP 是否放行? 如果限速器对 UDP 下手更狠,一切白搭。
先在已放行端口上用 UDP 回显测连通性(全通),再做吞吐:iperf3 匀速打流 12 秒。方法论上有个关键点:客户端读数反映的是发送速率,不是送达速率——一次突发打流中客户端显示 457 Mbps,服务端实测丢包 89%,瞬时发送速率远超出口处理能力,超发部分全部丢在路上。吞吐与丢包只能以服务端实收统计为准:
| 发送速率 | 服务端实收 | 丢包率 |
|---|---|---|
| 2 Mbps | ~2 Mbps | ≈ 0 |
| 8 Mbps | ~5 Mbps | ~12% |
三个结论:出口对 UDP 放行,通道可用带宽约 5 Mbps,是 TCP 的 30 倍;8 Mbps 打流实收 5 Mbps,说明通道存在约 5 Mbps 的客观上限,为调优设定了合理预期;2 Mbps 匀速几乎无损送达,说明丢包发生在超发之后而非常态存在——硬发策略在这条链路上有效,前文那个公平性代价可以放心支付。
(插曲:iperf3 默认端口起初全部超时,最终确认是云安全组未放行,尽管控制台给人"端口全开"的印象。安全组规则的实际生效只能靠连通性实测验证。)
落地与调优
同端口共存:Hysteria2 与现有 Xray 共用同一端口号——TCP 与 UDP 在内核中是两套独立的 socket 命名空间,同号并存互不干扰。好处是无需在安全组开新口子,旧服务零改动。
带宽档位:这一步直接对应 Brutal 的启用条件——客户端显式声明 up/down 后该方向才进入 Brutal 固定速率模式,实际速率取两端配置的较小值;服务端 bandwidth 是上限封顶,且只对 Brutal 生效。初次实测只有 1.9~2.8 Mbps、低于预实验的 5 Mbps,正是带宽未充分显式声明的表现;显式配置到位后单流稳定到 2.9 Mbps。
| 方案 | 吞吐 | 相对基线 |
|---|---|---|
| TCP 直连(VLESS + REALITY)单流 | 0.17 Mbps | 1× |
| TCP 8 并发 | ~1 Mbps | ~6× |
| TCP 国内中转 | 无提升 | — |
| Hysteria2 单流(调优后) | 2.9 Mbps | ~17× |
| Hysteria2 4 路并发 | 3.56 Mbps | ~21× |
3.56 Mbps 已逼近预实验测定的通道上限,剩余空间属于出口的物理限制,客户端侧无优化余地。
复盘
四套方案各自解决了不同层面的问题,按我实际的实验顺序排在一起看,路径就很清楚(再强调一次:这是个人排查路径,不是技术演进史):
| 我用的方案 | 解决的层面 | 手段 | 遗留问题 |
|---|---|---|---|
| OpenVPN AS | 隧道连通 | 私有协议封装 | 结构性指纹被识别,换端口无效 |
| V2Ray / VMess | 特征对抗 | 自定义协议 + 可插拔传输伪装 | 吞吐低,误归因于协议开销 |
| Xray / VLESS + REALITY | 抗主动探测 | 借用真实证书 + 流控 + 头部精简 | 证明协议不是瓶颈,问题在链路 |
| 国内中转路由 | 路径优化(尝试) | 国内机房转发,RTT 300→150 ms | 失败:跨境未被消除,两段拥塞控制串联反而更慢 |
| Hysteria2 | 传输层吞吐 | QUIC + Brutal 固定速率 | 逼近出口物理上限 |
协议侧的教训有两条:指纹位于负载结构与交互行为中,端口和混淆层都不是有效维度;协议开销压到极低仍无改善,就该把怀疑对象从协议换成路径。
中转实验的教训同样有两条,而且更容易被忽略:ping 测的是单包往返,不能预示持续传输的吞吐——去程丢的是 ACK,而 ACK 丢失会直接拖垮反方向的数据流,所以"去程延迟低、无丢包"与"下载只有 0.14 Mbps"完全可以同时成立;多一跳不是中性的,两段独立的拥塞控制串联后端到端吞吐取最小值,在差链路上中转是净损耗。
而链路侧的诊断收敛为一个三变量框架:
- RTT 是吞吐公式的分母之一,但高丢包链路上窗口涨不到 BDP,RTT 不构成实际约束,优化它是无效动作;
- 丢包率 对丢失驱动拥塞控制是平方根级的绞杀,15% 丢包足以把 150 ms 链路锁死在 0.2 Mbps;
- 出口带宽 是硬上限,前两项解决得再好也会撞墙。
对应处置:丢包型瓶颈换不依赖丢包信号的协议,限速型瓶颈只能换出口。先测量、归类瓶颈,再选择手段——先假设后实验、用数据推翻假设、每组实验只动一个变量,这套流程比任何具体结论都更可复用。
提速落地后,代理环境的日常使用又暴露出 TUN 劫持 DNS、应用对 CDN 裸 IP 直连绕过分流规则等客户端侧问题,属于分流工程的主题,与本文的链路层诊断无关,另文再谈。
文章评论