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 to false if needed, though SSLKEYLOGFILE is preferred) and security.ssl.enable_sni (set to true). The SSLKEYLOGFILE environment variable is the most reliable.
  • Chrome/Chromium: Set the SSLKEYLOGFILE environment 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:

  1. Open Wireshark.
  2. Go to Edit -> Preferences.
  3. Navigate to Protocols -> TLS.
  4. In the (Pre)-Master-Secret log filename field, browse to and select your sslkeys.log file.
  5. 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.2 or TLSv1.3 records.
  • 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, and RST_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 ID associated 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 for DATA frames.
  • http2.type == 1: Filters for HEADERS frames.
  • http2.type == 6: Filters for RST_STREAM frames (indicating an error or cancellation).
  • http2.type == 7: Filters for GOAWAY frames (indicating the connection is closing).

Troubleshooting Common Issues:

  • No HTTP/2 Dissection:
    • Cause: TLS not decrypted.
    • Fix: Ensure SSLKEYLOGFILE is 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 -v or check server logs/configuration. In Wireshark, look for h2 in the ALPN (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.log file 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 ALPN extension in the TLS handshake explicitly lists h2.

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.

Want structured learning?

Take the full Http2 course →