For the time being, until companies design products and services with them in mind, the work of protecting our privacy and security falls on consumers like you and I. This article is about how to use tools that are widely available and well-supported to improve the privacy of our devices behind-the-scenes as part of the hidden machinery of the Internet.
Full transparency: the battles of taste won’t ever be won. When Mozilla’s Firefox announced it would be rolling out DNS-over-HTTPS by default in September, there were many valid and important discussions about why this isn’t all awesome, like this: https://ungleich.ch/en-us/cms/blog/2019/09/11/turn-off-doh-firefox/
Personally, I agree with most everything these debates put forward. Applications should not control things like DNS. However, most of the everyday people using the Internet are already giving most or all of their data, including their DNS requests, to a big entity like Google and/or the primary ISPs, so until there are more alternatives, it’s a lesser-of-evils-sort-of-model, especially until there are better consumer data protection laws in the U.S.
Here’s what this article isn’t: it isn’t an opinion piece about the good and bad of all that to convince anyone of anything. You are free to make up your own mind about who you are going to trust.
Here’s what this article is: a guide to using Cloudflare as a DoH resolver to send encrypted DNS requests from your own network architecture, working around Firefox’s forced roll-out of the technology in their browser as of September of this year, adding arguably better privacy and, in combination with Pi-Hole, to block ads and malicious sites, while reclaiming bandwidth used up by those targeted ads, greatly improving overall network performance and resilience.
In a world of many tough decisions and unknown outcomes, this article is making a choice to work with some tools to get some practical value from them on terms I am comfortable with. You may disagree and that’s okay. This article isn’t for you.
Domain Naming System (DNS)
If our computers and mobile devices are cars that drive on the Internet, then the maps they use to get from place-to-place are powered by the Domain Naming System or DNS for short. DNS is what translates the unique, long, complicated-string-of-numbers called IP addresses websites have, like 184.108.40.206, into domain names, like duckduckgo.com, which are far more memorable and elegant.
Here's the thing, fundamentally, DNS requests to translate these IP addresses into domains are sent from our devices in the clear, as if written on a postcard that others can read and mess with. This makes DNS requests vulnerable to a broad spectrum of nefarious tomfoolery. For example, a criminal could potentially redirect our browser to a site that might LOOK like the one we want to get us to give away our username and/or password. This is called DNS poisoning and it's more common than most of us realize.
Also, this flaw allows whoever our Internet provider is to track, monitor, and even censor our activity while building a profile that includes a record of every single site we've ever visited that they can sell to the highest bidder(s) without our consent. There are many reasons why we should care about this and none of them are what you might think.
If you're thinking, "I don't really care," then you might consider that privacy is an endangered species for precisely that attitude, for allowing advertisers and the companies they represent to continue doing whatever they want, doing that which most of us aren't aware of and that NONE of us have even had a chance to consent to or not.
<rant>Privacy matters for reasons you haven't even thought of yet. It's not too late to ditch your cynicism and start caring before it's too late. </rant>
In a nutshell, DNS is not secure-by-design or built with privacy in mind. Wouldn't it be better to send these requests in a private envelope like a personal letter rather than a postcard that anyone can collect and read?
A pretty good analogy for encryption is a personal letter or a bill we need to pay that we send in a private envelope that provides a higher degree of privacy than a postcard. We generally don't pay bills or send checks in the mail without an envelope. We shouldn't send private digital transmissions as postcards, either. We should use an encryption technology or the digital equivalent of an envelope.
Encryption of DNS: HTTPS or TLS?
There is a raging debate between the two standardized protocols for encrypting DNS requests: DNS-over-HTTPS (RFC 8484) and DNS-over-TLS (RFC 7858 and RFC 8310). While both of these encrypt DNS requests, there are some important differences and pros and cons to each.
DNS-over-TLS uses TCP as the basic connection protocol and layers over TLS encryption and authentication. DNS-over-HTTPS uses HTTPS and HTTP/2 to make the connection. These are important distinctions because they affect what port is used in each case. DNS-over-TLS uses port 853. DNS-over-HTTPS uses port 443, standard for HTTPS traffic (the modern websites and apps we use travel over this port, too).
In the case of DNS-over-TLS, having a dedicated port is an advantage from a network management and security operations perspective because it can be easily identified and isolated. However, because of the dedicated port (853), it's easy to tell you're using it, which isn't great for privacy.
DNS-over-HTTPS, on the other hand, is great for privacy because it blends in with other ubiquitous HTTPS traffic on port 443, making it difficult to tell someone is encrypting their DNS requests. However, it makes blocking malicious websites more difficult because instead of just blocking DNS requests on a specific port we'd have to block HTTPS traffic, which is more complicated.
Confused, yet? Yep, it's complicated!
If you wish, you can read more on the differences here: https://www.thesslstore.com/blog/dns-over-tls-vs-dns-over-https/
About a year ago, the debate came to a pointed head in this tweet between some of the folks involved: https://twitter.com/grittygrease/status/1053505079515312128
Gotta Start Somewhere
While the battles of taste may never be won and will continue to rage on, I've chosen to start with DNS-over-HTTPS. There is no perfect solution but we can overcome its shortcomings using a tool like Pi-Hole to work around the management limitations while optimizing it's value to our privacy.
In the words and ideas that follow, I'm going to share how I set up DNS-over-HTTPS on my home network and hopefully it will be useful for someone else who's keen on this idea and is looking to learn more, too. You can tinker with this approach and make up your own mind. In the end, it comes down to personal preference.
Pi-Hole: A Black Hole for Advertisements
First, some housekeeping - massive gratitude to Jacob Salmela who has built this wonderful set of tools called Pi-Hole that replaces regular DNS servers and offers some functionality the others don't: it can't encrypt our DNS queries but it can block ads (and also any domains we choose) for all devices on any network.
Pi-Hole is open source software, which is great because we can make our own modifications to it if we choose and it's supported by a community of people who value and work to continue improving it.
Pi-Hole is awesome for two important reasons:
First, Pi-Hole saves a TON of bandwidth or, figuratively speaking, the water pressure of the Internet, which greatly improves performance on a home or corporate network by only loading the content we're requesting minus all the scwhack advertisers send along with it.
Second, it's a great way to filter DNS-over-HTTPS in order to make up for the lack of value from the security operations side-of-the-coin, as pointed out by Paul Vixie (in the image above), by allowing us to black or whitelist domains using lists or one-offs:
- Pi-Hole speeds up the overall performance of a network by denying those ads a significant share of bandwidth or water pressure, as it were, and reclaims it for what we actually intend to use it for.
- By doing so, Pi-Hole also prevents those ads from doing their bidding - collecting personal information about us without our consent, such as our IP address, geographical location, the kind of devices we use, what we do with them, how often, using what apps, and much more intrusive behavioral analysis that helps advertisers build profiles of us and our family and/or whoever else is using the network.
- Not to mention, we can also use it to block known malware command-and-control infrastructures, too, which offers us more resilience.
To run Pi-Hole, we need hardware that can run a compatible operating system, such as an old laptop or desktop computer or a small and inexpensive Raspberry Pi. I've set these up on various architectures, including ARM, x86_32/64. There are many options to choose from to suit your own preferences.
This guide is going to presume that since you've read this far you likely have a compatible device already living on your network that can be used and want to get to the focus: sending DNS requests in more secure envelopes using a technology like DNS-over-HTTPS or DoH. If so, read on.
If you're a few steps behind, that's okay! Here's a great guide for setting up a Raspberry Pi with Pi-Hole: https://techwiser.com/how-to-set-up-pi-hole-on-raspberry-pi-4/
Encrypting DNS Queries
Argo Tunnel creates an encrypted tunnel between the DNS server (in this case Pi-Hole) and Cloudflare’s nearest data center without opening any publicly-accessible inbound ports on our server and/or firewall. cloudflared (the d at the end stands for daemon) is a small piece of software that runs on the server that acts as a proxy DNS service, a service that works in place of the way these are typically sent, sending all DNS queries through this private tunnel.
Let's install both of these on our Pi-Hole server (make sure you note the directory you're in before running the following commands!). First, we'll nab the installer:
Next, let's make a directory to keep it in (we can delete this later if we choose) and un-tar it into there:
mkdir argo-tunnel tar -xvzf cloudflared-stable-linux-arm.tgz -C argo-tunnel
Let's verify the version we just installed and add it to our documentation (we're building good documentation, right? RIGHT?):
cd argo-tunnel ./cloudflared --version
Doing this today at the time of this writing, our output looks like this:
cloudflared version 2019.10.4 (built 2019-10-21-1955 UTC)
Next, let's start cloudflared to proxy all our DNS queries. Note we're not using the default port 53 that DNS uses for a reason (because Pi-Hole is already using that port):
sudo ./cloudflared proxy-dns --port 54 --upstream https://220.127.116.11/.well-known/dns-query --upstream https://18.104.22.168/.well-known/dns-query
The output from that should look like this:
INFO Adding DNS upstream url="https://22.214.171.124/.well-known/dns-query" INFO Starting metrics server addr="127.0.0.1:43389" INFO Adding DNS upstream url="https://126.96.36.199/.well-known/dns-query" INFO Starting DNS over HTTPS proxy server addr="dns://localhost:54"
Next, we need to configure Pi-Hole to use this new functionality.
Putting It All Together
We need to edit some things to put this all to work. We'll start by modifying the following file. I like vim but you can use whatever editor you prefer:
sudo vim /etc/dnsmasq.d/01-pihole.conf
In this file, if we want to use our Argo Tunnel'd and proxied connection to Cloudflare, we need to comment out the two existing server values,
#server=188.8.131.52, and replace them with
#server=184.108.40.206 #server=220.127.116.11 server=127.0.0.1#54
Gratefully, Steve Lord offered this wise addition, too:
So let’s add that, too, before we write and save that file:
Next, we need to edit the following file:
sudo vim /etc/pihole/setupVars.conf
Simply comment out the two DNS entries:
Save the file.
Last, restart the DNS service:
sudo systemctl restart pihole-FTL.service
Our Pi-Hole will now send all DNS requests to cloudflared which runs as our DoH proxy over an encrypted tunnel directly to Cloudflare.
We can test this to check our work. Start with https://www.dnsleaktest.com/ --> it will tell us right away:
You may see more than one DNS server listed and that’s okay just as long as Cloudflare is listed under ISP. You were successful!
Next, we can test our work against Cloudflare: https://18.104.22.168/help --> this is what we want to see:
Make Sure cloudflared Runs As A Service
If our tests all look good, the last detail is to make sure cloudflared will always be running, even when we restart our DNS server, whether it's a Raspberry Pi or other device. We need to create a new file to ensure it does:
sudo vim /etc/systemd/system/dnsproxy.service
In this new file, copy and paste the following code:
[Unit] Description=CloudFlare DNS over HTTPS Proxy Wants=network-online.target After=network.target network-online.target [Service] ExecStart=/home/pi/argo-tunnel/cloudflared proxy-dns --port 54 --upstream https://22.214.171.124/.well-known/dns-query --upstream https://126.96.36.199/.well-known/dns-query Restart=on-abort [Install] WantedBy=multi-user.target
Last but not least, run this command to ensure the cloudflared service will start up on device boot and/or restart itself should the service fail for some reason:
sudo systemctl enable dnsproxy.service
Make the Most of Pi-Hole
This cool Pi-Hole setup is most valuable when every device on a network uses it. The easiest way is to tell the network (via the router or whatever is serving DHCP and/or DNS) to use the new Pi-Hole as the primary DNS server. Depending on your own, unique setup and the make/model of your router or switch, as the case may be, these steps will differ.
Whatever the steps involved, it's worthwhile to use Pi-Hole as the authoritative DNS server on the network and watch the statistics roll in. This fantastic tool helps improve performance and improves our privacy and that of our friends, teams, and families.
Here's my own stats below. The 2 clients represent my core router and primary DNS server:
Gratitude for inspiration:
I am not the first one to write about putting this to work using these tools. I'm grateful for others who've done the work, too, and I'm happy to update their efforts while also giving credit where it's due: