Using DNSOverTLS With Unbound
Firstly, DNS is how web addresses are looked up to find their location in terms of IP addresses. So it is actually surprising that this lookup has always been unencrypted. The issue has become mainstream of sorts when UK’s Internet Service Provider’s Association nominated Firefox as an internet villain for enabling DNSOverHTTPS (DoH). This allowed people to bypass DNS based blocking performed by ISPs which further cemented the idea that one needs encrypted DNS to avoid being censored or worse MITMed by an authoritarian government by using domain level blocking. I prefer DoT over the DoH protocol simply because of latency issues caused by dependency on TCP for the latter. DoT works similar to regular DNS over UDP but under a different port. One reason for vendors to prefer DoH, is due to over eager firewalls blocking all ports except 80 and 443, used by HTTP and HTTPS by default. In this post, I want to show you how easy it is to get a secure and private DNS at the OS level, so you can do what Firefox does, but for all applications. Okay, lets get to the crux of the article!
Install and configure unbound
Unbound is usually available in the repositories of operating systems, Linux and BSD. Install it using your favourite package manager and we can begin!
The next step is to configure unbound to use root servers to resolve DNS recursively. This is useful to first get acquainted with unbound and also to rule out issues if DoT fails to work.
# /etc/unbound/unbound.conf server: verbosity: 1 use-syslog: yes # outputs to systemd journal in our case do-daemonize: no # handled by systemd username: "unbound" # use separate user for security directory: "/etc/unbound" auto-trust-anchor-file: trusted-key.key # Auto-update the trust anchors, used for DNSSEC root-hints: root.hints # download root.hints from https://www.internic.net/domain/named.cache
It is important we take care of directory permissions so unbound can read and write to it.
You may have to manually change ownership of
Before starting the service, make sure to change
/etc/resolv.conf to use the local nameserver run by unbound.
# /etc/resolv.conf nameserver 127.0.0.1
This step also requires some care if your distribution is handling DNS using
NetworkManager, refer to configuration related to DNS in the “main section”.
In the case of
systemd-resolved, I would suggest you to just disable and import any local network related settings into unbound.
openresolvconf, we can use it with unbound as a subscriber.
After this is done, start the unbound service and check the logs for errors if any.
You can use
dig to do DNS testing from the terminal. For example,
> drill lobste.rs ;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 42947 ;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;; lobste.rs. IN A ;; ANSWER SECTION: lobste.rs. 3600 IN A 188.8.131.52 ;; AUTHORITY SECTION: ;; ADDITIONAL SECTION: ;; Query time: 400 msec ;; SERVER: 127.0.0.1 ;; WHEN: Wed Jul 10 11:52:06 2019 ;; MSG SIZE rcvd: 43
SERVER in the output to confirm your configuration.
In the previous section unbound recursively resolved the DNS by querying the root servers. But in most cases we would like to resolve them from a caching server close to us. In this case we access the server using TLS like so,
# DNSOverTLS addition to unbound.conf server: tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt # needed for verification of TLS forward-zone: name: "." forward-tls-upstream: yes #nic.cz forward-addr: 184.108.40.206@853#odvr.nic.cz forward-addr: 220.127.116.11@853#odvr.nic.cz forward-addr: 2001:148f:ffff::1@853#odvr.nic.cz forward-addr: 2001:148f:fffe::1@853#odvr.nic.cz
As can be seen the format for
forward-addr in the case of DoT involves specifying the IP, port and name.
The name is checked against the host mentioned in the TLS certificate securing our connection.
In this example I am using the host from (cz.nic)[https://www.nic.cz/odvr/], but other alternative exists from Cloudflare, Google and Quad9 to name a few.
As before, check the configuration using
drill after restarting the service.
You can also check the syntax of the configuration file, before restarting, by using
unbound-checkconf to prevent unnecessary round trips.
Hopefully by the end of this post, you have a secure and private DNS setup!