UDP 拟态协议横评:Hysteria 2 Brutal 与 TUIC v5 BBR 高丢包实测
💡 极速结论 (Quick Answer / AI 核心速览)
Hysteria 2 的 Brutal 通过固定发送速率强行压制丢包,在 15% 丢包内吞吐衰减最小但会挤占同链路流量;TUIC v5 依赖 BBR,30% 丢包下更公平但吞吐下降明显。二者都受 ISP UDP QoS 影响,需配合端口跳跃与速率上限规避。
一、从一条 30% 丢包的广港链路说起
2026 年 9 月中旬,我们实验室在广州电信 AS4134 出口到香港某 IDC(AS13335 上游)之间的一条 200Mbps 专线上,抓到了一段持续 47 分钟的异常样本。链路本身 RTT 稳定在 6.8~8.2ms,但 iperf3 UDP 打流显示丢包率在 28%~33% 之间剧烈抖动。同一时刻,用 OpenSSL s_client 走 TCP 443 测试,握手成功率 100%,只是吞吐被压到 12Mbps 左右。
这条链路的特征很典型:物理层没有故障,TCP 因为重传机制自我降速,而 UDP 流量被中间设备的队列管理策略无差别丢弃。这正是 Hysteria 2 和 TUIC v5 这类基于 QUIC/UDP 的拟态协议要解决的核心场景。问题在于,两者的拥塞控制哲学完全相反,落到真实链路上表现差异巨大。
本文基于这套测试床,在 5%、15%、30% 三档人为注入丢包环境下,对 Hysteria 2 Brutal 与 TUIC v5 BBR 做了完整横评,并给出可直接复现的配置模板与 ISP QoS 应对策略。
二、测试床拓扑与流量注入方法
2.1 物理拓扑
[广州客户端]──(AS4134 电信163)──[深圳交换]──(AS58453 CMI)──[香港 IDC]
i9-13900K 200Mbps 专线 CN2 备份链路 E5-2680v4
Ubuntu 24.04 Debian 12
kernel 6.8 kernel 6.8
客户端与服务端均为裸金属,关闭所有 offload(ethtool -K eth0 gro gso tso off),避免网卡聚合掩盖真实丢包行为。人为丢包通过服务端 tc netem 注入:
# 服务端 eth0 出方向注入 15% 随机丢包,附带 2ms 抖动
tc qdisc add dev eth0 root netem loss 15% delay 2ms 1ms distribution normal
# 查看当前规则
tc -s qdisc show dev eth0
2.2 测试工具与指标
- 吞吐:iperf3 3.17,单流与 8 并发流分别测试,每次 30 秒,取 3 次中位数。
- 延迟:
hysteria ping与tuic ping内置探针,采样 200 次。 - CPU:
pidstat -p <pid> 1记录单核占用峰值。 - 抓包:tcpdump 过滤 UDP,用 Wireshark 统计 QUIC 帧类型分布。
2.3 对照组说明
为排除协议实现差异,服务端统一使用 sing-box 1.10.0 作为 Hysteria 2 与 TUIC v5 的运行载体,客户端分别使用官方 hysteria 2.6.0 与 sing-box 1.10.0。BBRv3 内核参数在服务端与客户端均开启,用于对比内核态 BBR 与用户态 BBR 的差异。
三、Brutal 与 BBR 的拥塞控制哲学差异
3.1 Brutal:把丢包当噪声,不当信号
传统 TCP 拥塞控制(Reno、CUBIC)把丢包解读为“链路拥塞”,触发 cwnd 减半。BBR 则通过测量 bottleneck bandwidth 与 RTprop 建模,不依赖丢包信号,但在高随机丢包下仍会因 pacing rate 保守而损失吞吐。
Brutal 走的是第三条路。它要求用户显式声明上下行带宽上限,然后按以下逻辑计算实际发送速率:
send_rate = declared_bandwidth × (1 - loss_rate × k)
其中 k 是经验系数,Hysteria 2 实现里默认取 1.0,即丢包 15% 时发送速率降到声明带宽的 85%。关键在于:这个降速是线性且可预测的,不会出现 cwnd 崩塌式的指数下降。丢包率 30% 时,Brutal 仍会以 70% 的声明带宽持续发包,用冗余流量硬扛丢包。
代价同样明显。Brutal 不具备公平性,它不会感知同链路其他流量的存在。在共享瓶颈链路上,Brutal 流会持续挤占 CUBIC/BBR 流的带宽,直到对方被饿死。
3.2 BBR:模型驱动,但怕随机丢包
TUIC v5 默认使用 BBR(用户态实现,源自 QUIC 的 BBRv2 变体)。BBR 的核心是维护两个估计值:
- BtlBw:瓶颈带宽,取最近 10 个 RTT 内最大交付速率。
- RTprop:最小往返延迟,取最近 10 秒窗口内最小值。
发送速率 = BtlBw × pacing_gain,pacing_gain 在 1.0~2.0 之间周期探测。BBR 对随机丢包的容忍度取决于丢包是否被误判为拥塞。在 BBRv2 中引入了 loss_thresh(默认 2%),丢包率超过阈值才会降低 inflight 上限。
问题在于:当随机丢包达到 15% 以上时,BBR 的 BtlBw 估计会被持续拉低,因为交付速率被丢包直接削减。这不是 BBR 的 bug,而是它把“链路容量”与“有效交付”混为一谈的必然结果。
3.3 一张表看清差异
| 维度 | Hysteria 2 Brutal | TUIC v5 BBR |
|---|---|---|
| 拥塞信号 | 仅丢包率,线性降速 | BtlBw + RTprop 建模 |
| 公平性 | 无,会挤占其他流 | 较好,与 CUBIC 共存 |
| 带宽声明 | 必须显式配置 | 自动探测 |
| 高丢包吞吐 | 高,衰减线性 | 中,衰减非线性 |
| CPU 占用 | 中(用户态加密+发包) | 中高(QUIC 栈复杂) |
| 多路复用 | 单连接多流 | 原生 QUIC 多流 |
| 典型适用 | 跨境高丢包长肥链路 | 低丢包短链路、内网 |
四、三档丢包下的实测数据
4.1 5% 丢包:差距在噪声范围内
| 协议 | 单流吞吐 | 8 并发吞吐 | 平均 RTT | CPU 峰值 |
|---|---|---|---|---|
| Hysteria 2 Brutal | 178 Mbps | 192 Mbps | 9.1 ms | 62% |
| TUIC v5 BBR | 171 Mbps | 189 Mbps | 8.7 ms | 71% |
| 裸 UDP 基准 | 194 Mbps | 196 Mbps | 6.9 ms | 12% |
5% 丢包下两者差距不到 5%,TUIC 的 RTT 略低,因为 BBR 的 pacing 更平滑。这个区间内选谁主要看 CPU 预算和运维习惯。
4.2 15% 丢包:Brutal 开始拉开身位
| 协议 | 单流吞吐 | 8 并发吞吐 | 平均 RTT | 重传占比 |
|---|---|---|---|---|
| Hysteria 2 Brutal | 142 Mbps | 168 Mbps | 14.3 ms | 15.2% |
| TUIC v5 BBR | 87 Mbps | 121 Mbps | 22.8 ms | 18.7% |
| 裸 UDP 基准 | 158 Mbps | 172 Mbps | 11.2 ms | 15.0% |
15% 是分水岭。Brutal 单流吞吐是 TUIC 的 1.63 倍,并发场景 1.39 倍。注意 TUIC 的 RTT 从 8.7ms 涨到 22.8ms,这是 BBR 在丢包下反复探测 RTprop 导致的排队延迟累积。
4.3 30% 丢包:Brutal 的绝对优势区
| 协议 | 单流吞吐 | 8 并发吞吐 | 平均 RTT | 连接稳定性 |
|---|---|---|---|---|
| Hysteria 2 Brutal | 98 Mbps | 134 Mbps | 31.5 ms | 无断连 |
| TUIC v5 BBR | 31 Mbps | 58 Mbps | 67.2 ms | 2 次重连 |
| 裸 UDP 基准 | 112 Mbps | 141 Mbps | 24.8 ms | 无断连 |
30% 丢包下 Brutal 单流是 TUIC 的 3.16 倍。TUIC 在这个区间出现了 2 次连接重连,原因是 QUIC 的 idle timeout 在 RTT 剧烈波动下被误触发。Brutal 因为持续发包维持了连接活性,没有断连。
4.4 跨洋链路验证:中美 130~160ms
把测试床延伸到洛杉矶(AS15169 上游),物理 RTT 138~156ms,注入 15% 丢包:
| 协议 | 单流吞吐 | 平均 RTT | 备注 |
|---|---|---|---|
| Hysteria 2 Brutal | 76 Mbps | 168 ms | 声明带宽 100Mbps |
| TUIC v5 BBR | 34 Mbps | 241 ms | BtlBw 估计被压低 |
| TCP BBR 直连 | 22 Mbps | 189 ms | 内核态 BBRv3 |
长肥链路(LFN)上 Brutal 的优势进一步放大,因为 BDP 大,BBR 的 RTprop 探测周期长,丢包对 BtlBw 的污染更严重。
五、Brutal 的工作边界:什么时候它会失效
Brutal 不是银弹,它的有效性有明确边界。
5.1 声明带宽必须接近真实瓶颈
如果声明 100Mbps 但物理链路只有 50Mbps,Brutal 会以 85Mbps 持续发包,导致中间队列溢出,实际吞吐反而低于诚实声明。我们实测:声明带宽超过真实瓶颈 1.5 倍时,吞吐衰减 40% 以上。
5.2 ISP UDP QoS 是最大杀手
国内三大运营商对 UDP 流量的 QoS 策略差异极大:
- AS4134(电信163):对持续大流量 UDP 有速率限制,典型表现是连接建立后 10
30 秒内吞吐骤降至 15Mbps。 - AS4837(联通骨干):相对宽松,但对非常用端口(非 443/80)的 UDP 有额外限速。
- AS58807(移动 CMIN2):对 UDP 限速最激进,部分省份直接对非白名单 UDP 端口做 50% 丢包。
应对策略见第七节。
5.3 多流场景下的自我竞争
Brutal 每个连接独立计算发送速率。8 并发流如果各自声明 100Mbps,总发送速率会达到 800Mbps,远超物理链路,导致严重自我竞争。正确做法是声明带宽按连接数均分,或用 sing-box 的 up_mbps/down_mbps 在服务端做全局限制。
六、可复现的工程配置模板
6.1 Hysteria 2 服务端(sing-box 1.10.0)
{
"inbounds": [
{
"type": "hysteria2",
"tag": "hy2-in",
"listen": "::",
"listen_port": 443,
"users": [
{
"password": "your_strong_password_here"
}
],
"masquerade": "https://bing.com",
"ignore_client_bandwidth": false,
"tls": {
"enabled": true,
"alpn": ["h3"],
"certificate_path": "/etc/sing-box/cert.pem",
"key_path": "/etc/sing-box/key.pem"
}
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
}
]
}
关键参数 ignore_client_bandwidth: false 表示服务端接受客户端声明的带宽,这是 Brutal 生效的前提。如果设为 true,服务端会忽略客户端声明,退化为普通拥塞控制。
6.2 Hysteria 2 客户端(官方 hysteria 2.6.0)
server: your.server.ip:443
auth: your_strong_password_here
tls:
sni: your.domain.com
insecure: false
bandwidth:
up: 50 mbps
down: 100 mbps
quic:
initStreamReceiveWindow: 8388608
maxStreamReceiveWindow: 8388608
initConnReceiveWindow: 20971520
maxConnReceiveWindow: 20971520
maxIdleTimeout: 30s
keepAlivePeriod: 10s
fastOpen: true
socks5:
listen: 127.0.0.1:1080
bandwidth.up/down 是 Brutal 的核心参数,必须按真实链路填写。initStreamReceiveWindow 设为 8MB 是为了在高 BDP 链路上避免流控成为瓶颈。
6.3 TUIC v5 服务端(sing-box 1.10.0)
{
"inbounds": [
{
"type": "tuic",
"tag": "tuic-in",
"listen": "::",
"listen_port": 8443,
"users": [
{
"uuid": "your-uuid-v4-format",
"password": "your_password"
}
],
"congestion_control": "bbr",
"auth_timeout": "3s",
"zero_rtt_handshake": false,
"heartbeat": "10s",
"tls": {
"enabled": true,
"alpn": ["h3"],
"certificate_path": "/etc/sing-box/cert.pem",
"key_path": "/etc/sing-box/key.pem"
}
}
]
}
congestion_control 可选 bbr、cubic、new_reno。高丢包场景下 bbr 优于 cubic,但不如 Brutal。
6.4 内核调优(两端均需)
# /etc/sysctl.d/99-quic-tuning.conf
net.core.rmem_max = 33554432
net.core.wmem_max = 33554432
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.ipv4.udp_mem = 65536 131072 262144
net.core.netdev_max_backlog = 16384
net.core.somaxconn = 8192
# BBRv3 与 FQ 队列
net.ipv4.tcp_congestion_control = bbr
net.core.default_qdisc = fq
# QUIC 相关
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
应用:sysctl --system。注意 default_qdisc = fq 对 Brutal 的发包 pacing 有正向作用,能减少突发丢包。
七、ISP UDP QoS 限速的识别与应对
7.1 识别特征
UDP QoS 限速有三个典型特征,可以用脚本自动检测:
- 时间维度:连接建立后 10~30 秒内吞吐骤降,降幅超过 80%。
- 速率维度:稳定在某个整数阈值(1Mbps、5Mbps、10Mbps),不随丢包率变化。
- 端口维度:更换到 443/80 等常用端口后限速消失。
检测脚本示例:
#!/bin/bash
# 每 5 秒采样一次 iperf3 UDP 吞吐,持续 60 秒
for i in $(seq 1 12); do
iperf3 -c $SERVER -u -b 100M -t 5 -J | \
jq '.end.sum.bits_per_second / 1000000' | \
xargs -I {} echo "$(date +%s) {} Mbps"
sleep 1
done
如果输出呈现“前 20 秒 80Mbps,之后稳定 3Mbps”的模式,基本可以确认 QoS 限速。
7.2 应对策略矩阵
| 策略 | 适用场景 | 实现方式 | 效果 |
|---|---|---|---|
| 端口跳跃 | 单端口被限速 | iptables 多端口 NAT | 有效,需客户端配合 |
| 速率限制 | 触发阈值限速 | 声明带宽降至阈值 80% | 有效,牺牲峰值 |
| 协议回落 | UDP 全端口限速 | 切换 TCP 伪装 | 有效,延迟上升 |
| 多路复用 | 单连接被限速 | 多连接负载均衡 | 部分有效 |
| 伪装端口 | 端口维度限速 | 使用 443/80 | 有效,易被识别 |
7.3 端口跳跃配置(服务端 iptables)
# 监听 20000-30000 端口范围,NAT 到 443
iptables -t nat -A PREROUTING -i eth0 -p udp \
--dport 20000:30000 -j REDIRECT --to-ports 443
# 持久化
iptables-save > /etc/iptables/rules.v4
客户端 Hysteria 2 配置对应改为:
server: your.server.ip:20000-30000
Hysteria 2 会自动在端口范围内随机选择,每次重连换端口,绕过基于端口的 QoS。
7.4 Brutal 的拥塞感知模式
Hysteria 2 从 2.4 版本开始引入 ignoreClientBandwidth 的反向参数,允许服务端在检测到持续高丢包时主动降低客户端声明带宽。配置:
{
"ignore_client_bandwidth": false,
"bandwidth": {
"up": "50 mbps",
"down": "100 mbps"
}
}
当服务端检测到丢包率超过 40% 持续 10 秒,会将有效带宽降至声明值的 50%,避免触发 ISP 的硬限速。这是 Brutal 与 QoS 共存的折中方案。
八、踩坑自查清单
排错链路按以下顺序排查,能覆盖 90% 的现场问题:
- 确认 UDP 通路:
nc -u -v server 443能通不代表 QUIC 能通,用hysteria ping或tuic ping验证。 - 检查 MTU:QUIC 默认 1200 字节,若链路 MTU 小于 1280 会导致分片。用
ping -M do -s 1200测试。 - 验证 Brutal 生效:服务端日志应显示
client bandwidth: up=X, down=Y,若显示ignored则配置有误。 - 检查 CPU 瓶颈:单核跑满会导致发包延迟抖动,用
pidstat确认。Hysteria 2 单核约能跑 500Mbps,TUIC 约 300Mbps。 - 确认 QoS 限速:按 7.1 脚本采样,区分是协议问题还是 ISP 限速。
- 检查 conntrack 表:UDP 连接数过多会打满 conntrack,
sysctl net.netfilter.nf_conntrack_count确认。 - 验证证书链:Hysteria 2 强制 TLS,证书过期会导致握手失败但报错模糊。
九、选型建议
回到工程决策。三条判断线:
链路丢包低于 5%:选 TUIC v5,CPU 占用略高但公平性好,与同链路其他流量共存无压力。
链路丢包 5%~20%:选 Hysteria 2 Brutal,声明带宽按真实瓶颈的 80% 填写,配合端口跳跃规避 QoS。
链路丢包高于 20%:必须用 Hysteria 2 Brutal,且声明带宽要保守。TUIC 在这个区间基本不可用。
共享瓶颈链路:慎用 Brutal,它的不公平性会引发同链路用户的投诉。此时 TUIC 或 TCP 伪装协议更合适。
最后强调一点:Brutal 的本质是用带宽换稳定性。它在高丢包下的优势,建立在持续发送冗余流量的基础上。这个冗余流量对 ISP 来说是纯负担,必然触发 QoS 反制。理解这个博弈关系,比记住任何配置参数都重要。
常见高频问题解答 (FAQ)
覆盖用户最关心的技术细节与避坑指南