How to run master NSD on FreeBSD 10.0

Prime knots chart
[Some of you asked for an updated version of the NSD how to. Here it is, enjoy.]

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 (version 4.0.3) in a chrooted environment for a master instance deployed on a FreeBSD 10.0 box.

For both master and slave setup refer to my previous article “How to run master and slave NSD on FreeBSD 9.0”.

Let’s start installing:

cd /usr/ports/dns/nsd
make install clean
cp /usr/local/etc/nsd/nsd.conf.sample /usr/local/etc/nsd/nsd.conf
cd /usr/ports/converters/base64
make install clean

Prepare the tree for our chrooted environment:


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

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

Enter the right directory:


cd /usr/local/etc/nsd

Generate a TSIG key to use for zone transfers:


dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
1+0 records in
1+0 records out
32 bytes transferred in 0.000035 secs (913046 bytes/sec)
gsJQqhLnBfV/Qqdc/BqUC1p+yNg28ev2R2oxLbxg+wo=

Run
nsd-control-setup
in order to generate all the certificates NSD needs to allow a remote control via nsd-control.

Here is the output of the above command:


setup in directory /usr/local/etc/nsd
generating nsd_server.key
Generating RSA private key, 1536 bit long modulus
....++++
.++++
e is 65537 (0x10001)
generating nsd_control.key
Generating RSA private key, 1536 bit long modulus
.................++++
..............................................................++++
e is 65537 (0x10001)
create nsd_server.pem (self signed certificate)
create nsd_control.pem (signed client certificate)
Signature ok
subject=/CN=nsd-control
Getting CA Private Key
Setup success. Certificates created. Enable in nsd.conf file to use

Now edit nsd.conf to best suit your needs or 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
# include: "file" # include that file's text over here.

# options for the nsd server
server:
  # Number of NSD servers to fork.  Put the number of CPUs to use here.
  # server-count: 1

  # uncomment to specify specific interfaces to bind (default are the
  # wildcard interfaces 0.0.0.0 and ::0).
  # ip-address: 1.2.3.4
  # ip-address: [email protected]
  # ip-address: 12fe::8ef0

  # Allow binding to non local addresses. Default no.
  # ip-transparent: no

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

  # listen on IPv4 connections
  # do-ip4: yes

  # listen on IPv6 connections
  # do-ip6: yes

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

  # Verbosity level.
  verbosity: 2

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

  # 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"

  # The directory for zonefile: files.  The daemon chdirs here.
  zonesdir: "/usr/local/etc/nsd"
  
  # the list of dynamically added zones.
  zonelistfile: "var/db/nsd/zone.list"

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

  # log messages to file. Default to stderr and syslog (with
  # facility LOG_DAEMON).  stderr disappears when daemon goes to bg.
  logfile: "/usr/local/etc/nsd/var/log/nsd.log"

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

  # 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"

  # The directory where zone transfers are stored, in a subdir of it.
  xfrdir: "tmp"

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

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

  # NSID identity (hex string, or "ascii_somestring"). default disabled.
  nsid: "ascii_ns1.myzone.demo"

  # Maximum number of concurrent TCP connections per server.
  # tcp-count: 100

  # 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

  # statistics are produced every number of seconds. Prints to log.
  # statistics: 3600

  # Number of seconds between reloads triggered by [prado.it] xfrd.
  # xfrd-reload-timeout: 1

  # check mtime of all zone files on start and sighup
  # zonefiles-check: yes

  # RRLconfig
  # Response Rate Limiting, size of the hashtable. Default 1000000.
  # rrl-size: 1000000

  # Response Rate Limiting, maximum QPS allowed (from one query source).
  # Default 200. If set to 0, ratelimiting is disabled. Also set
  # rrl-whitelist-ratelimit to 0 to disable ratelimit processing.
  # rrl-ratelimit: 200

  # Response Rate Limiting, number of packets to discard before
  # sending a SLIP response (a truncated one, allowing an honest
  # resolver to retry with TCP). Default is 2 (one half of the
  # queries will receive a SLIP response, 0 disables SLIP (all
  # packets are discarded), 1 means every request will get a
  # SLIP response.
  # rrl-slip: 2

  # Response Rate Limiting, IPv4 prefix length. Addresses are
  # grouped by netblock. 
  # rrl-ipv4-prefix-length: 24

  # Response Rate Limiting, IPv6 prefix length. Addresses are
  # grouped by netblock. 
  # rrl-ipv6-prefix-length: 64

  # Response Rate Limiting, maximum QPS allowed (from one query source)
  # for whitelisted types. Default 2000.
  # rrl-whitelist-ratelimit: 2000
  # RRLend

# Remote control config section. 
remote-control:
  # Enable remote control with nsd-control(8) here.
  # set up the keys and certificates with nsd-control-setup.
  control-enable: yes

  # what interfaces are listened to for control, default is on localhost.
  # control-interface: 127.0.0.1
  # control-interface: ::1

  # port number for remote control operations (uses TLS over TCP).
  # control-port: 8952

  # nsd server key file for remote control.
  server-key-file: "/usr/local/etc/nsd/nsd_server.key"

  # nsd server certificate file for remote control.
  server-cert-file: "/usr/local/etc/nsd/nsd_server.pem"

  # nsd-control key file.
  control-key-file: "/usr/local/etc/nsd/nsd_control.key"

  # nsd-control certificate file.
  control-cert-file: "/usr/local/etc/nsd/nsd_control.pem"

