This is a recreation of a previous blog post on running Unbound, a recursive and caching DNS server on OpenBSD. I originally wanted to run my own DNS server to make it easier to administer the machines on my network instead of having to remember IP addresses. Later on, I would discover that OpenDNS, CloudFlare, and Google are mining your data and selling it on the open market. Additionally, ISPs might also be doing the same thing so it’s time to stand up my own DNS server. With the newer version of Unbound, I discovered that it is now capable of operating as a true authoritative DNS server. It used to be that I ran both Unbound and NSD together on the same machine, Unbound to handle recursion and NSD to handle authoritative DNS. Now it is really easy to do and so easy that you can practically copy the example.
The first step to do is to create the configuration file
/var/unbound/unbound.conf. Remember to backup the original file. In my internal lan, I chose to use the domain
meow.lan after my favorite pets. When you decide on an internal domain, do not use a
.local as the TLD because that might break Apple’s Bonjour protocol and Avahi if you have Apple products. So I suggest using something like
.internal. Below is my configuration file.
server: verbosity: 1 interface: 127.0.0.1 interface: 192.168.0.5 tcp-upstream: yes access-control: 0.0.0.0/0 deny access-control: 127.0.0.0/8 allow access-control: 192.168.0.0/24 allow root-hints: root.hints hide-identity: yes hide-version: yes chroot: "/var/unbound" private-address: 192.168.0.0/24 private-domain: meow.lan domain-insecure: meow.lan insecure-lan-zones: yes unblock-lan-zones: yes remote-control: control-enable: yes auth-zone: name: "meow.lan." zonefile: /var/unbound/zones/meow.lan auth-zone: name: "0.168.192.in-addr.arpa." zonefile: /var/unbound/zones/meow.rev
The part of the configuration file that begins with
private-address is what makes the magic happen. First, we designate the domain that is to be private and we make it insecure because the zone is not signed. Then we allow insecure lan zones and unblock them so that reverse DNS for your hosts works properly. The
auth-zone keywords tell Unbound to treat this data as authoritative.
Now create the directory
/var/unbound/zones to store the zone files necessary for correct DNS resolutions to happen. Below are my forward and reverse zone files which you can use as an example. You can name this anything that you want. I named the file after my domain.
; Forward Zone file $ORIGIN meow.lan. $TTL 300 @ SOA whisker.meow.lan. dnsadmin.meow.lan. ( 2021041501 15m 30m 1d 5m) NS whisker.meow.lan. bastet A 18.104.22.168 bonadea A 22.214.171.124 firestick A 192.168.0.111 jaguar A 192.168.0.171 panther A 192.168.0.131 phone A 192.168.0.186 range-extender A 192.168.0.195 router A 192.168.0.1 tablet A 192.168.0.100 whisker A 192.168.0.5
;Reverse Zone file $ORIGIN 0.168.192.in-addr.arpa. $TTL 1d @ SOA whisker.meow.lan. dnsadmin.meow.lan. ( 2021041501 15m 30m 2w 5m) NS whisker.meow.lan. 1 PTR router.meow.lan. 5 PTR whisker.meow.lan. 100 PTR tablet.meow.lan. 111 PTR firestick.meow.lan. 131 PTR panther.meow.lan. 171 PTR jaguar.meow.lan. 186 PTR phone.meow.lan. 195 PTR range-extender.meow.lan.
It is also necessary to fetch the latest version of the root hints. In the directory,
/var/unbound/etc, run the following command:
dig @a.root-servers.net . NS > root.hints. Once you have done this, it is time to enable and start Unbound.
# unbound-control-setup # rcctl enable unbound # rcctl start unbound
Check to make certain that unbound is running and do a quick query using dig. Below is an example from my LAN. If all works, your results should be similar. This is a forward lookup.
# dig whisker.meow.lan ; <<>> dig 9.10.8-P1 <<>> whisker.meow.lan ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27192 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;whisker.meow.lan. IN A ;; ANSWER SECTION: whisker.meow.lan. 300 IN A 192.168.0.5 ;; Query time: 4 msec ;; SERVER: 192.168.0.5#53(192.168.0.5) ;; WHEN: Thu Apr 15 20:44:05 EDT 2021 ;; MSG SIZE rcvd: 61
Below is a reverse lookup.
# dig -x 192.168.0.5 ; <<>> dig 9.10.8-P1 <<>> -x 192.168.0.5 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9633 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;126.96.36.199.in-addr.arpa. IN PTR ;; ANSWER SECTION: 188.8.131.52.in-addr.arpa. 86400 IN PTR whisker.meow.lan. ;; Query time: 1 msec ;; SERVER: 192.168.0.5#53(192.168.0.5) ;; WHEN: Thu Apr 15 20:45:56 EDT 2021 ;; MSG SIZE rcvd: 83
And there you have it! You now have a fully functioning recursive and authoritative DNS server for your home LAN. This will also work with public servers. Queries that are not for your domain are forwarded on to the root servers for resolution. You don’t have to depend upon Google, OpenDNS, CloudFlare, or your ISP.