How to run master and slave NSD on FreeBSD 9.0

Prime knots chart[Running FreeBSD10? Check my new article: How to run master NSD on FreeBSD 10.0].

NSD  is  a  complete  implementation of an authoritative DNS nameserver written and maintained by NLnet Labs. Authoritative and not recursive. If you need a recursive and caching resolver please consider using Unbound and reading my article “How to configure Unbound with DNSSEC validation on FreeBSD 9.0”.

I’m going to lead you through an easy step by step guide: install, configure and run NSD in a chrooted environment for both master and slave instances.

Common background for both master and slave servers:

cd /usr/ports/dns/nsd
make install clean
cd /usr/port/dns/opendnssec
make install clean
cp /usr/local/etc/nsd/nsd.conf.sample /usr/local/etc/nsd/nsd.conf

Prepare the tree for chrooted environment:

mkdir -p /usr/local/etc/nsd/var/db/nsd
mkdir /usr/local/etc/nsd/var/run
mkdir /usr/local/etc/nsd/var/log

Make NSD start at boot:
echo 'nsd_enable="YES"' >> /etc/rc.conf

On master server.
Edit nsd.conf and feel free to use the following lines, slightly customized for a master role, being 192.0.2.1 master’s ipv4 address and 192.0.2.2 slave’s ipv4 address.
vi /usr/local/etc/nsd/nsd.conf

#
# nsd.conf -- the NSD(8) configuration file, nsd.conf(5).
#
# Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
#
# See LICENSE for the license.
#

# This is a comment.
# Sample configuration file

# options for the nsd server
server:
# uncomment to specify specific interfaces to bind (default wildcard interface).
# ip-address: 1.2.3.4
# ip-address: [email protected]
# ip-address: 12fe::8ef0

# don't answer VERSION.BIND and VERSION.SERVER CHAOS [prado.it] class queries
hide-version: yes

# enable debug mode, does not fork daemon process into the background.
# debug-mode: no

# listen only on IPv4 connections
# ip4-only: no

# listen only on IPv6 connections
# ip6-only: no

# the database to use
database: "/var/db/nsd/nsd.db"

# identify the server (CH TXT ID.SERVER entry).
# identity: "unidentified server"

# NSID identity (hex string). default disabled.
# nsid: "aabbccdd"

# log messages to file. Default to stderr and syslog (with facility LOG_DAEMON).
logfile: "/var/log/nsd.log"

# Number of NSD servers to fork.
server-count: 1

# Maximum number of concurrent TCP connections per server.
# This option should have a value below 1000.
tcp-count: 10

# Maximum number of queries served on a [prado.it] single TCP connection.
# By default 0, which means no maximum.
# tcp-query-count: 0

# Override the default (120 seconds) TCP timeout.
# tcp-timeout: 120

# Preferred EDNS buffer size for IPv4.
# ipv4-edns-size: 4096

# Preferred EDNS buffer size for IPv6.
# ipv6-edns-size: 4096

# File to store pid for nsd in.
pidfile: "/var/run/nsd.pid"

# port to answer queries on. default is 53.
# port: 53

# statistics are produced every number of seconds.
# statistics: 3600

# Run NSD in a chroot-jail.
# make sure to have pidfile and database reachable from there.
# by default, no chroot-jail is used.
# chroot: "/usr/local/etc/nsd"

# After binding socket, drop user privileges.
# can be a username, id or id.gid.
username: bind

# The directory for zonefile: files.
# zonesdir: "/usr/local/etc/nsd"

# The file where incoming zone transfers are stored.
# run nsd-patch to update zone files, then you can safely delete it.
difffile: "/var/db/nsd/ixfr.db"

# The file where secondary zone refresh and expire timeouts are kept.
# If you delete this file, all secondary zones are forced to be
# 'refreshing' (as if nsd got a notify).
xfrdfile: "/var/db/nsd/xfrd.state"

# Number of seconds between reloads triggered by xfrd.
# xfrd-reload-timeout: 10

# Verbosity level.
verbosity: 2

zone:
name: "myzone.demo"
zonefile: "myzone.demo.zone"

notify: 192.0.2.2 sec1_key
provide-xfr: 192.0.2.2 sec1_key
notify-retry: 10
key:
name: "sec1_key"
algorithm: hmac-md5
secret: "6KM6qiKfwfEpamEq72HQdA=="

Verify binding and sockets:
netstat -anfinet|grep '.53' && netstat -anfinet6|grep '.53'
tcp4 0 0 *.53 *.* LISTEN
udp4 0 0 *.53 *.*
tcp6 0 0 *.53 *.* LISTEN
udp6 0 0 *.53 *.*

now recompile NSD database and reload it:

nsdc rebuild
nsdc reload

make a query to verify it’s answering:
dig +norec @localhost -t ANY myzone.demo

; <<>> DiG 9.8.1-P1 <<>> +norec @localhost -t ANY myzone.demo
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER< ;; flags: qr aa; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 2

;; QUESTION SECTION:
;myzone.demo. IN ANY

;; ANSWER SECTION:
myzone.demo. 600 IN SOA ns1.myzone.demo. hostmaster.myzone.demo. 2012041403 86400 7200 604800 86400
myzone.demo. 3600 IN NS ns1.myzone.demo.
myzone.demo. 3600 IN NS ns2.myzone.demo.
myzone.demo. 3600 IN A 192.0.2.10
myzone.demo. 3600 IN MX 0 aspmx.l.google.com.
myzone.demo. 3600 IN MX 5 alt1.aspmx.l.google.com.
myzone.demo. 3600 IN MX 5 alt2.aspmx.l.google.com.
myzone.demo. 3600 IN MX 10 aspmx2.googlemail.com.
myzone.demo. 3600 IN MX 10 aspmx3.googlemail.com.

