NLnetLab Logo This post will cover a very simple Domain Name System server installation and will implement the NSD server to respond authoritatively for requests on the private network 192.168.1.0/24. Also, Unbound will act as a caching server, to provide query results, that local hosts on the network can quickly refer to. Both NSD and Unbound are developed by NLnetLabs and are available in the OmniOS Extra Repository.

To follow this post you should have a recent version of OmniOS installed and have the OmniOS Extra Repository enabled. The purpose of the post is more to get a DNS implementation running quickly, rather than going into fine details of DNS configuration. I have provided some links when further information is desirable. This post will not cover DNSSEC in any way, nor will it cover nsd-control which is disabled as a default setting. You should not need to set aside more than an hour to follow this post (including additional reading).

NSD will take care of the Authoritative DNS Server, which will provide information about the local hosts on the private network. This can provide records for canonical names, domain aliases, mail servers, reverse dns entries etc… If all you need is to provide A name & PTR records, then Unbound has a feature that can serve these without having to install an authoritative DNS server.

Unbound will act as the Caching DNS Server. The main reason to run a caching server is that by caching request results, made from hosts on the network, this can drastically speed up DNS resolution and also save bandwidth.

Why NSD & Unbound? Why not BIND? The NSlabsNet tools have become the default DNS server software for many Linux & *BSD distributions. In OmniOS, the BIND DNS server is not currently available in the software repositories, however, should be very soon. The case for using the NLnetLab tools has been claimed, the ease of configuration and also that the daemons are seperated into specific services to run either caching or authoritative services. Also, a lot of detractors of BIND will say that it has been plagued with secrutity problems, but this does not seem to be the case since BIND version 9.

I feel both NLnetLabs and the Internet Systems Consortium are both highly commendable projects, and it is worth taking some time to read about these organisations.

Installing NDS & Unbound on OmniOS

Simply issue the following command to install both NSD & Unbound.

pkg install nsd unbound

Configure NSD to serve a private “zone”

NSD will act as an authrotative server, responding to name queries for hosts on a private network. In DNS paralance this is called creating a “Zone”. Before we do this, the server needs to be configured. An excellent source of information for configuring NSD is the nsd.conf file itself. This includes, most if not all directives relative to the NSD server and these are commented on thoroughly. The objective of this post is not to get into such detail, therefore I will strip out everything that is a comment from the nsd.conf file and display what we have left, as follows:

# cd /etc/opt/ooce/nsd
# grep '^[[:blank:]]*[^[:blank:]#;]' nsd.conf.sample > nsd.conf
# cat nsd.conf
server:
remote-control:

Not much, just the bare minimum to have the server start.

I have fleshed out this file with minimal configuration settings and a couple of administratve declarations, followed by the zone information that I wish to serve for the private network.

server:
        server-count: 1
        ip-address: 127.0.0.1
        logfile: "/var/log/opt/ooce/nsd/log/nsd.log"
        pidfile: "/var/opt/ooce/nsd/run/nsd.pid"

remote-control:

zone:
        name: "internal.pbdigital.org"
        zonefile:  "/var/opt/ooce/nsd/zone/master/%s.dns"
zone:
        name: "1.168.192.in-addr.arpa"
        zonefile:  "/var/opt/ooce/nsd/zone/master/%s.dns"

The server settings should be self explanatory, however I would like to point out that the loopback interface address of 127.0.0.1 is used, as only the unbound server will be making direct quieres to NSD.

Further to this, 2 zones have been created, 1 for the private network internal.pbdigital.org, and the second is the zone for reverse lookups on this private network.

DNS Zone files

A Domain Name System (DNS) zone file is a text file that describes a DNS zone. A DNS zone is a subset, often a single domain, of the hierarchical domain name structure of the DNS. The zone file contains mappings between domain names and IP addresses and other resources, organized in the form of text representations of resource records (RR).

The format of a zone file is defined in RFC 1035 and RFC 1034. This format was originally used by the Berkeley Internet Name Domain (BIND) software package, but has been widely adopted by other DNS server software, such as NSD.

I will not go into further detail here of the zone file format, if you need a primer on this subject I reccommend reading the FreeBSD BIND Documentation.

/var/opt/ooce/nsd/zone/master/internal.pbdigital.org.dns

$ORIGIN .
$TTL 3600       ; 1 hour
internal.pbdigital.org  IN SOA  bloody.internal.pbdigital.org. admin.internal.pbdigital.org. (
                        40       ; serial
                        86400   ; refresh (1 day)
                        3600    ; retry (1 hour)
                        604800  ; expire (1 week)
                        3600    ; minimum (1 hour)
                        )
                NS      bloody.internal.pbdigital.org.
$ORIGIN internal.pbdigital.org.
mordecai        A       192.168.1.53
rigby           A       192.168.1.10
bloody          A       192.168.1.254
gitea           CNAME   rigby

/var/opt/ooce/nsd/zone/master/1.168.192.in-addr.arpa.dns

