HTTP M. Thomson Internet-Draft Mozilla Intended status: Standards Track L. Pardue Expires: 9 May 2024 Cloudflare 6 November 2023 Using HTTP/3 Stream Limits in HTTP/2 draft-thomson-httpbis-h2-stream-limits-00 Abstract A variant mechanism for managing stream limits is described for HTTP/2. This scheme is based on that used in QUIC and is more robust against certain patterns of abuse. About This Document This note is to be removed before publishing as an RFC. The latest revision of this draft can be found at https://martinthomson.github.io/h2-stream-limits/draft-thomson- httpbis-h2-stream-limits.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-thomson- httpbis-h2-stream-limits/. Discussion of this document takes place on the HTTP Working Group mailing list (mailto:ietf-http-wg@w3.org), which is archived at https://lists.w3.org/Archives/Public/ietf-http-wg/. Source for this draft and an issue tracker can be found at https://github.com/martinthomson/h2-stream-limits. Status of This Memo This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79. Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet- Drafts is at https://datatracker.ietf.org/drafts/current/. Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress." Thomson & Pardue Expires 9 May 2024 [Page 1] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 This Internet-Draft will expire on 9 May 2024. Copyright Notice Copyright (c) 2023 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 2. Conventions and Definitions . . . . . . . . . . . . . . . . . 3 3. The HTTP/2 MAX_STREAMS Frame . . . . . . . . . . . . . . . . 4 3.1. Applying Stream Limits . . . . . . . . . . . . . . . . . 5 3.2. Negotiating MAX_STREAMS Usage . . . . . . . . . . . . . . 5 4. Security Considerations . . . . . . . . . . . . . . . . . . . 6 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 6 6. References . . . . . . . . . . . . . . . . . . . . . . . . . 6 6.1. Normative References . . . . . . . . . . . . . . . . . . 6 6.2. Informative References . . . . . . . . . . . . . . . . . 7 Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 7 Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 7 1. Introduction HTTP/2 allows endpoints to declare the concurrency limit for streams created by their peer (SETTINGS_MAX_CONCURRENT_STREAMS; see Section 5.1.2 of [HTTP/2]). Initially, the stream concurrency limit is only bounded by the maximum number of streams that can be created, which is 2^30 for each endpoint, but the value can be changed at any time. Most endpoints set a smaller value in an attempt to protect the resources that are committed when processing a stream. This limit is not effective in the case that streams are quickly cancelled. The creator of a stream can cancel it using the RST_STREAM frame. The creator of a stream could also cause its peer to send RST_STREAM by purposefully sending frames that violate HTTP/2 rules, unless errors also cause the peer to close the connection. Either of these methods has deterministic and immediate effect, which means that the stream no longer counts against the concurrent stream Thomson & Pardue Expires 9 May 2024 [Page 2] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 limit. This means that a malicious endpoint can create or cancel an unbounded number of streams as long as its peer does not set a limit of zero. For clarity, we'll refer to either of these methods as "cancelling". If the creation of the stream results in the expenditure of resources, rapidly creating and cancelling streams can exhaust resources. For a server, clients that create and cancel many requests can effectively deny service; for a client, reserving and cancelling promised streams might have similar effect if a client does not disable server push using the SETTINGS_ENABLE_PUSH setting. This creates a denial of service exposure for which a remedy is not supported in the protocol. However, as noted in Section 10.5 of [HTTP/2], many of the features in HTTP/2 that have some potential to create denial of service attacks also have constructive uses. Distinguishing constructive and destructive uses is often challenging. Some applications of HTTP might find that cancelling many requests is necessary; if cancellation is treated as abusive, it is possible that the treatment necessary to prevent attacks might unintentionally punish some clients. The QUIC protocol [QUIC] on which HTTP/3 [HTTP/3] is built contains an alternative mechanism for limiting concurrency. The scheme in QUIC, as described in Section 4.6 of [QUIC], does not set a concurrent stream limit, but instead relies on a peer increasing the maximum allowed stream identifier. An endpoint cannot create new streams immediately after cancelling an open stream; their peer needs to send a message to make more streams available. In QUIC therefore, a malicious endpoint can only create and cancel a finite number of streams, after which their peer needs to provide consent to continue. This document ports the QUIC stream concurrency limit mechanisms to HTTP/2. As use of this system is voluntary and therefore not necessarily guaranteed, this does not prevent abusive use of stream cancellation. However, deployment of this mechanism in popular implementations might allow endpoints to deploy more aggressive strategies for managing abuse in its absence. 2. Conventions and Definitions The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. Thomson & Pardue Expires 9 May 2024 [Page 3] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 3. The HTTP/2 MAX_STREAMS Frame The MAX_STREAMS frame (type=0xTBD) is used to limit the streams that a recipient is permitted to create. The format of the MAX_STREAMS frame is illustrated in Figure 1, using the notation defined in Section 1.3 of [QUIC]. MAX_STREAMS Frame { Length (24) = 0x04, Type (8) = 0x0TBD, Unused Flags (8), Reserved (1), Stream Identifier (31) = 0, Reserved (1), Maximum Stream Identifier (31), } Figure 1: MAX_STREAMS Frame Format In addition to the common HTTP/2 frame header (see Section 4 of [HTTP/2]), the MAX_STREAMS contains a one-bit reserved field and a 31-bit Maxmimum Stream Identifier field. The Reserved field MUST be set to zero when sending and ignored on receipt. The Maximum Stream Identifier field contains the maximum value of stream identifier that a recipient of this frame can use when it creates or reserves a stream; see Section 5.1 of [HTTP/2] for how streams are created. A MAX_STREAMS frame MUST be sent on stream 0. Receipt of a MAX_STREAMS frame on any other stream MUST be treated as a connection error of type PROTOCOL_ERROR; see Section 5.4.1 of [HTTP/2]. An endpoint MUST treat receipt of a MAX_STREAMS frame with a length other than 4 as a connection error of type FRAME_SIZE_ERROR; see Section 5.4.1 of [HTTP/2]. Thomson & Pardue Expires 9 May 2024 [Page 4] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 A client MUST treat receipt of an even-numbered Maximum Stream Identifier as a connection error of type PROTOCOL_ERROR; see Section 5.4.1 of [HTTP/2], with an exception of a value of 0, which can be used to indicate support for the feature without enabling the creation of streams (see Section 3.2). Similarly, a server MUST treat receipt of an odd-numbered Maximum Stream Identifier as a connection error. 3.1. Applying Stream Limits An endpoint that receives a MAX_STREAMS frame MUST NOT create or reserve a stream with a number that exceeds the value of the Maximum Stream Identifier field from that frame, until it receives a MAX_STREAMS frame with a larger value. An endpoint MUST treat the creation or reservation of a stream with a higher valued stream identifier than it included in a MAX_STREAMS frame as a connection error of type FLOW_CONTROL_ERROR; see Section 5.4.1 of [HTTP/2]. Endpoints can only increase the value that they include in a MAX_STREAMS frame. An endpoint MUST treat receipt of a Maximum Stream Identifier that is equal to or smaller than a value that it has previously received as a connection error of type PROTOCOL_ERROR; see Section 5.4.1 of [HTTP/2]. Note that a value of 0 can be sent one time by either client or server to indicate support for this feature without permitting the creation of streams; see Section 3.2. An implementation can support a similar concurrency limit to that provided by SETTINGS_MAX_CONCURRENT_STREAMS. The initial value can be set to twice the value of SETTINGS_MAX_CONCURRENT_STREAMS, with a client adding 1 if the value is non-zero. The endpoint then increases the value of the Maximum Stream Identifier field as the streams its peer initiates are closed. An endpoint can avoid sending redundant MAX_STREAMS frames by processing all incoming data before increasing the maximum. This approach differs from SETTINGS_MAX_CONCURRENT_STREAMS in that a peer is not able to create and cancel streams arbitrarily, as new streams do not become available until after receiving a MAX_STREAMS frame. 3.2. Negotiating MAX_STREAMS Usage This extension is not negotiated using the SETTINGS frame. Instead, the receipt of a MAX_STREAMS frame indicates support for the feature. An endpoint that supports this extension MUST send a MAX_STREAMS frame after establishing a connection, after the HTTP/2 connection preface (Section 3.4 of [HTTP/2]). When a MAX_STREAMS frame is Thomson & Pardue Expires 9 May 2024 [Page 5] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 received, the endpoint MUST subsequently only create streams according to the rules in Section 3.1 and ignore any value of the SETTINGS_MAX_CONCURRENT_STREAMS setting. 4. Security Considerations HTTP/2 considered the cancellation of a stream to reclaim the resources that might have been committed during its creation. The stream limits in HTTP/2 therefore did not provide a means to limit stream creation. Though cancellation is a potential source of abusive traffic, it was not explicitly mentioned (see Section 10.5 of [HTTP/2]). However, experience has shown that the creation of a stream has costs that cannot always be recovered when that stream is cancelled. The use of the MAX_STREAMS frame provides endpoints with a means of limiting stream creation, using a method that has proven to be effective in QUIC. However, repeated use of the MAX_STREAMS frame is also a potential source of abuse, as described in Section 10.5 of [HTTP/2]. Though processing a MAX_STREAMS frame is likely to be trivial, receiving significantly more MAX_STREAMS frames than the number of streams that have been closed might indicate an attempt to waste effort. 5. IANA Considerations This document registers a new entry in the "HTTP/2 Frame Type" registry, as documented in Section 11 of [HTTP/2]. This entry has the following values. Frame Type: MAX_STREAMS Code: 0xTBD Specification: Section 3 6. References 6.1. Normative References [HTTP/2] Thomson, M., Ed. and C. Benfield, Ed., "HTTP/2", RFC 9113, DOI 10.17487/RFC9113, June 2022, . [QUIC] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, DOI 10.17487/RFC9000, May 2021, . Thomson & Pardue Expires 9 May 2024 [Page 6] Internet-Draft Using HTTP/3 Stream Limits in HTTP/2 November 2023 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . 6.2. Informative References [CVE-2023-44487] "HTTP/2 Rapid Reset CVE Record", 10 October 2023, . [HTTP/3] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114, June 2022, . Acknowledgments This document is written in response to the problems discovered as part of [CVE-2023-44487], so maybe those behind the botnet responsible for that attack deserve some credit. Authors' Addresses Martin Thomson Mozilla Email: mt@lowentropy.net Lucas Pardue Cloudflare Email: lucaspardue.24.7@gmail.com Thomson & Pardue Expires 9 May 2024 [Page 7]