QUIC’s encryption is designed to be so robust that even the server initiating the connection can’t fully decrypt all traffic without the client’s cooperation.
Let’s see QUIC in action. Imagine a user browsing a website that uses QUIC. The browser, acting as a QUIC client, initiates a connection to the web server. Instead of a TCP handshake followed by a TLS handshake, QUIC does it all in one go. The client sends an initial packet with cryptographic information. The server responds with its own cryptographic information and, crucially, a "0-RTT" or "1-RTT" key. This key allows the client to encrypt subsequent application data. Wireshark, running on a network tap or even the client/server itself, captures these UDP packets.
Here’s a simplified view of the packet flow:
Client -> Server:
Initial (ClientHello, public data)
(Server processes, generates handshake secrets)
Server -> Client:
Initial (ServerHello, public data, Handshake, EncryptedExtensions, Certificate, CertificateVerify, Finished, potentially early data)
(Client verifies, derives session keys)
Client -> Server:
Handshake (Finished, potentially early data)
(Both sides now have session keys)
Client -> Server:
1-RTT (Application Data, encrypted)
Server -> Client:
1-RTT (Application Data, encrypted)
The problem for Wireshark users is that the application data, everything after the initial handshake, is encrypted by default using TLS 1.3. Without the session keys, Wireshark sees only indecipherable UDP payloads.
To analyze QUIC traffic, you need to extract these TLS 1.3 session keys and provide them to Wireshark. The standard way to do this is by using the SSLKEYLOGFILE environment variable. Most modern browsers and applications that support QUIC also support writing these keys to a log file when this variable is set.
Here’s how you’d set it up:
1. Set the SSLKEYLOGFILE environment variable:
On Linux/macOS:
export SSLKEYLOGFILE=~/sslkeys.log
On Windows (Command Prompt):
set SSLKEYLOGFILE=C:\Users\YourUser\sslkeys.log
On Windows (PowerShell):
$env:SSLKEYLOGFILE = "C:\Users\YourUser\sslkeys.log"
Replace ~/sslkeys.log or C:\Users\YourUser\sslkeys.log with your desired log file path.
2. Launch your application (e.g., Chrome, Firefox) after setting the variable.
Make sure you start your browser or application from the same terminal where you exported the SSLKEYLOGFILE variable. This ensures the application inherits the environment variable.
3. Generate QUIC traffic.
Browse to a website known to use QUIC (e.g., google.com, facebook.com). Perform actions that generate traffic.
4. Capture traffic with Wireshark.
Start Wireshark before or during step 3. Select your network interface and start capturing. Filter for UDP traffic on port 443 (the default QUIC port).
5. Configure Wireshark to use the key log file.
- Go to
Edit->Preferences. - Navigate to
Protocols->TLS. - Under
(Pre)-Master-Secret log filename, clickBrowseand select thesslkeys.logfile you specified in step 1. - Click
OK.
6. Replay or re-examine captured traffic.
If you were already capturing, Wireshark might need a moment to re-dissect the packets. If you captured after the fact, restart Wireshark or tell it to re-read the capture file. You should now see the QUIC application data decrypted. Look for UDP packets with QUIC headers. You can filter for quic in Wireshark.
The key information Wireshark uses from the sslkeys.log file is the TLS session resumption secrets or the initial master secret, which are used to derive the actual encryption and decryption keys for the QUIC connection. These secrets are typically logged in a specific format: CLIENT_RANDOM <session_id> <master_secret>. Wireshark parses this to reconstruct the session keys.
The magic is that the TLS 1.3 handshake, which happens within the QUIC connection establishment, generates secrets that are then used to encrypt the QUIC packets. By providing these TLS secrets to Wireshark, you’re essentially giving it the decryption key for the QUIC traffic.
You’ll notice that even with the keys, not everything is visible. The initial QUIC handshake packets themselves, and any metadata that is explicitly designed to be public or is encrypted with a different key (like initial connection establishment tokens), might still appear unencrypted or differently dissected. The sslkeys.log file primarily helps decrypt the application data that flows after the handshake is complete.
The next thing you’ll likely encounter is understanding the nuances of QUIC’s stream multiplexing and how to trace specific application-level flows within the decrypted UDP payloads.