Note: this post has been updated to fix a mistake in the knot-resolver configuration. The earlier version would not have provided the privacy it purported to. I regret the error.
Until yesterday I hadn’t thought too much about DNS metadata leakage. Here’s how it works: your computer sends out a request to resolve a DNS hostname, let’s say “topsecretwebsite.example,” and your DNS server responds back with its IP address in a way that’s easy to eavesdrop on. It’s wild that the Internet works like this by default.
What happened yesterday is a company called CloudFlare (a popular and free content delivery network) announced a new DNS service at the IP address
220.127.116.11. (Yes it launched on April 1, no it’s not a joke.) The service supports a couple of interesting privacy protecting options: DNS-over-HTTPS and DNS-over-TLS. Those technologies don’t guarantee your DNS lookups are accurate (check out DNSSEC for that), or that the DNS provider won’t someday betray you, they just make it’s harder to collect metadata by listening in on DNS’s cleartext port 53.
I asked for pointers on Twitter, for how to set this up, and landed on these notes from Daniel Kahn Gillmor (aka dkg) from a workshop he offered at the most recent Internet Freedom Festival. (Thanks for the pointer Jen!)
This all got me to set up my own DNS resolver on my laptop, which runs macOS 10.13.4.
- I’m running a local instance of knot-resolver (the same software that runs CloudFlare’s
- macOS is configured to lookup DNS at
127.0.0.1on the usual port 53
- My local knot-resolver (aka
kresd) is configured to send requests upstream to
1. Install knot-resolver
I used Homebrew to install.
brew install knot-resolver
Then I installed a service to run it on startup.
sudo brew services start knot-resolver
2. Configure knot-resolver
Then I edited the config file.
I added the following to the end of the file:
3. Restart kresd
Restart the service for your change to take effect.
sudo brew services restart knot-resolver
4. Test the “before”
Now you want to configure your system to use the local DNS service. First, see how it responds before we add our own DNS server into the mix.
You should see some results resolving plannedparenthood.com to its IP address
18.104.22.168, with this detail at the bottom about where the results came from (yours will be different).
;; From 192.168.2.1@53(UDP) in 36.8 ms
Basically my computer just broadcast in cleartext, over UDP port 53, “hey
192.168.2.1 do you know where I can find
PLANNEDPARENTHOOD.COM?” This happens each time you load up a website. It happens that
192.168.2.1 is a wifi router in my apartment under my control, but that request still gets passed to other DNS servers upstream, all in cleartext.
5. Configure macOS
Now go to Apple Menu → System Preferences → Network → Advanced → DNS and add
127.0.0.1 as your DNS server.
6. Test the “after”
kdig plannedparenthood.com again. Now you should see your local address at the bottom.
;; From 127.0.0.1@53(UDP) in 149.5 ms
You’ll get the same IP address result, but now delivered to you with the privacy of TLS encryption. Hooray!
If that doesn’t work for you, you may want to check out the log file
/usr/local/var/log/kresd.log for errors.
Also consider using other privacy-protecting DNS services beyond
22.214.171.124. I applaud CloudFlare for drawing attention to how we can improve our network privacy, but if we all use the same service it creates a single point of failure. Alternatively you could go with
dns.cmrg.net (dkg’s own service), or something else.
You should also know there are situations where you need to use a specific DNS server. For example, if you are on a corporate network it might rely on hostnames that aren’t hosted anywhere but on the internal DNS servers. So realize that adjusting your DNS settings means things may break in the future. Try to remember this for when you end up with mysterious network issues in the future!