Safeguard
Application Security

Hardening HTTP/2 against protocol-level DoS attacks

HTTP/2 Rapid Reset hit Google with 398 million requests per second in 2023 — a single protocol quirk, not a bug in any one server, drove the largest DDoS ever disclosed.

Safeguard Research Team
Research
6 min read

On October 10, 2023, Google, Cloudflare, and AWS jointly disclosed CVE-2023-44487, an HTTP/2 protocol weakness that had already been exploited in the wild since August of that year. The attack, nicknamed "Rapid Reset," pushed Google's infrastructure to 398 million requests per second, Cloudflare to 201 million, and AWS to 155 million — the three largest DDoS attacks publicly documented at the time, all driven by the same short open-then-cancel exploit pattern rather than a bug specific to any one vendor. That's the uncomfortable truth about HTTP/2 security: because the protocol's multiplexing, flow control, and header compression are specified once and implemented dozens of times, a single design gap can turn into a CVE cluster spanning nginx, Apache, IIS, Envoy, gRPC, Node.js, and more, all at once. Rapid Reset wasn't even the first or last time this happened — a family of eight DoS CVEs surfaced in 2019, and a second protocol-level flaw, the CONTINUATION Flood, followed in April 2024. This piece walks through the three major waves of HTTP/2 DoS discoveries, what made each one dangerous, and the concrete server settings that close them off.

What made HTTP/2 Rapid Reset (CVE-2023-44487) different from a normal flood?

Rapid Reset abused HTTP/2's stream lifecycle instead of raw connection volume. In HTTP/1.1, a client needs a new TCP connection per concurrent request; HTTP/2 lets a client multiplex many streams over one connection, capped by the server's advertised SETTINGS_MAX_CONCURRENT_STREAMS. The attack opens a stream with a request, then immediately sends RST_STREAM to cancel it — before the server has finished processing — and repeats this open-then-cancel cycle thousands of times per connection. Because the stream is cancelled so quickly, it never counts against the concurrent-stream limit, but the server has already done the work of allocating request state, dispatching to backend logic, and tearing it back down. A handful of TCP connections can therefore generate request volume that would otherwise require a botnet of matching size. Cloudflare, Google, and AWS all published their mitigation research the same day the CVE dropped, and nearly every major HTTP/2 server and proxy shipped an independent patch within days, since each implementation tracked (or failed to track) reset streams differently.

How does the CONTINUATION Flood differ from Rapid Reset, and why is it arguably worse?

Security researcher Bartek Nowotarski reported the CONTINUATION Flood to CERT/CC on January 25, 2024, with public disclosure following in April 2024 as a cluster of CVEs including CVE-2024-27316 (Apache httpd). HTTP/2 splits large header blocks across multiple HEADERS and CONTINUATION frames, with an END_HEADERS flag marking the final frame. Nowotarski found that several implementations never enforced a limit on how many CONTINUATION frames could arrive before that flag showed up — so a client could send an effectively unbounded stream of CONTINUATION frames on a single stream, forcing the server to keep buffering header data that never completes. Where Rapid Reset needed volume to hurt, a CONTINUATION Flood could crash a vulnerable server's memory with a single connection and a handful of frames, which is why researchers flagged it as potentially more severe per-connection than Rapid Reset even though it made far fewer headlines. Apache httpd, Node.js, Envoy, Tomcat, and other projects each shipped separate patches and CVE identifiers, again illustrating how a single frame-handling gap in the spec's flexibility fans out across the ecosystem.

What did the 2019 wave of HTTP/2 DoS CVEs already teach the industry?

Four years before Rapid Reset, researchers at Netflix and Google jointly disclosed eight HTTP/2 implementation flaws in August 2019, tracked as CVE-2019-9511 through CVE-2019-9518 and given names like "Data Dribble," "Ping Flood," "Resource Loop," and "0-Length Headers Leak." Each exploited a different corner of frame handling — for example, "Ping Flood" sent a continuous stream of PING frames to force the server to generate acknowledgements faster than it could process real traffic, while "0-Length Headers Leak" sent many small header frames to inflate server-side memory bookkeeping. The disclosures affected nginx, Apache, and gRPC among others, and every vendor's fix converged on the same idea: cap the rate of specific frame types and reject clients that send abusive frame patterns rather than trusting the protocol's flexibility by default. That convergence — rate limits, not architecture changes — is exactly the same remediation shape both Rapid Reset and CONTINUATION Flood ended up needing five years later.

What concrete server settings actually stop these attack classes?

The fixes cluster around a small set of levers that every major web server and proxy now exposes, whether or not it's turned on by default. First, enforce SETTINGS_MAX_CONCURRENT_STREAMS at a conservative value and, critically, track streams that were reset by the client so a rapid open/reset cycle counts against a connection-level limit rather than resetting the counter. Second, cap the number and cumulative size of CONTINUATION frames permitted per header block before the connection is terminated — this is the direct fix for the 2024 flood class. Third, apply hard ceilings on request header size and count per connection, independent of any single frame type, so no single field can be abused to exhaust memory. Fourth, rate-limit control frames like PING and RST_STREAM per connection per second, which closes the 2019-era flood variants. Finally, push connection-level throttling and anomaly detection in front of the application layer — at a reverse proxy or CDN — so abusive patterns get dropped before they reach application servers at all, which is how Cloudflare, Google, and AWS absorbed record-setting Rapid Reset volumes without their origins ever seeing the full flood.

How should a team verify its own HTTP/2 stack is actually patched?

Patch level alone doesn't guarantee protection, because each of these CVEs was fixed independently per implementation rather than in the HTTP/2 specification itself — a server on a version that predates its vendor's fix for CVE-2023-44487 or CVE-2024-27316 is exposed regardless of how recent the overall release looks. Start by checking release notes for the exact CVE identifiers against your nginx, Apache httpd, Envoy, HAProxy, or language-runtime HTTP/2 library version, since some ecosystems (like Node.js) shipped the CONTINUATION Flood fix as a runtime update rather than a web-server config change. Then confirm the mitigating settings are actually enabled rather than just available — several servers shipped the Rapid Reset fix as an opt-in flag before making it default behavior in a later release. Load-testing with a controlled rapid-reset or continuation-flood simulator against a staging environment, capped well below production capacity, is the only way to confirm the limits are enforced rather than merely configured.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.