HTTP/2 Rapid Reset: How One Frame Enabled Record-Breaking DDoS Attacks
Rapid Reset (CVE-2023-44487) leverages HTTP/2 multiplexing for record-breaking L7 attacks. We explain the stream mechanism, RST_STREAM and defense.
- AUTHOR
- Karol Rapacz / CEO of Breachroad · OSCP · PNPT
- PUBLISHED
- 4 July 2026
- READING TIME
- 11 min read
- TOPIC
- Penetration Testing and AppSec
DDoS attacks on the application layer (L7) rarely break records - it’s usually the volumetric floods from the network layer that make the headlines. HTTP/2 Rapid Reset (CVE-2023-44487) was an exception: it achieved record highs of hundreds of millions of requests per second by exploiting not a code vulnerability but a design feature of HTTP/2. This is a great example of a feature becoming a weapon. Let’s take it apart.
Quick reminder: streams in HTTP/2
In HTTP/1.1, one TCP connection handled one request at a time (or pipelining, which didn’t work in practice). HTTP/2 introduced multiplexing: many independent streams operate within one TCP connection, and data travels in frames - HEADERS, DATA, RST_STREAM and others. This allows the browser to download dozens of resources in parallel without opening dozens of connections.
The server protects itself against abuse with the SETTINGS_MAX_CONCURRENT_STREAMS parameter - the maximum number of simultaneously active streams per connection (typically 100-128). This seems like enough protection. And here’s the catch.
Attack Mechanism: Open and immediately cancel
The client can cancel the stream at any time by sending the frame RST_STREAM. This is normal - the browser does this when, for example, the user stops loading. Rapid Reset abuses exactly this:
- The attacker opens the stream with the frame
HEADERS(full request: method, path, headers). - Immediately sends
RST_STREAM, canceling this stream. - Since the stream is already canceled, it does not count towards the
MAX_CONCURRENT_STREAMSlimit. - The attacker can therefore repeat step 1-2 in a loop, thousands of times on a single connection, without being limited by the concurrency limit.
The crux of the problem: server continues to work despite cancellation. Before RST_STREAM arrives, the request has already been accepted, parsed, and often forwarded to the backend or application (working on the proxy and origin side). The attacker pays pennies (sending two small frames) and the server pays the full cost of handling the request - millions of times over anyway. A few hundred connections are enough to generate a volume that would previously require a huge botnet.
client → server: HEADERS (stream 1) # request
client → server: RST_STREAM (stream 1) # immediate cancellation
client → server: HEADERS (stream 3)
client → server: RST_STREAM (stream 3)
... (thousands of times over one connection)
Why was it so dangerous
Three factors contributed to the record:
- Cost asymmetry. Sending a request is cheap, serving is expensive. Rapid Reset maximizes this asymmetry.
- Bypassing classic limits. Limits based on the number of active streams or connections do not catch the attack because the streams disappear immediately and there are few connections.
- Commonness. The very implementation of HTTP/2 support in most servers and proxies (nginx, Apache, Go-based servers, Node, CDN layers) was vulnerable, so the attack worked almost everywhere.
It is worth emphasizing: this is a L7 attack, hitting application resources (CPU, threads, connections to the backend), not just bandwidth. That’s why simply “passing traffic” doesn’t help - you need to distinguish between abuse and legitimate traffic. A similar “low attacker effort, high victim cost” logic can be seen in critical infrastructure attacks.
Defense: What actually works
1. Software update. Server and proxy vendors have released patches that change stream accounting and detect abuse. This is a mandatory first step - check if your HTTP/2 server, reverse proxy and libraries are up to date with the CVE-2023-44487 patch.
2. Reset limit per connection. Key defensive change: count cancelled stream rate. If the number of RST_STREAM on one connection (especially right after HEADERS) exceeds the threshold, the connection should be closed (GOAWAY). This takes away the offense’s leverage.
3. Limit on the total number of streams per connection. Not just simultaneous, but all in the connection lifecycle - when exceeded, we close the connection.
4. CDN/WAF layer with HTTP/2 flood protection. Large vendors (Cloudflare, etc.) have implemented dedicated Rapid Reset detection. If you use a CDN, make sure this protection is enabled - our scanner shows, among others: presence of a CDN/WAF layer in front of your domain.
5. Rate limiting on the application side. Per-IP and per-connection limits, although not sufficient in themselves, increase the cost of the attack.
Continuation of the story: CONTINUATION flood
It’s worth knowing your successor. In 2024, the HTTP/2 CONTINUATION flood family of vulnerabilities was disclosed: an attacker sends a stream of CONTINUATION (continuation headers) frames without the END_HEADERS flag, forcing the server to cache a growing set of headers - leading to memory or CPU exhaustion. The mechanics are different, the moral is the same: stateful multiplexing protocols have non-obvious abuse paths, and defense requires hard limits at every parsing stage.
Conclusions for the team
Rapid Reset showed that protocol security is not just about “if there is a vulnerability in the code”, but “how the feature behaves under malicious load”. Practical minimum:
- Keep HTTP/2 servers, proxies and libraries up to date - this is part of the vulnerability management process.
- Implement limits on resets and total streams per connection.
- Place an L7 flood detection layer in front of the application.
- Test the application’s resistance to protocol abuse, not only to classic vulnerabilities - this is an element of infrastructure penetration testing.
Security headers will not protect against DDoS, but their correct configuration is the foundation of web layer hygiene - more in guide to HTTP headers. If you want to check the resilience of your infrastructure against L7 attacks, let’s talk.
Frequently asked questions (FAQ)
Should we disable HTTP/2 to protect ourselves? No. HTTP/2 (and HTTP/3) has real performance benefits, and turning it off is going backwards rather than fixing it. The right answer is to update the software and implement reset and stream limits - all major implementations already have mechanisms in place.
Will a regular firewall stop Rapid Reset? Classic network firewall (L3/L4) does not - the attack looks like legitimate, encrypted HTTP/2 traffic on port 443. You need protection that understands the application layer protocol: an updated server, WAF or CDN with HTTP/2 flood detection.
How to check if we are susceptible? Start with the version: whether the server, reverse proxy and HTTP/2 libraries are patched for CVE-2023-44487. Then verify the configuration of stream limits and resets and whether there is a layer with L7 protection in front of the application. A load test simulating the “open/reset” pattern will show real resistance.
Does HTTP/3 solve this problem? HTTP/3 (over QUIC) also multiplexes streams and also requires proper cancellation limiting - it is not generally immune to this class of abuse. Security depends on implementation and configuration, not on the protocol version number.


