Wireshark: Tracing Encrypted HTTP/2 Traffic

After optimizing Firefox HTTP/1.1 settings for slow wireless connections 17 years ago (!) , I pretty much forgot all about it again, because networks became faster and default browser settings and features were adapted for the cellular world. Only recently did I have another look at HTTP, when I noticed that HTTP/2 is now widely used in practice, and also plays a big role in the 5G core networks. From a security point of view, the great thing about HTTP/2 is that browsers only support TLS encrypted HTTPS connections. This has the downside, of course, that tracing and analyzing HTTP/2 connections with Wireshark is not possible out of the box any more. But there’s a fix for this!

This post made me aware that Firefox and Chrome can be made to write the encryption keys for TLS connections to a file. All that is required is a Linux environment variable that specifies the path to the log file:

export SSLKEYLOGFILE=/home/martin/tlskeylog.log

After starting Firefox from the shell session in which the environment variable is set, the log file quickly fills with TLS session keys. Wireshark can then go ahead and decode TLS and, as a consequence HTTP/2 connections, in real time, by specifying the path + filename of the log file in ‘Edit -> Preferences -> Protocols -> TLS‘. The article above also recommends to enable ‘Reassemble out-of-order segments‘ in the TCP decoding preferences.

The screenshot above shows a decode of an HTTP/2 connection to this blog from my web browser. Even though my site is lean, one can nicely see many of HTTP/2’s features:

  • How a TCP connection is established
  • How subsequently, TLS authentication and encryption is done (and the ALPN parameter is included, so the client knows that HTTP/2 instead of HTTP/1.1 can be used)
  • How subsequently many HTTP/2 requests are made over the single TCP connection
  • While HTTP/1.1 has already introduced the possibility to request many files in a single TCP connection, delivery had to be in the same sequence as the request. In HTTP/2, they can now be sent in a different order, and parts of individual (file) streams can even be mixed on the wire.
  • For this mix and match process, HTTP/2 introduces ‘streams’ and stream header information that clearly identifies the length of the content that follows in this particular stream and the type of the information that follows. Different types of information that can be transmitted in a stream are for example DATA (i.e. the actual content of a file), HEADER information (such as a HTTP GET request), SETTINGS, WINDOW_UPDATEs and a couple of other things.

One thing that had me puzzled for a bit is that HTTP/2 includes transmission window control. Why is this necessary, transmission window handling is already part of the the TCP layer!? The answer: The window handling on the HTTP/2 layer is per stream, so different transmission window sizes can be negotiated for each individual stream. So what would that be useful for? For my blog, it’s probably not useful at all, as all data should be sent to the browser as quickly as possible. But for other content such as videos, an individual transmission window for the video stream could be used to throttle the stream to just the right speed for viewing from the application layer. I’m not sure if this is used in practice, but Google mentions this as an example here.