HTTP/2, despite its speed and efficiency gains, makes capturing and analyzing its traffic with Wireshark significantly more complex than its predecessor, HTTP/1.1.
Let’s dive into how to actually see this traffic and what makes it tricky.
Capturing HTTP/2 Traffic
The primary challenge with HTTP/2 is that it often runs over TLS (HTTPS) by default. Wireshark, by default, can’t decrypt TLS traffic. So, the first hurdle is getting plain HTTP/2 to analyze.
Method 1: Capture on the Client (if you control it)
If you’re debugging a client application, you can often configure it to use HTTP/2 without TLS for testing purposes. This is the easiest way.
For example, with curl, you can force HTTP/2 with the --http2 flag:
curl --http2 -v https://example.com/
This will attempt to establish an HTTP/2 connection. If the server supports it and your curl is compiled with HTTP/2 support, you’ll see output indicating the connection.
Method 2: Capture on the Server (if you control it)
On the server side, you might be able to configure your web server (like Nginx or Apache) to accept plain HTTP/2 traffic on a non-TLS port for debugging. This is less common and often a security risk in production.
For Nginx, you might add a listen directive like this in your nginx.conf:
server {
listen 8080 http2; # Listen on port 8080 with HTTP/2 enabled
server_name example.com;
# ... other configurations
}
Then, you’d point your client to http://example.com:8080.
Method 3: Decrypting TLS Traffic (The Most Common Scenario)
This is where most of the magic happens for real-world analysis. If your HTTP/2 traffic is over HTTPS (which it almost always is), you need to provide Wireshark with the decryption keys.
This typically involves capturing the TLS handshake and then using the session keys to decrypt subsequent traffic.
Step 1: Enable TLS Logging on the Client
Many applications and libraries allow you to log the TLS session keys.
For curl, you can use the SSLKEYLOGFILE environment variable:
export SSLKEYLOGFILE=~/sslkeys.log
curl -v https://example.com/
This will create a sslkeys.log file containing the pre-master secret for the TLS session.
For browsers, you often need to set an environment variable or a specific preference:
- Firefox:
about:config->security.ssl.enable_ocsp_stapling(set tofalseif needed, thoughSSLKEYLOGFILEis preferred) andsecurity.ssl.enable_sni(set totrue). TheSSLKEYLOGFILEenvironment variable is the most reliable. - Chrome/Chromium: Set the
SSLKEYLOGFILEenvironment variable before launching the browser.
Step 2: Capture Traffic with Wireshark
Start Wireshark and capture traffic on the network interface your client is using. Filter for your target IP address or port.
Step 3: Tell Wireshark How to Decrypt
Once you have both the capture file (.pcapng) and the sslkeys.log file:
- Open Wireshark.
- Go to
Edit->Preferences. - Navigate to
Protocols->TLS. - In the
(Pre)-Master-Secret log filenamefield, browse to and select yoursslkeys.logfile. - Click
OK.
Wireshark will re-read the capture file and attempt to decrypt any TLS traffic for which it has the keys.
Analyzing HTTP/2 in Wireshark
Once you have decrypted traffic, you’ll notice HTTP/2 looks different. It’s a binary protocol, not plain text like HTTP/1.1.
What You’ll See:
- TCP Segments: You’ll still see the underlying TCP packets.
- TLS Records: If you decrypted correctly, these will show up as
TLSv1.2orTLSv1.3records. - HTTP/2 Frames: Inside the decrypted TLS records, you’ll see the actual HTTP/2 frames. Wireshark will dissect these as
HTTP/2.
Key HTTP/2 Concepts to Look For:
- Frames: HTTP/2 is built on frames. Common frame types include
HEADERS,DATA,SETTINGS,GOAWAY,PING, andRST_STREAM. - Streams: A stream is an independent, bidirectional sequence of frames. Multiple streams can be multiplexed over a single TCP connection. You’ll see a
Stream IDassociated with many frames. - Connection: A single TCP connection can carry many streams.
- Headers (HPACK): HTTP/2 uses HPACK compression for headers, making them much smaller. Wireshark can decompress these if it correctly dissects the HPACK frames.
Useful Wireshark Filters for HTTP/2:
http2: Shows all dissected HTTP/2 traffic.http2.streamid == <id>: Filters for frames belonging to a specific stream.http2.flags.end_stream == 1: Shows frames that mark the end of a stream.http2.type == 0: Filters forDATAframes.http2.type == 1: Filters forHEADERSframes.http2.type == 6: Filters forRST_STREAMframes (indicating an error or cancellation).http2.type == 7: Filters forGOAWAYframes (indicating the connection is closing).
Troubleshooting Common Issues:
- No HTTP/2 Dissection:
- Cause: TLS not decrypted.
- Fix: Ensure
SSLKEYLOGFILEis set correctly and Wireshark is configured to use it. Verify the capture actually contains the TLS handshake for the session. - Cause: Client or server not actually using HTTP/2.
- Fix: Use
curl --http2 -vor check server logs/configuration. In Wireshark, look forh2in theALPN(Application-Layer Protocol Negotiation) extension within the TLS handshake.
- "Bad HTTP/2 frame" errors:
- Cause: Corrupted packets or incorrect TLS decryption.
- Fix: Re-capture traffic. If decryption is the issue, double-check the
sslkeys.logfile and Wireshark’s configuration. - Cause: An intermediary (like a proxy or firewall) is mangling the HTTP/2 frames.
- Fix: Capture traffic as close to the client and server as possible to rule out intermediaries.
- Seeing only TCP/TLS, no HTTP/2:
- Cause: Wireshark’s dissector isn’t recognizing the traffic as HTTP/2.
- Fix: Ensure you have the latest version of Wireshark, as dissectors are frequently updated. Verify that the
ALPNextension in the TLS handshake explicitly listsh2.
The most subtle aspect of HTTP/2 analysis is understanding how multiple streams are multiplexed. You might see HEADERS for stream 5, then DATA for stream 7, then more HEADERS for stream 5 again, all interleaved within the same TCP connection. This is the core of HTTP/2’s performance advantage, allowing requests and responses to be sent concurrently without head-of-line blocking at the HTTP layer.
Once you’ve mastered capturing and decrypting, the next step is often understanding how HPACK compression impacts header sizes and debugging performance issues related to stream prioritization.