Barton Bytes   Archives  About

How to Configure CoreDNS for DNS Over TLS


CoreDNS makes DNS-over-TLS easy to implement



In this tutorial, we’re going to run CoreDNS in Docker containers. One container will listen for standard DNS queries on port 53, and it will resolve these queries using DNS-over-TLS upstream. Another container will listen for DNS-over-TLS queries on port 853, and will resolve these queries using standard DNS.

I’m going to assume that you have an intermediate DNS server, like a Pi-Hole, which will cache responses and filter out ads. We’ll set everything up so that your Pi-Hole will forward queries to the container that encrypts our upstream queries using DNS-over-TLS, and the container that listens for DoT will forward queries to our Pi-Hole for filtering.

DNS network topology

I would highly recommend running these containers on an x86_64 machine, since it will be much simpler than trying to run them on an ARM machine like a Raspberry Pi. This guide will not work on a Raspberry Pi: you’ll need to make some tweaks to get it functional.

To start, make sure that both Docker and docker-compose are installed on your system. You can learn how to install Docker here.

And, assuming that you’re on a Debian-based machine:

sudo apt install -y docker-compose

Now, let’s clone the repository that contains some config files we’ll use:

git clone https://github.com/gdbarton/simple-coredns-tls.git && cd simple-coredns-tls

Let’s look through the config files and verify that everything is accurate for your purposes.

First, the coreconfig-up file. You can change the upstream server if you’d like, or lengthen the cache if you’re not using a Pi-Hole:

. {
  forward . tls://9.9.9.9 tls://149.112.112.112 {
    tls_servername dns.quad9.net
    health_check 10s
  }
  cache 60
}

Now the coreconfig-down file. Make sure to change the ‘forward’ address to that of your Pi-Hole (or any other standard DNS server):

tls://.:853 {
  tls /etc/coredns/cert.pem /etc/coredns/key.pem /etc/coredns/ca.pem
  forward . 192.168.0.2:53
  log
}

You’ll notice that the coreconfig-down contains a cert, key, and CA. You can follow a guide like this to make one, or you can generate it using the configure.sh file that I provided (must be run with sudo). You can hit Enter on all of the prompts without entering any information.

If you don’t use my configure.sh script, make sure you move the coreconfig files and the three .pem files into the /etc/coredns directory, and that they all have the correct names.

Finally, check the docker-compose.yml file. If you’re running CoreDNS on the same server as another DNS server, you’ll need to change the two 53s before the colons (on lines 6 and 7) to a different number, like 5553:

version: "3"
services:
        forwarder:
                image: "coredns/coredns"
                ports:
                        - "53:53/udp"
                        - "53:53"
                volumes:
                        - "/etc/coredns/:/etc/coredns/"
                command: -conf /etc/coredns/coreconfig-up
                restart: always
                container_name: coredns_up

        listener:
                image: "coredns/coredns"
                ports:
                        - "853:853"
                volumes:
                        - "/etc/coredns/:/etc/coredns/"
                command: -conf /etc/coredns/coreconfig-down
                restart: always
                container_name: coredns_down

Once everything is verified and in the right place, we can bring up the containers:

docker-compose up -d

Verify That It Works

We need to start by installing the program kdig, which will let us test our new DNS containers. On Debian, run:

sudo apt install -y knot-dnsutils

Let’s verify that the forwarder is resolving DNS queries. From your client machine or Pi-hole, run this:

kdig @IP -p PORT yahoo.jp

…where IP is the IPv4 address of your CoreDNS machine, and PORT is the leftmost port you listed in the docker-compose file for the forwarder container. If dig is not installed, run sudo apt install -y dnsutils

If the DNS resolves correctly, we can point all of the machines on our network to the CoreDNS forwarder. In the Pi-hole web GUI, hit Settings on the left, followed by DNS at the top. Under Upstream DNS Servers Custom 1, enter the IP address and port of your CoreDNS forwarder (the same IP and port we used in our dig command above):

Pi-Hole Configuration

Finally, we need to test the listener container. Again from your client machine or Pi-hole, run a kdig command:

kdig @IP +tls example.com

You can configure DNS-over-TLS on your client by using a program like dnsproxy

If both of your kdig commands return addresses, then congratulations, your CoreDNS containers are working properly!

Written on Jan 7, 2020.