Version-Independent Properties of QUIC
updated by
- rfc-9368 — Compatible Version Negotiation for QUIC
Extracted elements (19)
Only the first QUIC packet in a UDP datagram is covered by the invariant properties. A QUIC version may permit multiple packets per datagram, but invariants apply only to the first, keeping the specification minimal and version-agnostic.
The connection ID echoing requirement in Version Negotiation (swapping DCID and SCID from the triggering packet) gives clients modest assurance that the server actually received the initial packet and that the Version Negotiation was not forged by an on-path attacker unable to observe the original datagram.
The invariants defined in this document exist specifically to ensure that new versions of QUIC can be deployed. By documenting only the properties that cannot change, the document preserves the ability for endpoints to negotiate changes to any other aspect of the protocol. As a consequence, it also defines the minimal information made available to entities other than endpoints.
A protocol that does not conform to the invariant properties defined in this document is not QUIC. Future documents may define additional properties that apply to specific versions or ranges of versions, but the invariants here are the floor for all versions.
Appendix A lists common incorrect assumptions about QUIC derived from knowledge of version 1 that are NOT version-independent invariants, including: use of TLS, long headers only during handshake, client-speaks-first, the 0x40 bit always set, connection IDs changing infrequently, and the version field being the same in both directions.
Only long-header packets trigger version negotiation; packets with a short header do not cause a server to send a Version Negotiation response, regardless of version.
An endpoint MUST authenticate the semantic content of a Version Negotiation packet if it subsequently attempts a different QUIC version as a result of receiving that packet, since Version Negotiation packets have no integrity protection.
An endpoint MUST ignore a Version Negotiation packet that contains no Supported Version fields or contains a truncated (incomplete) Supported Version value.
The 7 Unused bits in the first byte of a Version Negotiation packet MAY be set to any value on sending and MUST be ignored on receipt.
When sending a Version Negotiation packet, an endpoint MUST place the Source Connection ID from the received packet into the Destination Connection ID field, and MUST copy the Destination Connection ID from the received packet (originally randomly chosen by the client) into the Source Connection ID field.
A Connection ID is an opaque field of arbitrary length whose primary function is to ensure that lower-layer addressing changes (UDP, IP) do not cause packets to be delivered to the wrong QUIC endpoint. The connection ID is chosen by each endpoint using version-specific methods, and packets for the same connection may use different connection ID values.
The Header Form bit (most significant bit of the first byte) is the sole invariant distinguishing long headers (bit = 1) from short headers (bit = 0) across all QUIC versions. All other bits in the first byte are version-specific.
The Version field is a 4-byte (32-bit) identifier appearing in long headers that identifies the QUIC version in use. The value 0x00000000 is reserved exclusively for Version Negotiation packets; all other values are potentially valid version identifiers.
Middleboxes may observe traits specific to one QUIC version and incorrectly assume those same semantics apply when other versions exhibit similar traits. QUIC version 1 made efforts to eliminate or obscure some observable traits, but many remain, and different versions may behave differently.
The QUIC version number does not appear in all QUIC packets (short headers omit it), meaning that reliably extracting version-based information from a flow requires middleboxes to maintain state for every connection ID they observe—a significant operational burden that limits practical version-based traffic analysis.
Version Negotiation packets have no integrity or confidentiality protection, providing only modest resistance to insertion by attackers. Specific QUIC versions may add mechanisms to detect modification of the supported versions list, but no such mechanism is defined here.
A Version Negotiation packet uses the long-header form with the Version field set to 0x00000000, followed by Destination and Source Connection ID fields, then a list of 32-bit Supported Version fields. The 7 bits after the Header Form bit are labeled Unused and carry no defined semantics.
The QUIC long header begins with a Header Form bit set to 1, followed by 7 version-specific bits, a 32-bit Version field, an 8-bit Destination Connection ID Length, Destination Connection ID (0–255 bytes), an 8-bit Source Connection ID Length, Source Connection ID (0–255 bytes), and version-specific data of arbitrary length.
The QUIC short header begins with a Header Form bit set to 0, followed by 7 version-specific bits, a Destination Connection ID of length not encoded in the packet (version-specific), and version-specific data. The short header carries no Source Connection ID, no DCID Length field, and no Version field.