Unbound Caching and NSD Local Authoritative Master Slave DNS Server – Part II

nlnetlabs logo

NSD – Authoritative DNS Server:

In Part I of our tutorial, Unbound is used as a caching DNS Server for clients on our LAN.  If any local DNS resolution is needed, Unbound is configured via it’s stub-zone to parse the query to an authoritative DNS Server, and in this case, it is NSD.

Below is our operating environment.  As you can see, we have two servers both running Unbound as a DNS Caching Server, and Server 1 running NSD as a Master DNS Server and Server 2 running NSD as a Slave DNS Server.

 

Operating Environment:

Server 1:

Hostname: bsd220.loga.us

IP Address: 192.168.0.220/24

Unbound Caching DNS Server: 192.168.0.220@53

Master NSD DNS Server: 192.168.0.220@5053

 

Server 2:

Hostname: bsd222.loga.us

IP Address: 192.168.0.222/24

Unbound Caching DNS Server: 192.168.0.222@53

Slave NSD DNS Server: 192.168.0.222@5053

 

Before starting some important notes:

  • NSD by default is not installed in a chroot environment.  In this tutorial, a chroot environment will be utilized.
  • NSD purpose in this example is to serve DNS resolution within our LAN the domain loga.us.
  • Unbound thru the use of stub-zones, will pass the queries for the domain loga.us to NSD for resolution.
  • The proper and accurate server time is imperative in a Master/Slave NSD environment.  Ensure your server’s clock is synchronized to an ntpd server or else you may encounter errors in your log files.

 

NSD:

Let’s start by installing NSD on each server:

# portsnap fetch update
# cd /usr/ports/dns/nsd
# make install clean
# cd /usr/ports/converters/base64
# make install clean

 

nsd.conf:

Next, create an nsd.conf from the sample file on each server:

# cd /usr/local/etc/nsd
# cp nsd.conf.sample nsd.conf

 

Create the necessary directory structure for the chroot environment on each server:

# cd /usr/local/etc/nsd
# mkdir log db zonefile tmp
# chown bind:wheel log db zonefile tmp
# chmod 755 log db zonefile tmp

 

rc.conf:

Next, let’s setup NSD to startup automatically by adding the following line in our /etc/rc.conf on each server:

nsd_enable="YES"

 

Generate TSIG Key for Zone Transfers:

To secure and encrypt zone transfers perform the following key generation on the Master NSD Server:

# dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
1+0 records in
1+0 records out
32 bytes transfered in 0.000025 secs (1278264 bytes/sec)
/hhsH59zLiXlRD/PjQ7x3INl1gPu7foejS7yEpUiHik=

Save this key for later.

 

nsd-control:

Next step is to generate the keys needed for NSD to be controlled by nsd-control (8) on each server. 

# cd /usr/local/etc/nsd
# nsd-control-setup

 

Zone Files:

Create zone files (forward and reverse) on each server:

The forward zone file /usr/local/etc/nsd/zonefile/loga.us.forward is listed below:

$ORIGIN loga.us. ; default zone domain
$TTL 86400       ; default time to live

@ IN SOA ns1.loga.us. admin.loga.us. (
                 2014010203 ; serial number
                 28800      ; Refresh
                 7200       ; Retry
                 864000     ; Expire
                 86400      ; Min TTL
                   )

IN NS ns1.loga.us.
IN NS ns2.loga.us.

@               IN A 192.168.0.220
ns1             IN A 192.168.0.220 
ns2             IN A 192.168.0.220
www             IN A 192.168.0.220
ldap1           IN A 192.168.0.220
ldap2           IN A 192.168.0.222

 

The reverse zone file /usr/local/etc/nsd/zonefile/loga.us.reverse is listed below:

$ORIGIN loga.us. ; default zone domain
$TTL 86400       ; default time to live

0.168.192.in-addr.arpa. IN SOA ns1.loga.us. admin.loga.us. (
                            2014010203 ; serial number
                            28800      ; Refresh
                            7200       ; Retry
                            864000     ; Expire
                            86400      ; Min TTL
                             )
; Name Servers

                            IN NS  ns1
                            IN NS  ns2

220.0.168.192.in-addr.arpa. IN PTR @
220.0.168.192.in-addr.arpa. IN PTR ns1
222.0.168.192.in-addr.arpa. IN PTR ns2
220.0.168.192.in-addr.arpa. IN PTR www
220.0.168.192.in-addr.arpa. IN PTR ldap1
222.0.168.192.in-addr.arpa. IN PTR ldap2

 

Before starting NSD make sure the /usr/local/etc/nsd.conf file is modified to your environment.

 

nsd.conf:

Here’s the complete /usr/local/etc/nsd/nsd.conf file for Server 1:

Note:  Please refer to the uncommented statements and adjust to your environment.

 

#
# 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: 1.2.3.4@5678
# ip-address: 12fe::8ef0
  ip-address: 127.0.0.1
  ip-address: 192.168.0.220

# 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: 5053

# 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/zonefile"
 
