§2.4
Chapter 02 · QUIC Connection Establishment and Security Handshake

§2.4Connection Migration and the Role of Connection Identifiers

RFC 9000

Learning objective. Explain how Connection IDs let a QUIC connection survive a change of client address, how path validation confirms the new path safely, and what resets when a connection migrates.

A connection is not its address #

TCP binds a connection to the four-tuple of source and destination IP and port; change any element and the connection breaks. QUIC binds a connection to a Connection ID instead (§1.4), so when the client's address changes (a phone leaving Wi-Fi for cellular, a NAT rebinding after an idle period), the packets still carry a Connection ID the server recognizes, and the connection can continue on the new path ([RFC 9000 §9]). Only the client migrates in QUIC v1; the server keeps its address (aside from the optional preferred_address).

Two mechanisms make this work. First, each endpoint issues its peer a pool of Connection IDs over the connection's life, via NEW_CONNECTION_ID frames, each with a sequence number and a stateless-reset token; RETIRE_CONNECTION_ID withdraws old ones. The number a peer will hold is capped by active_connection_id_limit (default 2, minimum 2; constants.md §6). Second, before trusting a new path, the endpoint validates it.

ServerClientconnection established and confirmed onpath Aaddress changes (Wi-Fi → cellular)switch to an unused Destination CIDpacket from a newaddress ⇒ validatethe pathpath B validated · congestion controller& RTT reset for the new pathNEW_CONNECTION_ID (spareCIDs + reset tokens)1-RTT from address B [app data] —non-probingPATH_CHALLENGE (8 randombytes) → address BPATH_RESPONSE (echo the same 8bytes)
Fig. 2.4-1Migration to a new address. A non-probing packet from address B triggers path validation; PATH_CHALLENGE/PATH_RESPONSE confirm reachability before the server commits to the path.RFC 9000 §9, §8.2

Path validation: challenge and response #

When a server receives a non-probing packet (one carrying anything other than PATH_CHALLENGE, PATH_RESPONSE, NEW_CONNECTION_ID, or PADDING) from an address it has not validated, it starts path validation ([RFC 9000 §9.1, §8.2]). It sends a PATH_CHALLENGE frame containing 8 bytes of unpredictable data to the new address; the peer echoes those exact bytes back in a PATH_RESPONSE (both frames are drawn byte-for-byte in §10.1). A matching response proves two things at once: the peer is genuinely reachable at that address (not a spoofed source in an amplification attack), and there is a working return path. Until validation succeeds, the server is held to the 3× anti-amplification limit on the new path: it may send at most three times the bytes it has received from that address (§8.1).

What resets, and why #

A new path is a different network — possibly a different bottleneck, RTT, and loss rate. Carrying the old path's congestion window and RTT estimate onto it would be wrong, so on migrating to a new path an endpoint MUST reset its congestion controller and RTT estimate ([RFC 9000 §9.4]). In practice migration begins conservatively and re-probes the new path's capacity from a small window, which is one reason addresses should change infrequently rather than flapping.

Note

Distinguish deliberate migration from a passive NAT rebinding. In both, packets arrive from a new source address and the server validates the new path identically. The difference is intent: a migrating client proactively switches to a fresh Connection ID for privacy; a NAT rebinding is involuntary and the client may not even notice. The server's response (validate, then continue) is the same. §10.3 treats NAT rebinding in depth.

In practice

editorial For migration to work, a client must switch to a Connection ID the server has not seen tied to the old path — otherwise a passive observer can trivially link the two paths by the constant CID, defeating the privacy benefit. That requires the server to have supplied spare CIDs before the move, so keep active_connection_id_limit at a few (not the minimum 2) on connections expected to roam, and issue NEW_CONNECTION_ID frames early. A server that hands out too few CIDs forces roaming clients to reuse one, quietly eroding privacy. See §10.2.

Takeaways #

Connection IDs turn a connection into something that outlives its address: a migrating or rebinding client keeps talking as long as it uses a known Connection ID, and path validation makes the switch safe by proving reachability before the server commits and by resetting congestion state for the new network. This closes the mechanics of establishing and maintaining a connection; §2.5 turns to what to do when the handshake goes wrong, reading failures out of a trace.