QUIC’s TLS 1.3 handshake happens before any application data is sent, and it’s surprisingly efficient because it piggybacks on UDP.
Let’s watch a QUIC connection establish, specifically the TLS 1.3 handshake, using tshark to capture the packets and then analyzing them. Imagine we’re connecting to a server at 192.168.1.100 on port 443.
# On the client side, capturing traffic to the server
sudo tshark -i <your_interface> -f "udp port 443 and host 192.168.1.100" -w quic_handshake.pcap
# On the server side, also capturing
sudo tshark -i <your_interface> -f "udp port 443 and host <your_client_ip>" -w quic_handshake.pcap
Now, let’s look at the quic_handshake.pcap file in Wireshark, filtering for quic and tls.
Here’s what you’ll observe in the packet flow, assuming a successful handshake:
- Client Hello (QUIC Initial Packet): The client sends its first packet, which encapsulates a TLS
ClientHellomessage. This packet contains the QUIC version, a connection ID, and theClientHelloitself. TheClientHelloincludes supported TLS versions (aiming for 1.3), cipher suites, and a random number. Crucially, it also includes initial crypto data. This is the very first packet. - Server Hello, Certificate, Encrypted Extensions, Certificate Verify, Finished (QUIC Initial/Handshake Packets): The server responds with its own initial packet(s). These packets contain the server’s TLS
ServerHello(choosing the TLS version and cipher suite), its digitalCertificate,Encrypted Extensions(server preferences encrypted with the soon-to-be-established keys),CertificateVerify(proof of certificate ownership), and theFinishedmessage (verifying the handshake integrity). All of this is sent within QUIC packets. If the handshake needs multiple round trips (e.g., for certificate chains or OCSP stapling), you’ll see more QUIC packets carrying TLS handshake messages. - Finished (Client Side, QUIC Handshake Packet): The client receives the server’s handshake messages, verifies the certificate, decrypts the extensions, and sends its own
Finishedmessage, also encapsulated in a QUIC packet. This confirms the handshake is complete from the client’s perspective. - 0-RTT Data (Optional, QUIC Handshake Packet): If the client has previously completed a handshake with this server and the server supports 0-RTT, the client might send application data in its very first packet (the one containing the
ClientHello). This data is encrypted using keys derived from a previous session. This is a major win for latency.
The problem QUIC’s TLS 1.3 handshake solves is the inherent latency of TCP’s three-way handshake followed by TLS’s two-way handshake. By merging these into a single round trip (or even zero round trips for 0-RTT), QUIC drastically reduces connection setup time, especially over high-latency networks. It achieves this by sending the TLS ClientHello within the first QUIC packet, which is sent over UDP. UDP doesn’t have a handshake, so the initial packet can go out immediately. The server then responds with its TLS handshake messages, also within QUIC packets.
The internal mechanism is that QUIC defines specific packet types for its crypto framework. The Initial packet type is used for the first flight of data, carrying the ClientHello. Subsequent handshake messages are carried in Handshake packet types. This allows the handshake to proceed independently of the main QUIC packet numbering, which starts after the handshake is complete. The cryptographic negotiation is standard TLS 1.3, but its transport is embedded within QUIC’s packet structure.
The levers you control are primarily on the server side: enabling TLS 1.3, configuring supported cipher suites, and managing certificate validation (like OCSP stapling) to encourage 0-RTT. On the client, it’s about supporting these features and potentially caching session tickets for 0-RTT.
A surprising aspect of QUIC’s handshake is how it handles packet loss during the handshake. If a UDP packet carrying TLS handshake data is lost, QUIC’s stream multiplexing and loss recovery mechanisms kick in. The TLS handshake is designed to be resilient to this, often by retransmitting the lost TLS message within a new QUIC packet. The crucial part is that the TLS Finished messages act as cryptographic anchors; if they are successfully exchanged, the handshake is considered complete, even if some intermediate packets were lost and retransmitted.
The next step after a successful handshake is dealing with QUIC’s stream management and flow control.