# the list of dynamically added zones.
  zonelistfile: "/usr/local/etc/nsd/db/zone.list"

# the database to use
  database: "/usr/local/etc/nsd/db/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/log/nsd.log"

# File to store pid for nsd in.
  pidfile: "/usr/local/etc/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: "/usr/local/etc/nsd/db/xfrd.state"

# The directory where zone transfers are stored, in a subdir of it.
  xfrdir: "/usr/local/etc/nsd/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: "aabbccdd"

# 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 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 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: "secure_key"
# algorithm hmac-md5, or hmac-sha1, or hmac-sha256 (if compiled in)
algorithm: hmac-sha256
# 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: "/hhsH59zLiXlRD/PjQ7x3INl1gPu7foejS7yEpUihik="                              


# 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

# 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

  zone:
   name: "loga.us"
   zonefile: loga.us.forward
   notify: 192.168.0.222@5053 secure_key
   provide-xfr: 192.168.0.222 secure_key

  zone:
   name: "0.168.192.in-addr.arpa"
   zonefile: loga.us.reverse
   notify: 192.168.0.222@5053 secure_key
   provide-xfr: 192.168.0.222 secure_key

 

 

Here’s the complete /usr/local/etc/nsd/nsd.conf file for Server 2:

#
# 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: 1.2.3.4@5678
# ip-address: 12fe::8ef0
  ip-address: 127.0.0.1
  ip-address: 192.168.0.222 

# 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: 5053

# 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/zonefile"
 
# the list of dynamically added zones.
  zonelistfile: "/usr/local/etc/nsd/db/zone.list"

# the database to use
  database: "/usr/local/etc/nsd/db/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/log/nsd.log"

# File to store pid for nsd in.
  pidfile: "/usr/local/etc/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: "/usr/local/etc/nsd/db/xfrd.state"

# The directory where zone transfers are stored, in a subdir of it.
  xfrdir: "/usr/local/etc/nsd/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: "aabbccdd"

# 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 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 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: "secure_key"
# algorithm hmac-md5, or hmac-sha1, or hmac-sha256 (if compiled in)
algorithm: hmac-sha256
# 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: "/hhsH59zLiXlRD/PjQ7x3INl1gPu7foejS7yEpUihik="


# 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

# 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

  zone:
   name: "loga.us"
   zonefile: loga.us.forward
   allow-notify: 192.168.0.220 secure_key
   allow-notify: 127.0.0.1 NOKEY
   request-xfr: AXFR 192.168.0.220@5053 secure_key
 
  zone:
   name: "0.168.192.in-addr.arpa"
   zonefile: loga.us.reverse
   allow-notify: 192.168.0.220 secure_key
   allow-notify: 127.0.0.1 NOKEY
   request-xfr: AXFR 192.168.0.220@5053 secure_key

 

Log Rotation:

Since NSD will generate a substantial amount of log entries depending on the verbosity level, managing log rotation is imperative.  The below actions are needed on both servers if you are maintaining log files.

 

When NSD first creates the log file, the file permissions are as follows:

-rw-r--r--  1 bind  wheel    11086 Aug  2 16:15 nsd.log

 

Therefore, an entry in the /etc/newsyslog.conf file is necessary on each server:

/usr/local/etc/nsd/log/nsd.log  bind:wheel     640  7     *    @T12  R   /usr/local/etc/nsd/log_reopen

 

The content of the /usr/local/etc/nsd/log_reopen script is as follows:

# !/bin/sh

# This script restarts NSD after log rotation by newsyslog(8)

/usr/local/sbin/nsd-control log_reopen

exit 0

 

The permissions of /usr/local/etc/nsd/log_reopen are:

-rwxr--r--  1 bind  wheel      135 Aug  2 09:28 log_reopen*

The file permissions on the log file and script are important in order for newsyslog to properly utilize the R flag and execute the script

 

Restart the newsyslog and NSD daemons:

# service newsyslog restart
# service nsd restart

 

nsd-control write:

Cron Job for nsd-control write:

As you update your zone files with new DNS records and increment the serial number of the domain, NSD will update the Slave NSD Server when the zone files are reloaded using either nsd-control reload or if the nsd service is restarted from the Master NSD Server.  As the NSD database is updated with the changed zone information, the actual zone files, in our case, loga.us.forward and loga.us.reverse are not updated on the Slave NSD Server.  However, NSD provides a utility nsd-control write perform this task.  It is suggested to use a cron job once a day to update the text zone files on the slave.

 

Below is the cron entry on FreeBSD 10 using the crontab -e argument on slave server:

# crontab for nsd-control write

# Executes the zone_write script every day at 0800

00     08     *     *     *     /usr/local/etc/nsd/zone_write

#

 

Here is the content of the file /usr/local/etc/nsd/zone_write:

#!/bin/sh

#This script writes the zone files to the NSD Slave Server

#

/usr/local/sbin/nsd-control write

#

exit 0

 

Below is the file permissions for /usr/local/etc/nsd/zone_write:

