Setup CoreDNS as local DNS resolver

System setup

I am using ubuntu 20.10 as reference system with docker and docker-compose installed.

Ubuntu and other OSes comes with systemd-resolved installed and listening on port :53, preventing to listen on that port. Thanks to linuxuprising.com tutorial for the steps.

To check which port is in use in your system run sudo lsof -i :53. The response looks like

1
2
3
COMMAND   PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd-r 972 systemd-resolve 12u IPv4 32039 0t0 UDP 127.0.0.53:domain
systemd-r 972 systemd-resolve 13u IPv4 32040 0t0 TCP 127.0.0.53:domain (LISTEN)

Disable DNS stub listener option and set a default DNS

1
2
3
4
echo 'DNSStubListener=no' | sudo tee -a /etc/systemd/resolved.conf
echo 'DNS=1.1.1.1' | sudo tee -a /etc/systemd/resolved.conf
# check it is ok
cat /etc/systemd/resolved.conf

Replace the default resolv.conf file

1
2
sudo cp /etc/resolv.conf /etc/resolv.conf.bak
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Finally reload the systemd-resolved service

1
sudo service systemd-resolved restart

Create a docker-compose file for coredns

Now create a docker-compose.yaml file with the following content. We expose port :53 tcp and udp and use the coredns/coredns docker image. It also mount the local folder ./config to /etc/coredns in the container, where we will store our configurations.

1
2
3
4
5
6
7
8
9
10
11
version: "3.1"
services:
coredns:
image: coredns/coredns
command: -conf /etc/coredns/Corefile
volumes:
- ./config:/etc/coredns
restart: unless-stopped
ports:
- '53:53'
- '53:53/udp'

Create a ./config folder and add in it a Corefile file

1
2
3
4
5
6
7
.:53 {
log
errors
ready
file /etc/coredns/lan.zone lan
forward . 1.1.1.1
}

See the Coredns configuration docs for more information

Add a zone file (named /etc/coredns/lan.zone from the previous example) with the references to the IPs in the network. It is based on a Wikipedia example but there are many more examples online as the format is standardized.

In the example the machine IP hosting the DNS server is 192.168.1.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@  3600  IN  SOA  ns1.lan.  root.lan.  (
2019041900
3600
600
604800
600 )
3600 IN NS ns1.lan.
3600 IN NS ns2.lan.

ns1 IN A 192.168.1.2
ns2 IN A 192.168.1.2

;Example for IPv4, will provide ip for raspberrypi.lan
raspberrypi IN A 192.168.1.99

Now start the DNS server with docker-compose up.

You can test the resolution with nslookup

1
2
3
4
5
6
7
8
# replace the ip with your dns server ip
nslookup -norec raspberrypi.lan 192.168.1.2
# response
Server: 192.168.1.2
Address: 192.168.1.2#53

Name: raspberrypi.lan
Address: 192.168.1.99