;; ADDITIONAL SECTION:
ns1.myzone.demo. 3600 IN A 192.0.2.1
ns2.myzone.demo. 3600 IN A 192.0.2.2

;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 18 23:15:46 2012
;; MSG SIZE rcvd: 304

That works on master server.

Now on the slave.

Edit nsd.conf and feel free to use the following lines, slightly customized for a master role, being 192.0.2.1 master’s ipv4 address and 192.0.2.2 slave’s ipv4 address.
vi /usr/local/etc/nsd/nsd.conf

#
# nsd.conf -- the NSD(8) configuration file, nsd.conf(5).
#
# Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
#
# See LICENSE for the license.
#

# This is a comment.
# Sample configuration file

# options for the nsd server
server:
# uncomment to specify specific interfaces to bind (default wildcard interface).
# ip-address: 1.2.3.4
# ip-address: [email protected]
# ip-address: 12fe::8ef0

# don't answer VERSION.BIND and VERSION.SERVER CHAOS class queries
hide-version: yes

# enable debug mode, does not fork daemon process into the background.
# debug-mode: no

# listen only on IPv4 connections
# ip4-only: no

# listen only on IPv6 connections
# ip6-only: no

# the database to use
database: "/var/db/nsd/nsd.db"

# identify the server (CH TXT ID.SERVER entry).
# identity: "unidentified server"

# NSID identity (hex string). default disabled.
# nsid: "aabbccdd"

# log messages to file. Default to stderr and syslog (with facility LOG_DAEMON).
logfile: "/var/log/nsd.log"

# Number of NSD servers to fork.
server-count: 1

# Maximum number of concurrent TCP connections per server.
# This option should have a value below 1000.
tcp-count: 10

# Maximum number of queries served on a single TCP connection.
# By default 0, which means no maximum.
# tcp-query-count: 0

# Override the default (120 seconds) TCP timeout.
# tcp-timeout: 120

# Preferred EDNS buffer size for IPv4.
# ipv4-edns-size: 4096

# Preferred EDNS buffer size for IPv6.
# ipv6-edns-size: 4096

# File to store pid for nsd in.
pidfile: "/var/run/nsd/nsd.pid"

# port to answer queries on. default is 53.
# port: 53

# statistics are produced every [prado.it] number of seconds.
# statistics: 3600

# Run NSD in a chroot-jail.
# make sure to have pidfile and database reachable from there.
# by default, no chroot-jail is used.
# chroot: "/usr/local/etc/nsd"

# After binding socket, drop user privileges.
# can be a username, id or id.gid.
username: bind

# The directory for zonefile: files.
# zonesdir: "/usr/local/etc/nsd"

# The file where incoming zone transfers are stored.
# run nsd-patch to update zone files, then you can safely delete it.
difffile: "/var/db/nsd/ixfr.db"

# The file where secondary zone refresh and expire timeouts are kept.
# If you delete this file, all secondary zones [prado.it] are forced to be
# 'refreshing' (as if nsd got a notify).
xfrdfile: "/var/db/nsd/xfrd.state"

# Number of seconds between reloads triggered by xfrd.
# xfrd-reload-timeout: 10

# Verbosity level.
verbosity: 2

zone:
name: "myzone.demo"
zonefile: "myzone.demo.zone"
allow-notify: 192.0.2.1 sec1_key
request-xfr: AXFR 192.0.2.1 sec1_key
key:
name: "sec1_key"
algorithm: hmac-md5
secret: "6KM6qiKfwfEpamEq72HQdA=="

Verify binding and sockets:
netstat -anfinet|grep '.53' &amp;&amp; netstat -anfinet6|grep '.53'
tcp4 0 0 *.53 *.* LISTEN
udp4 0 0 *.53 *.*
tcp6 0 0 *.53 *.* LISTEN
udp6 0 0 *.53 *.*

now recompile NSD database and reload it:

nsdc rebuild
nsdc reload

make a query to verify it’s answering:
dig +norec @localhost -t ANY myzone.demo

; <<>> DiG 9.8.1-P1 <<>> +norec @localhost -t ANY myzone.demo
; (2 servers found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER< ;; flags: qr aa; QUERY: 1, ANSWER: 9, AUTHORITY: 0, ADDITIONAL: 2

;; QUESTION SECTION:
;myzone.demo. IN ANY

;; ANSWER SECTION:
myzone.demo. 600 IN SOA ns1.myzone.demo. hostmaster.myzone.demo. 2012041403 86400 7200 604800 86400
myzone.demo. 3600 IN NS ns1.myzone.demo.
myzone.demo. 3600 IN NS ns2.myzone.demo.
myzone.demo. 3600 IN A 192.0.2.10
myzone.demo. 3600 IN MX 0 aspmx.l.google.com.
myzone.demo. 3600 IN MX 5 alt1.aspmx.l.google.com.
myzone.demo. 3600 IN MX 5 alt2.aspmx.l.google.com.
myzone.demo. 3600 IN MX 10 aspmx2.googlemail.com.
myzone.demo. 3600 IN MX 10 aspmx3.googlemail.com.

;; ADDITIONAL SECTION:
ns1.myzone.demo. 3600 IN A 192.0.2.1
ns2.myzone.demo. 3600 IN A 192.0.2.2

;; Query time: 4 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 18 23:18:02 2012
;; MSG SIZE rcvd: 304

Now you have a working scenario with both master and slave instances of NSD on Freebsd 9.0.

Anyway, you’re encouraged to read the manual:
man 5 nsd.conf

Creative Commons License
How to run master and slave NSD on FreeBSD 9.0 by Antonio Prado is licensed under a Creative Commons Attribution-ShareAlike 4.0 International

Leave a Reply