Last Updated: 2019-12-17 03:47:52 UTC
by Johannes Ullrich (Version: 1)
Whenever I talk about DNS over HTTPS (DoH), the question comes up if it is possible to fingerprint DoH traffic without decrypting it. The idea is that something about DoH packets is different enough to identify them.
This evening after recording my podcast, I experimented a bit with this idea to see what could be used to identify DNS over HTTPS traffic. To run this experiment, I used Firefox. I used Firefox for a couple of different reasons:
- I consider the Mozilla DoH implementation mature. Mozilla was one of the trailblazers for DoH and has made it very easy to enable DoH. I find Chrome to be a bit more "tricky" in that it is more careful in its use of DoH.
- Firefox, just like Chrome, allows me to collect TLS master keys via the SSLKEYLOGFILE environment variable. This allowed me to decrypt and separate the DoH from other HTTPS traffic
At this point, I would call the experiment a "proof of concept." It is not a conclusive experiment. I only collected a few minutes of traffic and went maybe to a dozen different sites. All tests were performed on a Mac using Firefox 71 and Cloudflare as a resolver. I may get around to do more testing during the day and will update this post accordingly.
I started by running tcpdump (otherwise I forget it and realize that I need to start it after I started Firefox)
% tcpdump -i en8 -w /tmp/ssl.pcap
Next, in a different terminal, I set the SSLKEYLOGFILE environment variable
% export SSLKEYLOGFILE=/tmp/sslkeylogfile
Finally, I started Firefox from the console in the same terminal, where I set the environment variable (so it sees the environment variable). Make sure Firefox isn't already running.
% open /Application/Firefox.app
Next, I went to a few random websites (Google, CNN, isc.sans.edu, sans.edu... ). After I ran out of sites to visit, I closed Firefox and exited tcpdump.
I loaded the packet capture file and the SSL Key Logfile in Wireshark. I used version 3.1.0, which fully supports DoH and HTTP2 (Firefox uses HTTP2 for DoH). I identified the DoH traffic using the simple display filter "dns and tls." The entire DoH traffic was confined to a single connection between my host and mozilla.cloudflare-dns.com (2606:4700::6810:f8f9). Could I have just identified the traffic using this hostname? Sure. In this specific case. But you can run your own DoH server and evade simple blocklists like this.
I filtered all traffic to and from that Cloudflare host. Next, I filtered all port 443 traffic that did not involve this IP to a second file and did some simple statistics. Aside from the session length, I found that the payload length for DoH is somewhat telling. DNS queries and responses are usually a couple of hundred bytes long. HTTPS connections, on the other hand, tend to "fill" the MTU. So there is a graph of the payload size-frequency for DoH and HTTPS:
|TLS Without DoH||DoH Only|
The 3 (4?) spikes in the DoH traffic could be due to the limited sample. But these are typical sizes for DNS payloads. Note how the DoH payload size "clusters" below 5-600 bytes, the legacy DNS reply limit. For the non-DOH traffic, the payload sizes peak close to the MTU (the MTU was 1500 Bytes here).
In short: if you see long-lasting TLS connections, with payloads that rarely exceed a kByte, you probably got a DoH connection. But I need to run more tests to verify that. Feel free to do your own experiments and see what you find. Of course, some of these artifacts may be implementation-specific. The RFC somewhat suggests the extended session length. But in other implementations (earlier Firefox versions?), I seem to remember shorter TLS sessions for DoH.
So please let me know what you find, and I will likely update this some time tomorrow if I find time to look at more traffic.