I recently installed named/bind9 on one of my Raspberry Pis to use as a DNS server for my local network. Although initially written for my Raspberry Pi install, this has since been tested on Ubuntu as well. It should also work on any system you can run bind/named on, although you may need to find the appropriate packages via your distribution’s package manager if you’re running something other than a Debian-based system.
The most recent version this guide has been tested on is: BIND 9.18.18-0ubuntu0.22.04.2-Ubuntu
Here’s my notes from the setup:
Installing BIND9 & Utils
sudo apt install bind9 bind9utils bind9-doc dnsutils
Configuring as a Forwarder
Configuration files for “named” / bind(9) are located in the /etc/bind
directory. We can edit the named.conf.options
file to configure our server as a forwarder.
// This is the local lan access control list (acl), configure to your subnet.
acl local-lan {
localhost;
192.168.1.0/24;
};
options {
directory "/var/cache/bind";
// If there is a firewall between you and nameservers you want
// to talk to, you may need to fix the firewall to allow multiple
// ports to talk. See http://www.kb.cert.org/vuls/id/800113
// If your ISP provided one or more IP addresses for stable
// nameservers, you probably want to use them as forwarders.
// Uncomment the following block, and insert the addresses replacing
// the all-0's placeholder.
forwarders {
1.1.1.1; // Cloudflare
8.8.8.8; // Google
};
allow-query { local-lan; };
//========================================================================
// If BIND logs error messages about the root key being expired,
// you will need to update your keys. See https://www.isc.org/bind-keys
//========================================================================
dnssec-validation auto;
auth-nxdomain no; // conform to RFC1035
listen-on-v6 { any; };
// Additional config for our usage
recursion yes;
querylog yes; // Disable if you want, nice for debugging.
version "not available"; // Disable for security
};
Adding our own Zones
For adding our own zones, we’ll add a separate file called zone.<domain>
in this folder.
We’ll then add the domain to the /etc/bind/named.conf.local
file so it’ll be served:
//
// Do any local configuration here
//
// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";
zone "lan.example.com" {
type master;
file "/etc/bind/zone.lan.example.com";
};
Here’s the content of my /etc/bind/zone.lan.example.com
file:
; BIND data file for us-ne-1 lan0
;
$TTL 604800
@ IN SOA lan.example.com. (
admin.example.com. ; Owner
4 ; Serial - increment after save
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
@ IN NS lan.example.com.
@ IN A 10.10.0.1 ; Address of this server
foo IN A 10.10.0.2 ; Add more records here!
Debugging / Checking for errors
Using named-checkzone
You can individually debug zonefiles by checking their config. Any issues with the zone file should be printed to the console.
named-checkzone lan.example.com /etc/bind/zone.lan.example.com
Should output something like this:
zone lan.example.com/IN: loaded serial 4
OK
Using named-checkconf
The same goes for your config files, you can use named-checkconf
and it’ll print any syntax issues you may have. However, this doesn’t print an “OK” message, like you get from named-checkzone
. If you’re not seeing any output, it’s likely your config is fine, especially if checking the exit code via echo $?
returns 0
.
named-checkconf /etc/bind/named.conf
Debug Mode
You can also start named
in debug mode, although this doesn’t always seem to yield the most helpful results. I’d recommend checking the config files above before debugging elsewhere.
sudo -u bind named -d 1
Applying Changes
After making changes to the config files, you’ll need to restart the named
service to apply the changes. This may vary distribution to distribution:
sudo systemctl restart named
Testing it out
finally, to test it out, you can use dig
to query your server. dig
is included in the dnsutils
package we installed earlier.
I’m querying from on the host itself, hence the @127.0.0.1
, if you’re querying from another host, you can replace it with the IP of the host running named.
$ dig @127.0.0.1 foo.lan.example.com
;; ANSWER SECTION:
foo.lan.example.com. 604800 IN A 10.10.0.2
You should also be able to query for external domains:
$ dig @127.0.0.1 google.com
;; ANSWER SECTION:
google.com. 300 IN A 142.250.176.206