$ORIGIN .
$TTL 3600       ; 1 hour
1.168.192.in-addr.arpa  IN SOA  bloody.internal.pbdigital.org.  admin.internal.pbdigital.org. (
                                40   ; serial
                                86400   ; refresh (1 day)
                                3600    ; retry (1 hour)
                                604800  ; expire (1 week)
                                3600    ; minimum (1 hour)
                                )
                        NS      bloody.internal.pbdigital.org.
$ORIGIN 1.168.192.in-addr.arpa.
53                      PTR     mordecai.internal.pbdigital.org.
10                      PTR     rigby.internal.pbdigital.org.
10                      PTR     gitea.internal.pbdigital.org.
254                     PTR     bloody.internal.pbdigital.org.

Starting and testing the authoritive domain name server

Once these 3 files are in place, the NSD server is ready to be started as follows:

svcadm enable nsd

You can now test the server (only) from the localhost that it is installed on… such as:

$ dig @127.0.0.1 bloody.internal.pbdigital.org
; <<>> DiG 9.11.20 <<>> @127.0.0.1 bloody.internal.pbdigital.org
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35734
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;bloody.internal.pbdigital.org.      IN      A

;; ANSWER SECTION:
bloody.internal.pbdigital.org. 3600  IN      A       192.168.1.254

;; AUTHORITY SECTION:
internal.pbdigital.org.      3600    IN      NS      bloody.internal.pbdigital.org.

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Mon Jul 27 16:51:56 CEST 2020
;; MSG SIZE  rcvd: 83

This should confirm NSD is working as anticipated and now it is possible to move on to Unbound, the caching DNS server.

Configuring Unbound as a Caching DNS Server

Unbound, the caching server will query an internet dns server of out choice and will cache the results for queries from hosts on the local network. it will also query the NSD server on 127.0.0.1 for internal domain names.

/etc/opt/ooce/unbound/unbound.conf

# cd /etc/opt/ooce/unbound/
# cp unbound.conf{,.sample}
# grep '^[[:blank:]]*[^[:blank:]#;]' nsd.conf.sample > unbound.conf
server:
        verbosity: 1
chroot: ""
python:
remote-control:
server:
        verbosity: 1
        ip-address: 192.168.1.254
        access-control: 192.168.1.0/24 allow
        do-not-query-localhost: no
        local-zone: "168.192.in-addr.arpa." nodefault

chroot: ""

remote-control:

forward-zone:
        name: "."
        forward-addr: 1.1.1.1
        forward-addr: 1.0.0.1

stub-zone:
        name: internal.pbdigital.org
        stub-addr: 127.0.0.1

stub-zone:
        name: 1.168.192.in-addr.arpa.
        stub-addr: 127.0.0.1

OK, that is a pretty simple unbound.conf. Most all of this is self explanatory, howerver I would like to note the local-zone directive. This is to allow reverse PTR lookups on the private network 1.168.192.in-addr.arpa.

This is further explained in the unbound.conf man page as follows:

The default zones are localhost, reverse 127.0.0.1 and ::1, the onion, test, invalid and the AS112 zones. The AS112 zones are reverse DNS zones for private use and reserved IP addresses for which the servers on the internet cannot provide correct answers. They are configured by default to give nxdomain (no reverse information) answers. The defaults can be turned off by specifying your own local-zone of that name, or using the ‘nodefault’ type.

Further, do-not-query-localhost: no is required as we will be querying lookups for the local zones from NSD on the loopbadk interface.

Just for the sake of completeness, you will need to add update the /etc/resolv.conf file on your system to point to your host that is running Unbound.

search internal.pbdigital.org
nameserver 192.168.1.254

Test from an machine in the internal network, a normal and reverse pointer query should output something similar to the following:

$ dig bloody.internal.pbdigital.org

; <<>> DiG 9.11.14-RedHat-9.11.14-2.fc30 <<>> bloody.internal.pbdigital.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 46547
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;bloody.internal.pbdigital.org.	IN	A

;; ANSWER SECTION:
bloody.internal.pbdigital.org. 3600	IN	A	192.168.1.254

;; Query time: 0 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Mon Jul 27 17:20:51 CEST 2020
;; MSG SIZE  rcvd: 69

and now the reverse ptr query:

$ dig -x  192.168.1.10

; <<>> DiG 9.11.14-RedHat-9.11.14-2.fc30 <<>> -x 192.168.1.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13609
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;10.1.168.192.in-addr.arpa.	IN	PTR

;; ANSWER SECTION:
10.1.168.192.in-addr.arpa. 1812	IN	PTR	rigby.internal.pbdigital.org.
10.1.168.192.in-addr.arpa. 1812	IN	PTR	gitea.internal.pbdigital.org.

;; Query time: 0 msec
;; SERVER: 192.168.1.254#53(192.168.1.254)
;; WHEN: Mon Jul 27 17:20:02 CEST 2020
;; MSG SIZE  rcvd: 111

Wrapping up

That should give you a jumpstart on how to configure DNS with the NL Net Lab Tools. If you would like to discover more about BIND, this should be released for OmniOS very shortly and the documentation at FreeBSD is sufficient to guide you through a similar configuration as above.