From Bind to nsd and unbound on OpenBSD 5.6

       652 words, 4 minutes

I’ve been using Bind as a primary, slave or cache name server for all my IT life. But it seems Bind is being kicked out of OpenBSD. So far so good, I’m gonna use what’s provided by my favorite OS to do the job.

Here’s how to use nsd and unbound daemons to serve as an internal authoritative DNS nameserver and DNS resolver. Both will be running on the same machine.

The system

The server will be running OpenBSD 5.6 amd64. It ships with native nsd and unbound daemons. So since you install the OS, you get the toys.

# uname -a                
OpenBSD cheetara.tumfatig.net 5.6 GENERIC.MP#333 amd64
# nsd -v
NSD version 4.0.3
# unbound -dv 
[1424036203] unbound[24599:0] notice: Start of unbound 1.4.22.

The authoritative DNS nameserver

I’ll run both authoritative and resolver on the same host. I could either use different IP adresses and/or ports. Since I only have one authoritative nameserver, I don’t care using unusual ports. So I choose to use same IP and different ports. Only the resolver with query the authoritative nameserver.

Tell OpenBSD to start nsd on boot:

# vi /etc/rc.conf.local
(...)
nsd_flags=""
(...)

Then edit the configuration file. The daemon will “bind” on port 8053 for all IPv4 adresses. I have 3 authoritative zones for which I want to use private name resolution.

# vi /var/nsd/etc/nsd.conf
server:
        hide-version: yes
        ip-address: 0.0.0.0@8053

remote-control:
        control-enable: yes

zone:
        name: "tumfatig.net"
        zonefile: "tumfatig.net"
zone:
        name: "carnat.net"
        zonefile: "carnat.net"
zone:
        name: "192.in-addr.arpa"
        zonefile: "192.in-addr.arpa"

The zone files are stored in /var/nsd/zones/. Zones files are compatible with Bind format so you can simply scp them ; or use AXFR ; or write from scratch. The file name is the one referenced in the “zonefile” parameter.

That’s it. Just start the daemon and you’re done.

# /etc/rc.d/nsd start                                                                    
nsd(ok)
# nsd-control status                                                                     
version: 4.0.3
verbosity: 0
ratelimit: 200
# nsd-control zonestatus tumfatig.net
zone:   tumfatig.net
        state: master
# nsd-control zonestatus openbsd.org  
error zone openbsd.org not configured

The DNS resolver

The DNS resolver is the daemon that will query the DNS world on behalf of my LAN’s DNS clients. It’ll use Internet root DNS servers for general queries. For my “private” DNS zones, it will query the authoritative DNS nameserver previously created.

Tell the system that unbound will have to be launched at boot time:

# vi /etc/rc.conf.local
(...)
unbound_flags=""
(...)

Then edit the configuration file. The daemon will listen on every IP adresses, usual port. It will be told to use the local nsd daemon for my private zones.

# vi /var/unbound/etc/unbound.conf
server:
        interface: 0.0.0.0
        interface: ::0

        access-control: 192.168.0.0/24 allow
        access-control: 127.0.0.0/8 allow
        access-control: ::0/0 refuse
        access-control: ::1 allow

        hide-identity: yes
        hide-version: yes

        auto-trust-anchor-file: "/var/unbound/db/root.key"
        
        local-zone: "168.192.in-addr.arpa." nodefault

remote-control:
        control-enable: yes
        control-interface: 127.0.0.1
        control-interface: ::0
        
stub-zone:
        name: "tumfatig.net"
        stub-addr: 192.168.0.60@8053

stub-zone:
        name: "carnat.net"
        stub-addr: 192.168.0.60@8053

stub-zone:
        name: "0.168.192.in-addr.arpa."
        stub-addr: 192.168.0.60@8053

Control keys are to be created to enable remote management:

# unbound-control-setup
setup in directory /var/unbound/etc
generating unbound_server.key
(...)
generating unbound_control.key
(...)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
(...)
Setup success. Certificates created. Enable in unbound.conf file to use

By default, those keys are used if they exists. So there’s nothing more to do.

That’s all. Now start the daemon and enjoy:

# /etc/rc.d/unbound start
unbound(ok)
# unbound-control status
version: 1.4.22
verbosity: 1
threads: 1
modules: 2 [ validator iterator ]
uptime: 8 seconds
unbound (pid 5712) is running...
# unbound-control list_stubs
. IN stub prime: M.ROOT-SERVERS.NET. L.ROOT-SERVERS.NET. K.ROOT-SERVERS.NET. J.ROOT-SERVERS.NET. I.ROOT-SERVERS.NET. H.ROOT-SERVERS.NET. G.ROOT-SERVERS.NET. F.ROOT-SERVERS.NET. E.ROOT-SERVERS.NET. D.ROOT-SERVERS.NET. C.ROOT-SERVERS.NET. B.ROOT-SERVERS.NET. A.ROOT-SERVERS.NET. 2001:dc3::35 2001:500:3::42 2001:7fd::1 2001:503:c27::2:30 2001:7fe::53 2001:500:1::803f:235 2001:500:2f::f 2001:500:2d::d 2001:503:ba3e::2:30 202.12.27.33 199.7.83.42 193.0.14.129 192.58.128.30 192.36.148.17 128.63.2.53 192.112.36.4 192.5.5.241 192.203.230.10 199.7.91.13 192.33.4.12 192.228.79.201 198.41.0.4
carnat.net. IN stub noprime: 192.168.0.60
tumfatig.net. IN stub noprime: 192.168.0.60
168.192.in-addr.arpa. IN stub noprime: 192.168.0.60

So far, it took only a few couple of minutes to set this up.
Later on, I’ll dig around statistics for those ; and how to draw pretty graphics out of them.
Cheers!