RFC 9368 | QUIC-Compatible VN | May 2023 |
Schinazi & Rescorla | Standards Track | [Page] |
QUIC does not provide a complete version negotiation mechanism but instead onlyprovides a way for the server to indicate that the version the client chose isunacceptable. This document describes a version negotiation mechanism thatallows a client and server to select a mutually supported version. Optionally,if the client's chosen version and the negotiated version share a compatiblefirst flight format, the negotiation can take place without incurring an extraround trip. This document updates RFC 8999.¶
This is an Internet Standards Track document.¶
This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 7841.¶
Information about the current status of this document, any errata, and how to provide feedback on it may be obtained athttps://www.rfc-editor.org/info/rfc9368.¶
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.¶
The version-invariant properties of QUIC[QUIC-INVARIANTS] define aVersion Negotiation packet but do not specify how an endpoint reacts when itreceives one. QUIC version 1[QUIC] allows the server to use aVersion Negotiation packet to indicate that the version the client chose isunacceptable, but it doesn't allow the client to safely make use of thatinformation to create a new connection with a mutually supported version.This document updates[QUIC-INVARIANTS] by defining versionnegotiation mechanisms that leverage the Version Negotiation packet.¶
With proper safety mechanisms in place, the Version Negotiation packet can bepart of a mechanism to allow two QUIC implementations to negotiate between twototally disjoint versions of QUIC. This document specifies version negotiationusing Version Negotiation packets, which adds an extra round trip to connectionestablishment if needed.¶
It is beneficial to avoid additional round trips whenever possible, especiallygiven that most incremental versions are broadly similar to the previousversion. This specification also defines a simple version negotiation mechanism which leverages similarities between versions and can negotiate between"compatible" versions without additional round trips.¶
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.¶
The document uses the following terms:¶
This document specifies two means of performing version negotiation:1) "incompatible", which requires a round trip and is applicable to all versions,and 2) "compatible", which allows saving the round trip but only applies when theversions are compatible (seeSection 2.2).¶
The client initiates a QUIC connection by choosing an Original Version andsending a first flight of QUIC packets with a long header to the server[QUIC-INVARIANTS]. The client's first flight includes Version Information (seeSection 3), which will be used to optionally enable compatible versionnegotiation (seeSection 2.3) and to prevent version downgrade attacks (seeSection 4).¶
Upon receiving this first flight, the server verifies whether it knows how toparse first flights from the Chosen Version (which is also the Original Version in this case). If it does not, then it startsincompatible version negotiation (seeSection 2.1), which causes the clientto initiate a new connection with a different version. For instance, if theclient initiates aconnection with version A that the server can't parse, the serverstarts incompatible version negotiation; then, when the clientinitiates a new connection with version B, we say that the firstconnection's client Chosen Version is A, the second connection'sclient Chosen Version is B, and the Original Version for the entiresequence is A.¶
If the server can parse the first flight, it can establish the connectionusing the client's Chosen Version, or itMAY select any other compatibleversion, as described inSection 2.3.¶
Note that it is possible for a server to have the ability to parse the firstflight of a given version without fully supporting it, in the sense that itimplements enough of the version's specification to parse first flight packetsbut not enough to fully establish a connection using that version.¶
The server starts incompatible version negotiation by sending a VersionNegotiation packet. This packetSHALL include each entry from the server's setof Offered Versions (seeSection 5) in a Supported Version field. TheserverMAY add reserved versions (as defined inSection 6.3 of [QUIC]) inSupported Version fields.¶
Clients will ignore a Version Negotiation packet if it contains the OriginalVersion attempted by the client, as required bySection 4. The client also ignores aVersion Negotiation packet that contains incorrect connection ID fields, as required bySection 6 of [QUIC-INVARIANTS].¶
Upon receiving the Version Negotiation packet, the clientSHALL search for aversion it supports in the list provided by the server. If it doesn't find one,itSHALL abort the connection attempt. Otherwise, itSHALL select a mutuallysupported version and send a new first flight with that version -- this versionis now the Negotiated Version.¶
The new first flight will allow the endpoints to establish a connection usingthe Negotiated Version. The handshake of the Negotiated Version will exchangeVersion Information (seeSection 3) that is required to ensure that versionnegotiation was genuine, i.e., that no attacker injected packets in order toinfluence the version negotiation process (seeSection 4).¶
Only servers can start incompatible version negotiation. ClientsMUST NOT sendVersion Negotiation packets and serversMUST ignore all received VersionNegotiation packets.¶
If A and B are two distinct versions of QUIC, A is said to be "compatible" withB if it is possible to take a first flight of packets from version A and convertit into a first flight of packets from version B. As an example, if versions Aand B are absolutely equal in their wire image and behavior during the handshakebut differ after the handshake, then A is compatible with B and B is compatiblewith A. Note that the conversion of the first flight can be lossy; some data,such as QUIC version 1 0-RTT packets, could be ignored during conversion andretransmitted later.¶
Version compatibility is not symmetric. It is possible for version A to becompatible with version B and for version B not to be compatible with version A. This couldhappen, for example, if version B is a strict superset of version A, i.e., if version Aincludes the concept of streams and STREAM frames and version B includes theconcept of streams and the hypothetical concept of tubes along with STREAM andTUBE frames, then A would be compatible with B, but B would not be compatiblewith A.¶
Note that version compatibility does not mean that every single possibleinstance of a first flight will succeed in conversion to the other version. Afirst flight using version A is said to be "compatible" with version B if twoconditions are met: (1) version A is compatible with version B and(2) the conversion of this first flight to version B is well defined.For example, if version B is equal to version A in all aspects except it introduced anew frame in its first flight that version A cannot parse or even ignore, then version Bcould still be compatible with version A, as conversions would succeed for connectionswhere that frame is not used. In this example, first flights using version Bthat carry this new frame would not be compatible with version A.¶
When a new version of QUIC is defined, it is assumed to not be compatible withany other version unless otherwise specified. Similarly, no other version iscompatible with the new version unless otherwise specified. ImplementationsMUST NOT assume compatibility between versions unless explicitly specified.¶
Note that both endpoints might disagree on whether two versions are compatibleor not. For example, two versions could have been defined concurrently and thenspecified as compatible in a third document much later -- in that scenario, oneendpoint might be aware of the compatibility document, while the other may not.¶
When the server can parse the client's first flight using the client's ChosenVersion, it can extract the client's Version Information structure (seeSection 3). This contains the list of versions that the client knows itsfirst flight is compatible with.¶
In order to perform compatible version negotiation, the serverMUST select oneof these versions that it (1) supports and (2) knows the client's ChosenVersion is compatible with. This selected version is now the NegotiatedVersion. After selecting it, the server attempts to convert the client's firstflight into that version and replies to the client as if it had received theconverted first flight.¶
If those formats are identical, as in cases where the Negotiated Version is thesame as the client's Chosen Version, then this will be the identity transformation.If the first flight is correctly formatted, then this conversion process cannotfail by definition of the first flight being compatible; if the server is unableto convert the first flight, itMUST abort the handshake.¶
If a document specifies that a QUIC version is compatible with another, thatdocumentMUST specify the mechanism by which clients are made aware of theNegotiated Version. An example of such a mechanism is to have the clientdetermine the server's Negotiated Version by examining the QUIC long headerVersion field. Note that, in this example mechanism, it is possible for theserver to initially send packets with the client's Chosen Version beforeswitching to the Negotiated Version (this can happen when the client's VersionInformation structure spans multiple packets; in that case, the server mightacknowledge the first packet in the client's Chosen Version and later switch toa different Negotiated Version). Mutually compatible versionsSHOULD use thesame mechanism.¶
Note that, after the first flight is converted to the Negotiated Version, thehandshake completes in the Negotiated Version. If the Negotiated Version hasrequirements that apply during the handshake, those requirements apply to theentire handshake, including the converted first flight. In particular, if theNegotiated Version mandates that endpoints perform validations on Handshakepackets, endpointsMUST also perform such validations on the converted firstflight. For instance, if the Negotiated Version requires that the 5-tuple remain stable for the entire handshake (as QUIC version 1 does), then both endpoints need to validate the 5-tuple of all packets received during the handshake, including the converted first flight.¶
Note also that the client can disable compatible version negotiation by onlyincluding the Chosen Version in the Available Versions field of the VersionInformation (seeSection 3).¶
If the server does not find a compatible version (including the client's ChosenVersion), it will perform incompatible version negotiation instead (seeSection 2.1).¶
Note that it is possible to have incompatible version negotiation followed bycompatible version negotiation. For instance, if version A is compatible with version Band version C is compatible with version D, the following scenario could occur:¶
Client ServerChosen = A, Available Versions = (A, B) -------------><------------------------ Version Negotiation = (D, C)Chosen = C, Available Versions = (C, D) -------------><------------- Chosen = D, Available Versions = (D, C)
In this example, the client selected C from the server's Version Negotiationpacket, but the server preferred D and then selected it from the client's offer.¶
QUIC connections are shared state between a client and a server[QUIC-INVARIANTS]. The compatible version negotiation mechanism defined inthis document (seeSection 2.3) is performed as part of a single QUICconnection; that is, the packets with the client's Chosen Version are part ofthe same connection as the packets with the Negotiated Version.¶
In comparison, the incompatible version negotiation mechanism, which leveragesQUIC Version Negotiation packets (seeSection 2.1), conceptually operatesacross two QUIC connections, i.e., the connection attempt prior to receiving theVersion Negotiation packet is distinct from the connection with the incompatibleversion that follows.¶
Note that this separation across two connections is conceptual, i.e., it applies tonormative requirements on QUIC connections, but it does not require implementationsto internally use two distinct connection objects.¶
When the client picks its Original Version, itSHOULD try to avoid incompatibleversion negotiation to save a round trip. Therefore, the clientSHOULD pick anOriginal Version to maximize the combined probability that both:¶
Without additional information, this could mean selecting the oldest versionthat the client supports while advertising newer compatible versions in theclient's first flight.¶
During the handshake, endpoints will exchange Version Information, whichconsists of a Chosen Version and a list of Available Versions. Any version ofQUIC that supports this mechanismMUST provide a mechanism to exchange VersionInformation in both directions during the handshake, such that this data is authenticated.¶
In QUIC version 1, the Version Information is transmitted using a newversion_information transport parameter (seeSection 7.4 of [QUIC]). Thecontents of Version Information are shown below (using the notation fromSection 1.3 of [QUIC]):¶
Version Information { Chosen Version (32), Available Versions (32) ...,}
The content of each field is described below:¶
The version that the sender has chosen to use for this connection. In mostcases, this field will be equal to the value of the Version field in the longheader that carries this data; however, future versions or extensions can chooseto set different values in the long header Version field.¶
The contents of the Available Versions field depend on whether it is sent bythe client or by the server.¶
When sent by a client, the Available Versions field lists all the versionsthat this first flight is compatible with, ordered by descending preference.Note that the version in the Chosen Version fieldMUST be included in this listto allow the client to communicate the Chosen Version's preference. Note thatthis preference is only advisory; serversMAY choose to use their own preferenceinstead.¶
When sent by a server, the Available Versions field lists all theFully Deployed Versions of this server deployment (seeSection 5). Theordering of the versions in this field does not carry any semantics. Notethat the version in the Chosen Version field is not necessarily included in thislist, because the server operator could be in the process of removing supportfor this version. For the same reason, the Available Versions fieldMAY be empty.¶
Clients and serversMAY both include versions following the pattern 0x?a?a?a?ain their Available Versions list. Those versions are reserved to exerciseversion negotiation (seeSection 15 of [QUIC]) and will never beselected when choosing a version to use.¶
A version downgrade is an attack where a malicious entity manages to make theQUIC endpoints negotiate a QUIC version different from the one they would havenegotiated in the absence of the attack. The mechanism described in thisdocument is designed to prevent downgrade attacks.¶
ClientsMUST ignore any received Version Negotiation packets that contain theOriginal Version. A client that makes a connection attempt based on informationreceived from a Version Negotiation packetMUST ignore any Version Negotiationpackets it receives in response to that connection attempt.¶
Both endpointsMUST parse their peer's Version Information during the handshake.If that leads to a parsing failure (for example, if it is too short or ifits length is not divisible by four), then the endpointMUST close theconnection; if the connection was using QUIC version 1, that connection closureMUST use a transport error of type TRANSPORT_PARAMETER_ERROR. If an endpointreceives a Chosen Version equal to zero, or any Available Version equal to zero,itMUST treat it as a parsing failure. If a server receives VersionInformation where the Chosen Version is not included in Available Versions, itMUST treat it as a parsing failure.¶
Every QUIC version that supports version negotiationMUST define a method for closing the connection with a version negotiation error. For QUIC version 1,version negotiation errors are signaled using a transport error of typeVERSION_NEGOTIATION_ERROR (seeSection 10.2).¶
When a server receives a client's first flight, the server will first establishwhich QUIC version is in use for this connection in order to properly parse thefirst flight. This may involve examining data that is not part of the handshake transcript, such as parts of the packet header. When the server then processes the client's VersionInformation, the serverMUST validate that the client's Chosen Version matchesthe version in use for the connection. If the two differ, the serverMUST closethe connection with a version negotiation error.¶
In the specific case of QUIC version 1, the server determines that version 1 is in use by observing that the Version field of the first Long Header packet it receives is set to 0x00000001. Subsequently, if the serverreceives the client's Version Information over QUIC version 1 (as indicated bythe Version field of the Long Header packets that carried the transportparameters) and the client's Chosen Version is not set to 0x00000001, the serverMUST close the connection with a version negotiation error.¶
ServersMAY complete the handshake even if the Version Information is missing. ClientsMUST NOT complete the handshake if they are reacting to a Version Negotiation packet and the Version Information is missing, butMAY do so otherwise.¶
If a client receives Version Information where the server's Chosen Version wasnot sent by the client as part of its Available Versions, the clientMUST closethe connection with a version negotiation error. If a client has reacted to a Version Negotiation packet and the server's Version Information was missing, the clientMUST close the connection with a version negotiation error.¶
If the client received and acted on a Version Negotiation packet, the clientMUST validate the server's Available Versions field. The Available Versionsfield is validated by confirming that the client would have attempted the sameversion with knowledge of the versions the server supports. That is, the clientwould have selected the same version if it received a Version Negotiation packetthat listed the versions in the server's Available Versions field, plus theNegotiated Version. If the client would have selected a different version, theclientMUST close the connection with a version negotiation error. Inparticular, if the client reacted to a Version Negotiation packet and theserver's Available Versions field is empty, the clientMUST close the connectionwith a version negotiation error. These connection closures prevent an attackerfrom being able to use forged Version Negotiation packets to force a versiondowngrade.¶
As an example, let's assume a client supports hypothetical QUIC versions 10, 12,and 14 with a preference for higher versions. The client initiates a connectionattempt with version 12. Let's explore two independent example scenarios:¶
This validation of Available Versions is not sufficient to prevent downgrade.Downgrade prevention also depends on the client ignoring Version Negotiationpackets that contain the Original Version (seeSection 2.1).¶
After the process of version negotiation described in this document completes, the versionin use for the connection is the version that the server sent in the ChosenVersion field of its Version Information. That remains true even if otherversions were used in the Version field of long headers at any point in thelifetime of the connection. In particular, since the client can be made aware of the Negotiated Version by the QUIC longheader version during compatible version negotiation (seeSection 2.3), clientsMUST validate that the server'sChosen Version is equal to the Negotiated Version; if they do not match, theclientMUST close the connection with a version negotiation error. This preventsan attacker's ability to influence version negotiation by forging the long header Versionfield.¶
While this document mainly discusses a single QUIC server, it is common fordeployments of QUIC servers to include a fleet of multiple server instances.Therefore, we define the following terms:¶
This is the set of versions supported by a given server instance. Morespecifically, these are the versions that a given server instance will use if aclient sends a first flight using them.¶
This is the set of versions that a given server instance will send in aVersion Negotiation packet if it receives a first flight from an unknownversion. This set will most often be equal to the Acceptable Versions set,except during short transitions while versions are added or removed (see below).¶
This is the set of QUIC versions that is supported and negotiated by everysingle QUIC server instance in this deployment. If a deployment only contains asingle server instance, then this set is equal to the Offered Versions set,except during short transitions while versions are added or removed (see below).¶
If a deployment contains multiple server instances, software updates may nothappen at exactly the same time on all server instances. Because of this, aclient might receive a Version Negotiation packet from a server instance thathas already been updated, and the client's resulting connection attempt mightreach a different server instance which hasn't been updated yet.¶
However, even when there is only a single server instance, it is still possibleto receive a stale Version Negotiation packet if the server performs itssoftware update while the Version Negotiation packet is in flight.¶
This could cause the version downgrade prevention mechanism described inSection 4 to falsely detect a downgrade attack. To avoid that, serveroperatorsSHOULD perform a three-step process when they wish to add or removesupport for a version, as described below.¶
When adding support for a new version:¶
When removing support for a version:¶
Note that, during the update window, connections are vulnerable to downgrade attacks for Acceptable Versions that are not Fully Deployed. This is because a client cannot distinguish such a downgrade attack from legitimate exchanges with both updated and non-updated server instances.¶
When a client creates a QUIC connection, its goal is to use an application-layerprotocol. Therefore, when considering which versions are compatible, clientswill only consider versions that support one of the intended application-layerprotocols. If the client's first flight advertises multiple Application-LayerProtocol Negotiation (ALPN)[ALPN] tokens and multiple compatibleversions, it is possible for some application-layer protocols to not be able torun over some of the offered compatible versions. It is the server'sresponsibility to only select an ALPN token that can run over the compatibleQUIC version that it selects.¶
A given ALPN tokenMUST NOT be used with a new QUIC version that is different from theversion for which the ALPN token was originally defined, unless all thefollowing requirements are met:¶
When incompatible version negotiation is in use, the second connection that is created in response to the received Version Negotiation packetMUST restart its application-layer protocol negotiation process without taking into account the Original Version.¶
In order to facilitate the deployment of future versions of QUIC, designers offuture versionsSHOULD attempt to design their new version such that commonlydeployed versions are compatible with it.¶
QUIC version 1 defines multiple features which are not documented in the QUICinvariants. Since, at the time of writing, QUIC version 1 is widely deployed,this section discusses considerations for future versions to help withcompatibility with QUIC version 1.¶
QUIC version 1 features Retry packets, which the server can send to validate theclient's IP address before parsing the client's first flight. A server thatsends a Retry packet can do so before parsing the client's first flight. Therefore, aserver that sends a Retry packet might not have processed the client'sVersion Information before doing so.¶
If a future document wishes to define compatibility between two versions thatsupport Retry, that documentMUST specify how version negotiation (bothcompatible and incompatible) interacts with Retry during a handshake thatrequires both. For example, that could be accomplished by having the serverfirst send a Retry packet in the Original Version, thereby validating theclient's IP address before attempting compatible version negotiation. If bothversions support authenticating Retry packets, the compatibility definitionneeds to define how to authenticate the Retry in the Negotiated Versionhandshake even though the Retry itself was sent using the client's ChosenVersion.¶
QUIC version 1 uses TLS 1.3, which supports session resumption by sendingsession tickets in one connection that can be used in a later connection (seeSection 2.2 of [TLS]). New versions that also use TLS 1.3SHOULDmandate that their session tickets are tightly scoped to one version of QUIC,i.e., require that clients not use them across multiple version and that serversvalidate this client requirement. This helps mitigate cross-protocol attacks.¶
QUIC version 1 allows sending data from the client to the server during thehandshake by using 0-RTT packets. If a future document wishes to definecompatibility between two versions that support 0-RTT, that documentMUSTaddress the scenario where there are 0-RTT packets in the client's first flight.For example, this could be accomplished by defining which transformations areapplied to 0-RTT packets. That document could specify that compatible versionnegotiation causes 0-RTT data to be rejected by the server.¶
Because QUIC version 1 was the only QUIC version that was published on the IETF Standards Track before this document, it is handled specially as follows: if a client is starting a QUIC version 1 connection in response to a received Version Negotiation packet and the version_information transport parameter is missing from the server's transport parameters, then the clientSHALL proceed as if the server's transport parameters contained a version_information transport parameter with a Chosen Version set to 0x00000001 and an Available Version list containing exactly one version set to 0x00000001. This allows version negotiation to work with servers that only support QUIC version 1. Note that implementations that wish to use version negotiation to negotiate versions other than QUIC version 1MUST implement the version negotiation mechanism defined in this document.¶
The security of this version negotiation mechanism relies on the authenticity ofthe Version Information exchanged during the handshake. In QUIC version 1,transport parameters are authenticated, ensuring the security of this mechanism.Negotiation between compatible versions will have the security of the weakestcommon version.¶
The requirement that versions not be assumed compatible mitigates thepossibility of cross-protocol attacks, but more analysis is still needed here.That analysis is out of scope for this document.¶
IANA has registered the following value in the "QUIC Transport Parameters"registry maintained at<https://www.iana.org/assignments/quic>.¶
IANA has registered the following value in the "QUIC Transport Error Codes" registry maintained at<https://www.iana.org/assignments/quic>.¶
The authors would like to thankNick Banks,Mike Bishop,Martin Duke,Ryan Hamilton,Roberto Peon,Anthony Rossi, andMartin Thomson for their input andcontributions.¶