Internet DRAFT - draft-thomson-httpbis-h2-stream-limits
draft-thomson-httpbis-h2-stream-limits
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,
<https://www.rfc-editor.org/rfc/rfc9113>.
[QUIC] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based
Multiplexed and Secure Transport", RFC 9000,
DOI 10.17487/RFC9000, May 2021,
<https://www.rfc-editor.org/rfc/rfc9000>.
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,
<https://www.rfc-editor.org/rfc/rfc2119>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/rfc/rfc8174>.
6.2. Informative References
[CVE-2023-44487]
"HTTP/2 Rapid Reset CVE Record", 10 October 2023,
<https://www.cve.org/CVERecord?id=CVE-2023-44487>.
[HTTP/3] Bishop, M., Ed., "HTTP/3", RFC 9114, DOI 10.17487/RFC9114,
June 2022, <https://www.rfc-editor.org/rfc/rfc9114>.
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]