I received an email asking about implementing DNS over HTTPS (DoH) in Privacy Browser. As this is a fairly complex topic, and as there are likely to be other people with the same question, I thought it best to answer with this blog post.
First, a little background about the problem. When DNS (the Domain Name System) was originally designed, people hadn’t really thought through the security and privacy concerns that exist with the internet as we have it today. As such, the original protocol was designed to use UDP (on port 53). This has implications for DDoS amplification attacks, but more importantly for our purposes, it means that DNS traffic is not encrypted. Every time you make a request to view a website in a web browser, your device uses DNS to lookup the IP address of the server. Anyone who is able to listen to the packets leaving your system, like your ISP or the government of the country where you live, can read those DNS requests and, because they are not encrypted, can tell which websites you are visiting.
DoH is designed to address this problem by encrypting DNS traffic and sending it over the HTTPS protocol (which uses TCP instead of UDP and is encrypted). There has been a fair amount of discussion recently about DoH because both Firefox and Chrome have added experimental options to enable it in the browser. This sparked a bit of privacy theater in Europe, and has generally raised the consciousness of users about this topic. The purpose of this post is to explain what DoH is, why it isn’t the best solution to the problem, and why I don’t believe that DNS requests should be handled at the browser level.
- I am a big fan of encrypting everything that moves across the internet. I think running DNS over UDP is a poor idea. Most DNS servers now have the option of running a separate TCP interface, but it still often isn’t the default for either servers or clients. Moving to TCP, even unencrypted TCP (still on port 53), removes the problem of the DDoS amplification attacks, although at the cost of making DNS requests take a little more bandwidth and a little more time.
- But once you switch everything to use TCP for DNS, it is easy to encrypt that DNS traffic. This is known as DNS over TCP (DoT, which runs on port 853). This is the solution that everyone should be aiming for instead of DoH. While DoT is a little more bandwidth hungry than DNS over UDP, DoH is hugely more bandwidth hungry and much slower. This is because DoH must first setup a TCP connection, then it must setup a encrypted TCP session, then it must setup an entire HTTPS session (huge and bulky and overly complex) just to make a DNS request. So, the first part of the answer is that the solution we should be going for is DoT instead of DoH. Beginning with Android 9 Pie, the OS uses DoT by default as long as it is supported by the DNS server.
- Proponents of DoH point to scenarios where some type of ISP or government firewall blocks DoT traffic as a reason to use DoH (which runs on port 443 like normal HTTPS traffic). This is because DoH traffic looks a lot more like normal HTTPS traffic than DoT, so the argument is that it would be harder to block. While it is true that it would be marginally harder to block, it wouldn’t be that difficult to fingerprint it, because it doesn’t actually look that much like normal web browsing traffic. And the IP addresses DoH traffic is heading to are known DNS servers, so it would be fairly east to blacklist those IP addresses if one wanted to. However, the easiest solution to this problem is for all DoT servers to also run a DoH instance, and clients can downgrade from DoT to DoH instead of DNS over UDP if they cannot make a DoT connection.
- But this leads us to the next point, which is that even if all DNS traffic were encrypted with DoT or DoH, it would still be laughably easy for ISPs or governments to know exactly what websites you are visiting, so nothing has been gained from a privacy standpoint. This is why I call it privacy theater. Let me enumerate how they can do this in points 5-7 below.
- When your device makes an HTTPS request to a server for a website, it includes the server name in plaintext at the beginning of the encrypted packet. Let me slow down and say that again: every packet you send to a HTTPS server includes the unencrypted domain name of the server you want to speak with. This is called Server Name Indication (SNI). SNI exists to solve a very real problem: most servers host multiple domains on the same IP address. The server needs to know which certificate to use when it receives the first packet from your device. If it picks the wrong certificate, your device will show an SSL certificate error. So the packet contains the domain in plaintext to facilitate this. Anyone who could read your unencrypted DNS traffic can also read the SNI on your encrypted HTTPS traffic. So, until the SNI problem is fixed, encrypting DNS is meaningless from a privacy standpoint.
- There is some effort being made to encrypt SNI, which is included as an optional component of TLS 1.3. But implementing it is complicated and breaks things. I don’t see anything like this going mainstream until it is implemented as a core part of the TLS protocol and not as an optional component. Which means that we won’t see this until TLS 1.4 at the earliest. And it also means that it won’t work in the real world until the lowest protocol supported by either the server or the client is TLS 1.4, because otherwise the person who it attempting to sniff the domain name could just force a TLS downgrade to 1.3 to get the information. So, at a minimum I put that at 10 years.
- At face value the argument would then be that we should just get rid of SNI and have a 1:1 correlation between domain names and IP addresses. But this would make it even easier for ISPs and governments to track your web traffic, because there are companies who maintain lists of all the domain names on the internet and the IP addresses they are linked with. 95% of the websites you visit can be identified just by the list of IP addresses they use. Without SNI, that would be 100%. And the IP address, like the destination address on a letter, is one part of a packet that can’t be encrypted because otherwise the routers on the internet wouldn’t know where to send it.
- By now it should be apparent that DoT is the solution we are looking for to encrypt DNS, and that from a privacy standpoint it won’t mean anything until we also get encrypted SNI (and that even after both are encrypted it won’t mean very much). Which leads us to the question: what is Privacy Browser going to do about it. The answer is that Privacy Browser is going to do nothing. The reason I say that is not to be flippant, but because DNS is something I feel very strongly should not be dealt with at the browser level. It should be handled entirely by the OS. I have written a bit about this topic in relation to minimizing Privacy Browser’s attack surface. The idea is that, from a security perspective, the browser shouldn’t try to recreate core OS functions, like encryption or DNS. Not only does this introduce another attack surface that is unlikely to be as well audited as the functionality in the core OS, but it also overrides core OS networking settings at an app level, which leads to unexpected behavior, like not updating DNS servers to match the current network or VPN settings.
- This is the part of the conversation where we explain how DoH can actually decrease your privacy instead of merely doing nothing to increase it. During the normal course of the day, you probably connect to multiple DNS servers. When you wake up you probably use the DNS server provided by your home ISP (available over your home Wi-Fi). When you are commuting to work or school, you use your cell phone company’s DNS server. When you arrive at work or school, you connect to the DNS server provided through their Wi-Fi. Each of these DNS servers has a partial list of the the websites you visit throughout the day, but it would be hard to stitch them into a cohesive whole. However, if you use DoH as it is currently implemented in Chrome and Firefox, you would use one DNS server all the time. The two biggest servers that support DoH are run by Google and Cloudflare. Cloudflare promises they won’t do anything bad with that information. But you have no way of verifying that such is the case. And Google, they don’t even make any promises. There is a lot of additional information about this topic on a blog entitled Centralized DoH is bad for privacy, in 2019 and beyond.
- To round out this conversation, we should talk a little bit about DNSSEC (Domain Name System Security Extensions). The whole purpose of DoH is to encrypt traffic in transit while it is going between a DNS server and your device. The actual DNS data on the server is unencrypted, and, as a huge security problem, can be modified by that server before it is sent to you. DNSSEC digitally signs DNS information, so that only the owner of a DNS record can make changes. This verifies that the information DNS servers give you is what it is supposed to be. Because it is quite complex to implement, and because it dramatically increases the size of DNS responses, DNSSEC still hasn’t caught on as the default configuration in most cases. But we hopefully are a little closer than encrypted SNI.
Each of the points above represents almost a gross oversimplification of the complexities of these issues. And, because I am constantly learning more about these issues, the implication is that I do not yet know everything about them. As such, I am perfectly willing to change my mind about any of the above topics if I am presented with a persuasive argument to the contrary. I labeled each section above so that is it easy to reference them by number in the comments if you feel that there is anything I have missed.