-rwxr--r--  1 bind  wheel   118 Aug  5 19:38 zone_write*

 

Summary:

In this article, nsd as an authoritative DNS Server was configured for internal LAN DNS resolution.  In Part I and II of this series, unbound together with nsd is an effective combination as a replacement for Bind.  In the future, the inclusion of statistics and threads will provide an interesting challenge.  Until then, please let me know if you discover any typos or mistakes.

 

Additional References:

www.nlnetlabs.nl

calomel.org

http://www.prado.it/2014/08/20/how-to-run-master-and-slave-nsd-on-freebsd-10-0/

http://www.tokiwinter.com/nsd-master-slave-dns-servers

10 thoughts on “Unbound Caching and NSD Local Authoritative Master Slave DNS Server – Part II”

  1. Hi,
    I have set my two vm instances of freebsd and followed your instructions but i could never get my reverse dns to work. When i do a “dig 192.168.1.150” , my soa reply is always one of the root server. I have a pfsense which has unbound on it AFAIK, but i have resolvconf.conf file that overrides it to the localhost lookup.
    Hoping you can point me in the right direction.
    Thanks.

    1. Ralph,

      Can you provide the output of “drill 192.168.1.150” and “host 192.168.1.150”?

      Regards,

      Scott

      1. ;; ->>HEADER<<- opcode: QUERY, rcode: NXDOMAIN, id: 45005
        ;; flags: qr rd ra ; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0
        ;; QUESTION SECTION:
        ;; 192.168.1.150. IN A

        ;; ANSWER SECTION:

        ;; AUTHORITY SECTION:
        . 3600 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2017062003 1800 900 604800 86400

        ;; ADDITIONAL SECTION:

        ;; Query time: 1629 msec
        ;; SERVER: 127.0.0.1
        ;; WHEN: Tue Jun 20 22:50:04 2017
        ;; MSG SIZE rcvd: 106

        this is the host 192.168.1.150

        ;; connection timed out; no servers could be reached

        1. Ralph,

          Does your setup resolve any local or internal domains? Can you contact me via my email address cres24 at mac.com…

          Regards,

          Scott

          1. Was the above ever resolved? I know it’s almost 3 years ago, but I have the same thing.
            Except that my “host 10.42.42.1” will resolve my internal server, where drill shows a root hint server.

            In my case it’s perhaps because the domain I use on my LAN is the same as my internet domain?
            Perhaps I should change that to domain.local instead of domain.nl. (domain is not the actual name).

            I have set up Part 1 on one server, need to do it on the second.
            NSD is the next step, but had to add it to my Poudriere server first.

          2. Tom,

            I don’t recall, but take a careful look at your config files and also examine the log files for clues. If you needed you can contact me directly.

            Regards,

            Scott

  2. Today I noticed that a nsd-control write or nsd service restart will not update the zone files.
    Primary only notifies the secondary of any updates which updates it’s database accordingly.

    Looking at other sites that explain a primary/secondary NSD setup, they don’t mention creating those files on both servers.
    You do, and I wonder if that is a mistake?

    This does make me wonder what I can do in case of losing Primary. Can I extract the contents of the database to create new forward and reverse zone files?

    1. Tom,

      Thanks for the input. I believe you maybe correct in that you don’t have to create the exact zonefiles on the slave as were created on the Master. However, it’s been a long time since I wrote this post. I seem to recall the files names and permissions had to be created via the touch cmd before the Master could transfer the updates to the Slave. The contents of the file are transferred upon restarting the nsd service or as you mentioned using the nsd-control write utility. Also, remember to change or increment the serial number of the zone files on the Master Server or it will not update the Slave!

      1. Touch would make sense if those file are actually written, I’d say. But perhaps something funky is being done. I could try it out some day.

        Changing the serial number is important, yes. I think I forgot that once 🙂
        I only use it at home so I don’t edit the zone files daily.

        I’ve been running it now since mid April now and it works really well.
        I’ve included dns/void-zones-tools to Unbound as well, so I that’s less GNU/Linux for running Pi-hole 🙂

        1. Tom,

          As you, I use it for my home network. After reviewing my zone files, I decided to do a little house cleaning on my ‘A’ Records on the Master Server in order to test the transfer of zone file changes from the Master to the Slave Server. Completing the changes and incrementing the serial number for each zone file, I reloaded the nsd Master and Slave Servers and tested to ensure the hostname lookups were working correctly on the Master and Slave Servers. Reviewing the zone files on the Slave Server, I recalled one must execute the nsd-control write command on the Slave Server to update the nsd database and write the changes to the zone files. If you look towards the end of the post, there are procedures needed to execute the nsd-control write command from the Slave via a script by cron…. It definitely works as the zone file changes on the Slave are written out to their respective zone files. Make sure your zone files have the correct permissions and ownership 644 bind:wheel. NSD uses as the default “bind” as the ownership – at least in FreeBSD!

          If you have any questions, you can email me directly at cres24 at me.com. – Scott

Leave a Reply

Your email address will not be published. Required fields are marked *