Summary

  • Rapid Reset opened an HTTP/2 request and cancelled it immediately, freeing the protocol’s concurrency slot while proxy or backend work could continue.
  • The durable defence was to count useful and cancelled work across the connection, end abusive connections early and protect downstream queues without taking legitimate cancellation away from ordinary clients.

The stream closed before the work did

HTTP/2 earned its efficiency by placing many independent request streams on one transport connection. A browser can fetch page components in parallel without paying for a new TCP and TLS setup each time. A server can advertise SETTINGS_MAX_CONCURRENT_STREAMS to say how many streams the peer may keep active at once.

The limit counts streams that remain open or half-closed. It does not count a stream after RST_STREAM moves it to closed. That rule is useful. A person who leaves a page, an application whose timeout expires or a client that no longer needs a resource should be able to cancel it without destroying every other exchange on the connection.

Rapid Reset made the distinction between protocol state and resource state operationally decisive. The attacker sent request HEADERS and then immediately sent RST_STREAM. From the state machine’s perspective, the stream disappeared and its concurrency slot became available. The same connection could open another request without waiting for a response or a network round trip.

The receiver could not always erase the corresponding work at the same speed. It might already have allocated stream state, decompressed headers, selected a route, loaded customer policy or dispatched the request to another service. A reverse proxy could record the cancellation locally while an upstream job remained queued or running. The client paid for a small pair of frames. The infrastructure paid for setup, dispatch, notification and teardown.

This was not a bypass of TLS, a forged response or a request that exceeded the advertised number of simultaneous streams. The attack repeatedly reused a slot by closing each stream before concurrency accounting could restrain the rate. Google’s technical analysis described the resulting request rate as constrained principally by available bandwidth rather than round-trip time.

Three providers saw different peaks

Google, Cloudflare and AWS detected the campaign in late August 2023 and coordinated disclosure with HTTP/2 implementers. Public disclosure arrived on 10 October under CVE-2023-44487.

Their numbers must remain separate. Google reported an attack above 398 million requests per second. Cloudflare reported a peak just over 201 million requests per second from a botnet of roughly 20,000 machines. AWS reported an unusual CloudFront spike above 155 million requests per second on 28–29 August.

Those observations did not describe one jointly measured event. They used different networks, telemetry and customer surfaces. The figures establish that the technique operated at exceptional scale, not that every HTTP/2 server needed to absorb the largest number or that all providers suffered the same effect.

Google said its largest attack was largely stopped at the edge and did not cause an outage. Cloudflare reported initial customer impact affecting roughly one per cent of requests overall, with short peaks around twelve per cent in its most affected data centres during the most serious event. The different outcomes are evidence of architecture and mitigation, not a contradiction.

Concurrency was the wrong account

SETTINGS_MAX_CONCURRENT_STREAMS protects simultaneous state. Rapid Reset consumed sequential work at extreme speed. A stream could be created, charged to concurrency, cancelled and removed from that account while its resource consequences outlived it.

Merely lowering the advertised concurrency therefore could not solve the class. It could reduce the burst, but the attacker could continue to churn closed streams. Worse, a locally sensible number could conflict with deployed client behaviour.

Cloudflare reduced its maximum concurrency to 64 while responding. It then found that legitimate clients commonly started up to 100 requests before receiving the server’s SETTINGS. The excess streams were reset by the server. An older protection that counted server resets interpreted the resulting pattern as abuse and closed legitimate connections, producing page-load failures. Cloudflare restored the value to 100.

The episode is more instructive than a perfect patch narrative. A configuration can tighten a formal limit and still reduce real security if it creates false positives at scale. The correct operating boundary is not the smallest number. It is the smallest tested budget that preserves known legitimate behaviour while stopping work amplification before shared queues saturate.

The connection became the unit of judgment

Google’s mitigation analysis argued that blocking individual requests was insufficient. The server needed to evaluate the connection: how many streams it created, how many it cancelled, how much useful work completed and whether the peer repeatedly violated limits. Once the pattern became abusive, the server could send a restrictive GOAWAY or close the connection immediately.

This changes the authority relationship. A client retains the right to withdraw interest in one response. It does not retain an unconditional right to keep the transport relationship after using cancellation to impose unbounded work. The receiver owns the machine and the connection admission decision.

Cloudflare extended existing protections to client-sent resets, improved frame processing and cancellation propagation, changed queuing and scheduling, and moved detection earlier in its TLS proxy. Earlier rejection mattered because every hop after acceptance multiplied the cost. It also expanded connection-level logging after finding that some 502 errors occurred before the business-logic proxy that generated normal customer analytics. An error hidden from the usual dashboard is still an operational failure.

These measures did not require every provider to choose the same counter, ratio or scheduler. Google described connection statistics and immediate shutdown. Cloudflare combined reset-rate detection with processing-path changes. AWS relied on its edge capacity and automatic protections while issuing service-specific guidance. The common rule was bounded work at the relying endpoint, not a universal implementation.

Standards named the states, not the debt

RFC 9113 defines multiplexing, stream concurrency, RST_STREAM and GOAWAY. Its shared state machine makes independent implementations interoperable. It also made cancellation deterministic: after reset, the stream is closed and no longer counts toward the peer’s concurrency limit.

The specification could not make already dispatched work vanish. A 2023 individual Internet-Draft on HTTP/2 stream limits described the gap and proposed cumulative credit so that cancellation would not immediately restore unlimited capacity. The draft is useful evidence of the design problem. It was not an adopted standard and does not establish IETF consensus.

That distinction follows Heng Lu’s Minimum Initial Specification principle. The common layer needs enough precision to exchange frames and preserve legitimate cancellation. The future resource decision belongs first to the endpoint that bears the cost. Implementations can demonstrate safe connection budgets in running code, and successful practices can later inform a shared rule without pretending that one provider’s proxy graph is universal.

What a patched inventory proves

“HTTP/2 enabled” is not an exposure assessment, and “CVE patched” is not a service-continuity proof. Operators need to know where HTTP/2 terminates, which component first allocates expensive state, whether cancellation reaches every downstream hop and which queue remains shared with ordinary requests.

A defensible inventory names the CDN, load balancer, ingress controller, service mesh, reverse proxy and application server; records exact versions and patch provenance; and identifies which component owns the connection budget. Tests should mix ordinary page loads, legitimate cancellation and hostile open-reset churn. Success means that normal work advances while the abusive connection ends and the event appears in telemetry.

Disabling HTTP/2 can be an emergency containment choice when no safe update exists. It should have an owner, a narrow scope, an expiry and evidence for restoration. Otherwise a temporary availability measure discards multiplexing indefinitely and conceals whether the work-accounting defect was ever repaired.

Evidence limits

The reviewed record does not identify every target, implementation or loss. Provider peak rates are not directly comparable capacity benchmarks. A cloud edge absorbing the traffic does not prove an unprotected application server would do so, and a vendor patch does not prove that every downstream package or fleet deployed it on disclosure day.

What the evidence establishes is narrower and more useful. Closing a protocol object is not the same as reclaiming the work it caused. The party that accepts the work must preserve the authority to end the relationship when formal compliance becomes resource abuse.

Sources