QUIC’s ability to switch networks without dropping a connection isn’t magic; it’s a carefully engineered dance built on statelessness and a unique identifier.

Imagine you’re on a video call, and your phone switches from Wi-Fi to cellular data. Most protocols would stutter, freeze, or outright disconnect. QUIC, however, keeps the stream flowing. This is because QUIC connections are identified not by the IP address and port of the endpoints (like TCP), but by a 64-bit Connection ID.

Here’s a simplified view of a QUIC connection being migrated:

Initial Connection (Wi-Fi)

  • Client (192.168.1.10:50000) establishes a QUIC connection with Server (203.0.113.5:443).
  • A Connection ID (e.g., 0x123456789abcdef0) is generated and exchanged.
  • All subsequent packets for this connection carry this Connection ID.

Network Switch (Client moves to Cellular)

  • Client’s IP address changes to (198.51.100.20:50000).
  • The client doesn’t tear down the existing connection. Instead, it starts sending new packets from the new IP address, still containing the original Connection ID (0x123456789abcdef0).

Server Receives Migrated Connection

  • The server receives packets from the new IP address but recognizes the Connection ID.
  • The server updates its internal mapping to associate the Connection ID with the new client IP address.
  • The connection remains alive, and data continues to flow.

This might seem straightforward, but the devil is in the details, especially concerning how the server handles these incoming packets and how it ensures the client is legitimate.

The core mechanism relies on the Connection ID being independent of the IP address and port. When a QUIC connection is established, the client and server negotiate a set of Connection IDs. The client is free to use any of these IDs to send packets. The server, upon receiving a packet with a specific Connection ID, looks up its internal state for that ID. If it finds a match, it processes the packet.

When the client’s IP address changes, it simply starts sending packets from the new IP address, using one of its previously agreed-upon Connection IDs. The server will receive these packets, look up the Connection ID, and realize it’s coming from a new IP. To prevent spoofing, the server doesn’t immediately trust the new IP. Instead, it expects the client to re-authenticate itself at the new IP address. This is typically done through a process called "Source Address Token" validation.

When the server first establishes the connection, it sends a "Source Address Token" to the client. This token is essentially a cryptographic proof that the client’s original IP address was indeed the one that initiated the connection. If the client’s IP address changes, it must send this token back to the server along with its first packet from the new IP address. The server can then validate this token to confirm that the client is legitimate and has a right to migrate.

Consider a client that just established a connection and then immediately changes networks. The server might send a NEW_CONNECTION_ID frame to the client, indicating a new Connection ID the client can use. The client then sends a packet with this new ID, and critically, includes the original Source Address Token. The server validates the token, associates the new Connection ID with the new IP, and the migration is complete.

This process is robust because it leverages the stateless nature of UDP and the cryptographic integrity of TLS 1.3 (which QUIC uses). Each packet carries enough information (Connection ID, sequence numbers, cryptographic tags) for the receiver to verify its authenticity and relevance.

The most surprising thing about connection migration is how it leverages existing transport mechanisms (UDP) and security protocols (TLS 1.3) to achieve something that feels like a higher-level application feature. It’s not a new protocol layered on top of TCP; it’s a fundamental re-imagining of connection state management.

Let’s look at a simplified packet exchange. Assume client IP 192.168.1.10 migrates to 198.51.100.20.

  1. Client (old IP: 192.168.1.10) sends data:

    UDP Packet:
      - Source IP: 192.168.1.10
      - Source Port: 50000
      - Destination IP: 203.0.113.5
      - Destination Port: 443
      - QUIC Header:
        - Destination Connection ID: 0x123456789abcdef0
        - Packet Number: 10
      - QUIC Payload: Encrypted application data, crypto handshake messages, etc.
    

    Server receives this, associates 0x123456789abcdef0 with 192.168.1.10:50000.

  2. Client (new IP: 198.51.100.20) sends data after migration:

    UDP Packet:
      - Source IP: 198.51.100.20
      - Source Port: 50000
      - Destination IP: 203.0.113.5
      - Destination Port: 443
      - QUIC Header:
        - Destination Connection ID: 0x123456789abcdef0
        - Packet Number: 11
      - QUIC Payload: Encrypted application data, possibly with a Source Address Token (if it's the first packet after migration)
    

    The server receives this. It sees 0x123456789abcdef0. It checks its state. It knows this Connection ID was previously associated with 192.168.1.10:50000. Now it’s coming from 198.51.100.20:50000. If the Source Address Token is present and valid, the server updates its internal mapping: 0x123456789abcdef0 is now associated with 198.51.100.20:50000. The connection state (encryption keys, stream IDs, etc.) is preserved.

A crucial detail is that the client doesn’t have to use the same Source Port. The connection migration is primarily about the client’s IP address changing. The Source Port is part of the UDP socket binding, and while often it stays the same, it’s the IP that’s the critical part for network layer reachability.

The server can also initiate a change in the Connection ID using a NEW_CONNECTION_ID frame. This is important for the server to manage its own resources and potentially rotate cryptographic parameters. The client will then start using the new Connection ID provided by the server, and when it migrates, it will use the new Connection ID from its new IP address.

The most sophisticated aspect is how the server handles multiple simultaneous Source IP addresses for a single Connection ID during a transition period. It might temporarily accept packets from both the old and new IP addresses for a short window, allowing the client to fully re-establish itself on the new network before de-prioritizing the old IP. This smooths out any packet loss or reordering that might occur during the IP address switch.

The next hurdle is understanding how QUIC handles flow control and congestion control across these potentially unstable network paths.

Want structured learning?

Take the full Quic course →