# Secret keys for TSIGs that secure [prado.it] zone transfers.
# You could include: "secret.keys" and put the 'key:' statements in there,
# and give that file special access control permissions.
#
key:
  # The key name is sent to the other party, it must be the same
  name: "sec1_key"
  # algorithm hmac-md5, or hmac-sha1, or hmac-sha256 (if compiled in)
  # algorithm: hmac-sha256
  algorithm: hmac-md5
  # secret material, must be the same as the other party uses.
  # base64 encoded random number.
  # e.g. from dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
  #secret: "K2tf3TRjvQkVCmJF3/Z9vA=="
  secret: "gsJQqhLnBfV/Qqdc/BqUC1p+yNg28ev2R2oxLbxg+wo="

# Patterns have zone configuration and they are shared by one or more zones.
# 
# pattern:
  # name by which the pattern is referred to
  #name: "myzones"
  # the zonefile for the zones that use this pattern.
  # if relative then from the zonesdir (inside the chroot).
  # the name is processed: %s - zone name (as appears in zone:name).
  # %1 - first character of zone name, %2 second, %3 third.
  # %z - topleveldomain label of zone, %y, %x next labels in name.
  # if label or character does not exist you get a dot '.'.
  # for example "%s.zone" or "zones/%1/%2/%3/%s" or "secondary/%z/%s"
  #zonefile: "%s.zone"
  
  # If no master and slave access control elements are provided,
  # this zone will not be served to/from other servers.

  # A master zone needs notify: and provide-xfr: lists.  A slave
  # may also allow zone transfer (for debug or other secondaries).
  # notify these slaves when the master zone changes, address TSIG|NOKEY
  # IP can be ipv4 and ipv6, with @port for a nondefault port number.
  #notify: 192.0.2.1 NOKEY
  # allow these IPs and TSIG to transfer zones, addr TSIG|NOKEY|BLOCKED
  # address range 192.0.2.0/24, 1.2.3.4&255.255.0.0, 3.0.2.20-3.0.2.40
  #provide-xfr: 192.0.2.0/24 my_tsig_key_name
  # set the number of retries for notify.
  #notify-retry: 5

  # uncomment to provide AXFR to all the world
  # provide-xfr: 0.0.0.0/0 NOKEY
  # provide-xfr: ::0/0 NOKEY

  # A slave zone needs allow-notify: and request-xfr: lists.
  #allow-notify: 2001:db8::0/64 my_tsig_key_name
  # By default, a slave will request a zone transfer with IXFR/TCP.
  # If you want to make use of IXFR/UDP use: UDP addr tsigkey
  # for a master that only speaks AXFR (like NSD) use AXFR addr tsigkey
  #request-xfr: 192.0.2.2 the_tsig_key_name
  # Attention: You cannot use UDP and AXFR together. AXFR is always over 
  # TCP. If you use UDP, we higly recommend you to deploy TSIG.
  # Allow AXFR fallback if the master does not support IXFR. Default
  # is yes.
  #allow-axfr-fallback: yes
  # set local interface for sending zone transfer requests.
  # default is let the OS choose.
  #outgoing-interface: 10.0.0.10

  # if you give another pattern name here, at this point the settings
  # from that pattern are inserted into this one (as if it were a 
  # macro).  The statement can be given in between other statements,
  # because the order of access control elements can make a difference
  # (which master to request from first, which slave to notify first).
  #include-pattern: "common-masters"

# Fixed zone entries.  Here you can config zones that cannot be deleted.
# Zones that are dynamically added and deleted are put in the zonelist file.
#
# zone:
   # name: "example.com"
   # you can give a pattern here, all the settings from that pattern
   # are then inserted at this point
   # include-pattern: "master"
   # You can also specify (additional) options directly for this zone.
   # zonefile: "example.com.zone"
   # request-xfr: 192.0.2.1 example.com.key
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

  # RRLconfig
  # Response Rate Limiting, whitelist types
  # rrl-whitelist: nxdomain
  # rrl-whitelist: error
  # rrl-whitelist: referral
  # rrl-whitelist: any
  # rrl-whitelist: rrsig
  # rrl-whitelist: wildcard
  # rrl-whitelist: nodata
  # rrl-whitelist: dnskey
  # rrl-whitelist: positive
  # rrl-whitelist: all
  # RRLend

Put your zones in /usr/local/etc/nsd.

vi myzone.demo.zone


$TTL 86400
$ORIGIN myzone.demo.
@  1D  IN  SOA  ns1.myzone.demo. hostmaster.myzone.demo. (
      2014082000
      1D
      2H
      7D
      1D)
@  IN  NS  ns1.myzone.demo.
@  IN  NS  ns2.myzone.demo.
@  IN  A  192.0.2.10

Adjust permissions:


chown -R bind:bind /usr/local/etc/nsd

Start NSD:


/usr/local/etc/rc.d/nsd start

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 reload NSD:


nsd-control reload

make a query to verify it’s answering:


drill @localhost ANY myzone.demo
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 54928
;; flags: qr aa rd ; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; myzone.demo.  IN  ANY

;; ANSWER SECTION:
myzone.demo.  86400  IN  SOA  ns1.myzone.demo. hostmaster.myzone.demo. 2014082000 86400 7200 604800 86400
myzone.demo.  86400  IN  NS  ns1.myzone.demo.
myzone.demo.  86400  IN  NS  ns2.myzone.demo.
myzone.demo.  86400  IN  A  192.0.2.10

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Wed Aug 20 17:54:22 2014
;; MSG SIZE  rcvd: 128

(I know: glue records missing; but that’s just an example, isn’t it? Always remember glue records in your production environment).

Now you have a working scenario with a master instance of NSD 4.0.3 on FreeBSD 10.0.

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

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

Leave a Reply