HTTP/3 也出事了。
安全研究团队 FoxIO 在 10 月 20 日公开了一类名为 Header Accordions(头部手风琴攻击) 的拒绝服务攻击。部分 HTTP/3 实现处理请求头时,几百 KB 的输入就可能换来远超这个量级的资源消耗。
研究人员测试 Bun 的 HTTP/3 服务时,发送了约 516 KiB 数据,服务器就陷入了死循环,CPU 占用率一直维持在 100%,新请求也处理不了了。

10 种实现,7 种发现问题
FoxIO 测试了 10 种 HTTP/3 相关实现,其中 7 种存在不同程度的问题:
- quic-go:Caddy、Traefik 等项目使用的 QUIC 实现。
- Cloudflare quiche:Cloudflare 开发的 QUIC/HTTP/3 库。
- lsquic:LiteSpeed 相关的 QUIC 实现。
- Bun:JavaScript 运行时,其 HTTP/3 支持基于 lsquic。
- aioquic / mitmproxy:Python QUIC 库,以及使用它的代理工具。
- h3(hyperium):Rust HTTP/3 库。
- Wireshark:HTTP/3 协议解析器,处理特制流量时可能卡住或崩溃。
Wireshark 已经算在这 7 种里面;它的问题发生在协议解析过程,与网站服务器遭到攻击的场景有所区别。各实现的后果也不完全相同,包括内存耗尽、CPU 死循环和线程 panic。
几百 KB,为什么能搞垮服务器?
问题主要出在 HTTP/3 的请求头压缩技术 QPACK 上。
为了节省流量,重复出现的请求头可以用很短的索引表示。服务器收到后,再把索引还原成完整字段。这本来是正常的压缩机制,但部分实现没有在解码过程中有效限制资源消耗。
有的只检查压缩后的大小,有的等全部解压完才检查,还有的虽然宣告了大小限制,代码却没有真正执行。
于是,网络上传来的一小段数据,到了服务器里,就可能变成一大堆需要分配、复制和保留的请求头对象。
这也是 Header Accordions 这个名字的由来:传输时像收拢的手风琴,占不了多少空间;到了服务器上,却一下展开了。
在部分动态表引用测试中,每个很短的索引都会触发对较大字段的重新分配和复制,放大比例可达约 4000 倍。这个比例来自特定测试路径,并非所有实现的共同表现。

研究人员在 Bun 上展示了两种不同的结果:
- 内存耗尽:约 5.8 MiB 的传输数据,让一个 2 GiB 容器被 OOM 杀死。
- CPU 死循环:单条流约 516 KiB 的传输数据,触发缓冲区扩容时的整数溢出,程序进入死循环,CPU 持续占满。
这是两项独立测试,不能把“516 KiB”理解为“直接耗尽一个 2 GiB 容器”。
对于攻击者来说,麻烦之处就在于:在这些存在问题的配置下,并不需要很大的攻击流量,就可能让服务停止响应。FoxIO 原始研究
哪些服务器需要注意?
如果你使用了 HTTP/3,尤其是 Caddy、Traefik、LiteSpeed 或相关 QUIC 库,建议检查实际集成的依赖版本。
FoxIO 列出的修复版本如下,统计截止日为 2026 年 10 月 20 日:
| 组件 | 修复版本 |
|---|---|
| quic-go | 0.57.0 |
| Cloudflare quiche | 0.29.3 |
| lsquic | 4.9.0 |
| Wireshark | 4.6.2 / 4.4.12 |
其中,quic-go、Cloudflare quiche 和 Wireshark 的修复版本,也可在各自的官方安全公告中核对:quic-go 公告、quiche 公告、Wireshark 公告。
按照 FoxIO 在 10 月 20 日发布的状态,Bun 1.4.3、h3、aioquic / mitmproxy 仍有相关问题未修复。这是披露时的状态,部署前应继续查看项目的最新公告。
HTTP/3 还能放心用吗?
可以继续用,但得关注实现本身的安全更新。
HTTP/3 基于 QUIC,使用 UDP 传输。这次研究集中暴露的是软件实现对请求头资源消耗的处理问题:限制有没有生效,检查得是否及时,以及应用最终保留了多少数据。
青小蛙觉得,对于很多小水管服务器来说,攻击者只需要一点点的流量,就需要服务器端几千倍的资源开销,完全是放大器效果,中招以后有些棘手。
能更新就更新,不能就先把 HTTP/3 关了?