为何Http3没有Http2快速重置(CVE-2023-44487)攻击?

让我们从一个简单的自动售货机的类比开始:

  • HTTP/2 就像一个效率非常低的系统:每次有人购买一件物品时,都需要立即由一名(非常劳累的)员工全天候(24/7)进行补充。它始终保持充足的库存。
  • HTTP/3 是一种更现实的设置:机器只有在(几乎)空的时候或在设定的时间才会重新加水。如果是空的,你只需要等待。 HTTP/3 自动售货机非常严格地执行了这一规定:如果你试图购买不存在的物品,它就会炸毁整栋大楼!

换句话说,

  • HTTP/2 对其可处理的并发请求量是有限制的。 每当一个请求处理完毕(从自动售货机中购买并补充物品),紧接着就可以接受另一个请求。
  • 但是,HTTP/3 对累计请求的处理量有限制。 即使请求已完成,总计数仍会增加 1(自动售货机中少了 1 件商品)。您需要等待自动售货机重新装满(新的累计限制)。


和大多数比喻一样,这个类比也有缺陷,但能帮助我们理解这里的高层次差异。

那么,让我们从更底层的角度来看看实际发生了什么。

假设 HTTP/2 和 HTTP 3 的请求数都限制为 3 个:

对于 HTTP/2:

  • 请求 1 接收(并发请求数 = 1)
  • 请求 1 被客户端快速重置(并发请求数 = 0)
  • 请求 2 进入(并发请求数 = 1)
  • 请求 2 被客户端快速重置(并发请求数 = 0)
  • 请求 3 进入(并发请求 = 1)
  • 请求 3 被客户端快速重置(并发请求 = 0)、

由于被客户端“快速重置”,3 这个并发限制被 "绕过"。

对于 HTTP/3:

  • 请求 1 接收(累计请求数 = 1)
  • 请求 1 被重置(累计请求数 = 1)
  • 请求 2 进入(累计请求数 = 2)
  • 请求 2 被重置(累计请求数 = 2)
  • 请求 3 进入(creqs = 3)
  • 请求 3 重置(creqs = 3)

如果请求 4 进入,HTTP/3 将以 STREAM_LIMIT_ERROR 结束。

因此,虽然 HTTP/2 的限制从未改变,但并发请求量却始终低于该限制。 而对于 HTTP/3,累计限制会增加,但只有当总请求数达到之前的限制时才会增加,而不是像http2在重置数据流的时候!

这里有一点细微差别。理论上,HTTP/3 实现可以在每次请求重置后更新(内部)累计限制,但这种实现方式很奇怪(通常要等到至少处理完一个数据包后才会这样做)。

因此,在上面的例子中,如果请求 4 与请求 1-3 在同一个数据包中(如快速重置),HTTP/3 就会出错,因为它只有在处理完整个数据包后才会更新累计限制。 因此,攻击者可以在每个数据包中容纳更少的请求。

因此,从概念上讲,HTTP/3 可能存在漏洞,但前提是实现过程中出现了奇怪的情况(非常急切地更新限制)。 否则,攻击就会受到每次往返最大累计请求的限制(因为限制更新需要先到达客户端,然后才能继续!)。


因此,HTTP/3的每秒最大请求次数比 http2 低得多,从而减轻了攻击。 IETF 的一份新文件建议在 HTTP/2 中使用 HTTP/3 流限制
我们将拭目以待未来的实现如何处理这一问题。

最后的技术补充:在 HTTP/3 中,实际上是由 QUIC 来管理限制,从技术上讲,限制是针对 "流 "而非 "请求 "的。