Configure CoreDNS as basic DNS server on your Local Area Network at home
I use libvirt to create virtual machines on my home server, and when using NAT networking, libvirt can use dnsmasq to register DNS entries for the virtual machines, and both the host machine and the guest networks can utilize this.
Recently I switched to bridge networking where each virtual machine is getting an IP address directly on my LAN. Hence I needed to find a simple way to manage DNS lookups without setting up a full blown and complicated DNS server. Since I have no prior experience with managing DNS servers, I chose to install CoreDNS and configure it to use /etc/hosts as its “database”. The downside is that I will have to manually add IP addresses to /etc/hosts. The upside is that CoreDNS reads this file dynamically.
So all I need to do is:
- Install CoreDNS
- Configure CoreDNS to use /etc/hosts
- Configure CoreDNS to run as a systemd service on my host server.
- Configure the virtual machines to use my CoreDNS server as the primary DNS.
Install CoreDNS
COREDNS_VERSION=1.9.3curl -LO https://github.com/coredns/coredns/releases/download/v$COREDNS_VERSION/coredns_$COREDNS_VERSION_linux_amd64.tgztar zxvf coredns_$COREDNS_VERSION_linux_amd64.tgzchmod +x corednssudo mv coredns /usr/binrm zxvf coredns_$COREDNS_VERSION_linux_amd64.tgz
Configure CoreDNS
Most of the configuration was found in the Arch Linux wiki: https://wiki.archlinux.org/title/CoreDNS#Configuration
mkdir -p /etc/coredns
Create a file called /etc/coredns/Corefile with the following configuration:
.:53 {
bind 10.0.1.74
bufsize 1232
acl {
allow net 10.0.0.1/23
block
}
hosts {
reload 0
fallthrough
}
cache {
success 4096
denial 1024
prefetch 512
}
errors
log
}
The “bind 10.0.1.74” tells CoreDNS to bind to IP address 10.0.1.74 on my host server where I installed CoreDNS.
The “allow net 10.0.0.1/23” is the CIDR range I will allow DNS lookup requests. This range is my LAN’s CIDR range with IP addresses from 10.0.0.0 through 10.0.1.255.
Configure CoreDNS to run as a systemd service
useradd coredns -s /sbin/nologin -c 'coredns user'touch /usr/lib/systemd/system/coredns.servicechmod +x /usr/lib/systemd/system/coredns.service
The file /usr/lib/systemd/system/coredns.service has the following content:
[Unit]
Description=CoreDNS DNS server
Documentation=https://coredns.io
After=network.target
[Service]
PermissionsStartOnly=true
LimitNOFILE=1048576
LimitNPROC=512
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
User=coredns
WorkingDirectory=/home/coredns
ExecStart=/bin/bash -c '/usr/bin/coredns -conf=/etc/coredns/Corefile'
ExecReload=/bin/kill -SIGUSR1 $MAINPID
Restart=on-failure
[Install]
WantedBy=multi-user.target
Enable and start the service:
systemctl enable coredns
systemctl start coredns
Allow network traffic to reach the DNS server at port 53:
firewall-cmd --permanent --zone=public --add-port=53/tcp
firewall-cmd --permanent --zone=public --add-port=53/udp
firewall-cmd --reload
Configure the VMs to use CoreDNS as the primary DNS
On each of my virtual machines, I have configured the nameservers like this:
#!/bin/bash
nmcli con mod "System eth0" ipv4.dns "10.0.1.74 10.0.0.1 8.8.8.8"
systemctl restart NetworkManager
What this does is that it configures the eth0 device to use my host server with IP 10.0.1.74 as the primary nameserver, my LAN router with IP 10.0.0.1 as the secondary nameserver and finally Google’s public DNS 8.8.8.8 as the tertiary nameserver for the eth0 network interface.