Who do you trust? And do you trust them indefinitely far into the future?
If you have specific reasons to believe you will be targetted by an interested, competent, resourceful attacker: you need serious information security measures, which will be painful and potentially expensive in both time and money. I have no such specific fears, so I’m merely interested in protecting my household against generalized attacks, the sort of thing that Google and Facebook and Amazon and every advertiser in the world carries out as a matter of course.
In this installment, I’m going to increase the difficulty of tracking my household network via intercepting DNS requests. I will assume you know a fair amount about DNS and feel comfortable configuring daemons and running them – this isn’t a step-by-step HowTo.
Let’s start with an overview of what we’re working with. This is the house network of an opinionated sysadmin, with a handful of users ranging from a former director of technical support for a major network through some teenagers who like to play games. I prefer to optimize for cost, with the proviso that I discount my cost of designing, installing and maintaining systems significantly.
There is one internet connection, which hands off as a gigabit ethernet port. I have an overkill-spec firewall, previously documented on this blog. There’s a general purpose server that I expect to be up nearly continuously, and then a bunch of client machines and access points and so forth.
I already run an authoritative DNS server (bind) for internal service on the server, and a caching resolving service (unbound) on the firewall. I block access to Google’s 126.96.36.199 and 188.8.131.52 DNS resolvers, because of an annoying interaction between ChromeOS devices and the odd static IPv6 setup.
My goal is to reduce the analyzability of our DNS traffic. The current state is that unbound and bind both know about the root servers, so we don’t directly query the ISP’s DNS servers and so they don’t get the easiest possible log. Instead, they would have to direct a router upstream of us to log all port 53 requests. That’s a little more work for them, but not much. And it’s only a little data, which costs little to store against a rainy day when you suddenly want to find out my history and correlate it against my other suspicious activities, like voting and being kind to people who ask for help.
If all the root servers and TLD servers spoke DNS-over-TLS, this problem would be solved immediately. That’s not the case.
There are lots (dozens!) of public-facing DNS servers that do speak DNS-over-TLS. Some of them have explicit no-logging policies. My policy decision here is to have unbound use at least a dozen of them as forwarders.
Unbound will serve as a local cache, and forward requests over TLS to the multiple upstream resolvers; it will know about local domains and forward those to the bind server. The bind server will treat the unbound server as its own forwarder for anything that it doesn’t know about locally.
Useful implementation notes:
For unbound.conf, you want something similar to this:
qname-minimisation: yes hide-version: yes hide-identity: yes root-hints: "/etc/unbound/root.hints" tls-cert-bundle: "/etc/ssl/certs/ca-certificates.crt" private-domain: "local" private-domain: "use-application-dns.net" forward-zone: name: "local" forward-addr: 10.12.0.2 forward-zone: name: "use-application-dns.net" forward-addr: 10.12.0.2 forward-zone: name: "." forward-ssl-upstream: yes forward-addr: 184.108.40.206@853#cloudflare-dns.com
Note that you can add multiple
forward-addr: entries to a
forward-zone, and that the form for DNS over TLS is
IP @ port # domainname so that you can match the upstream cert to a particular name. The
tls-cert-bundle above is appropriate for Debian.
The existence of the zone “use-application-dns.net” without any resolvable hosts in it is a hint to Firefox and eventually other DNS-over-HTTPS clients that they should not bypass all the local arrangements in order to send data to Mozilla’s preferred trading partner of the day.