An old green door closed behind a padlock and chain.

Actually secure DNS over TLS in Unbound

You’ll find quite a few blog posts and tutorials on how to configure encrypted DNS over TLS forwarding in Unbound. I’ve yet to find a single one that sets up TLS securely with certificate domain validation, however. Without TLS certificate domain validation your DNS can still be intercepted, monitored, or manipulated by a attacker-in-the-middle attacker with nothing more than a self-signed certificate. Here is how you set it up more securely.

I’ve already covered the use and configuration of a local and remote DNS caching service in my Knot Resolver tutorial. I’ll not go over those parts again, but I’ll focus exclusively on the required Unbound configuration and, of course, the necessary parts everyone else skips.

Here is a minimal example configuration for Unbound, /etc/unbound/unbound.conf, that uses both Quad9 and Cloudflare Resolver as the forwarding resolvers and validates their TLS certificates against the expected domain names for each service:

# SPDX-License-Identifier: CC0-1.0

  tls-cert-bundle: /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

  name: "."
  forward-tls-upstream: yes
  # Quad9
  # Cloudflare DNS

The first thing you’ll notice is the inclusion of the tls-cert-bundle option that points to the local system’s root certificate authority bundle; including all the trusted root certificates of the operating system. This is needed to verify the validity of a certificate. You’ll get this bundle by installing the ca-certificates package in most Linux distributions.

The default location of the root certificate bundle is /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem on Fedora Linux, and /etc/ssl/certs/ca-certificates.crt on Debian/Ubuntu. Refer to the documentation of your distribution if you can’t locate their root certificate bundle.

If you haven’t setup the tls-cert-bundle option correctly, you may end up with certificate validation errors (below) and Unbound refusing to connect to the remove resolver:

notice: ssl handshake failed port 853
error: ssl handshake failed crypto error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed

The domain names to validate the certificates against may appear as comments behind the forward-addr configuration lines at first glance. The syntax for forward-addr is IP address of the resolver an @ sign and then the resolver’s port number followed by a # sign and then the expected TLS domain name to validate the certificate the resolver will present.

It’s important that you get these domain names right or otherwise you’ll end up with the same error messages as shown above. Unfortunately, Unbound doesn’t produce different error messages when the certificate domain mismatch, is expired, or when the root certificate is missing or otherwise not trusted.

You should keep an eye on your logs and watch out for any certificate errors. It may be an indication that someone is trying to intercept, monitor, or modify your DNS requests. You can add an additional layer of protection against this by enabling DNSSEC validation.

I’ve added both IPv4 and IPv6 addresses in the above configuration example. Unbound will figure out which protocol is available and which is faster on its own. You can get better reliability from your DNS server by configuring more routes and more options to cover for outages or routing disruptions.

I also wrote about randomizing DNS forwarding servers with Knot Resolver a few weeks back. This ensures you’re not sending all your DNS traffic to one provider; making it more difficult for any one provider to build a complete profile on your online activities and behavior.

Unbound will do this by default with no additional configuration assuming each of your configured DNS forwarders respond within 400 milliseconds. Note that you’re not limited to just four DNS forwarders as you are with Knot Resolver. You can configure as many DNS forwarders as you want with Unbound and it will spread your forwarding requests out among each of them automatically.