How to configure master and slave Knot on Ubuntu 11.10

Prime knots chartKnot is an authoritative-only nameserver developed by CZ.NIC Labs. On their website you can read that it supports all key features of the domain name system including zone transfers, dynamic updates and DNSSEC.
If you need a recursive and caching resolver please consider using Unbound and reading my article “How to configure Unbound on Ubuntu 11.10“.

I’m going to show you how to install and configure knot as master and as slave server.

The initial procedure is the same for master and for slave.

[Jan Piet Mens @digdns suggests:
Tired of issuing sudo?
By the command sudo -i you open a bash shell as root so…]

Start grabbing the package from cz.nic-labs:

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:cz.nic-labs/knot-dns

Prepare the location to store db:
sudo mkdir /var/lib/knot

then use a fully commented configuration file:
sudo cp /usr/share/doc/knot/examples/knot.sample.conf /etc/knot/knot.conf

and start editing it:
sudo vi /etc/knot/knot.conf

Now, on master server.
Feel free to use the following configuration file slightly edited for a master role:

#
# knot.sample.conf
#
# This is a sample configuration file for Knot DNS server.
#

# This is a comment.

#
# There are 4 main sections of this config file:
# system, zones, interfaces and log
#

# Section 'system' contains general options for the server
system {

# Identity of the server (see RFC 4892). Not used yet.
#identity "I have no mouth and must scream";

# Version of the server (see RFC 4892). Not used yet.
#version "0.1";

# Server identifier
# Use string format "text"
# Or hexstring 0x01ab00
#nsid "myserver0";

# Working directory of the server
# Used to store compiled zones and PID file
storage "/var/lib/knot";

# Custom pidfile path
# default: pidfile is created in 'storage'.
pidfile "/var/run/knot.pid";

# Number of workers per interface
# This option is used to force number of threads used per interface
# Default: unset (auto-estimates optimal value from the number of online CPUs)
workers 1;

# User for running server
# May also specify user.group (f.e. knot.users)
user root;
}

# Section 'keys' contains list of TSIG keys
keys {

# TSIG key
#
# format: name key-type "";
# where key-type may be one of the following:
# hmac-md5
# hmac-sha1
# hmac-sha224
# hmac-sha256
# hmac-sha384
# hmac-sha512
# and is the private key
key1.slave1 hmac-md5 "Wg==";

# TSIG key for zone
key0.example.com hmac-md5 "==gW";
}

# Section 'interfaces' contains definitions of listening interfaces.
interfaces {

# Interface entry
#
# Format 1: { address

<address>; [port ;] }
ipv4 { # is an arbitrary symbolic name
address 0.0.0.0; #</address><address>may be ither IPv4 or IPv6 address
port 53; # port is required for XFR/IN and NOTIFY/OUT
}</address># Format 2: { address

<address>@; }
# shortipv4 {
# address [email protected];
#}</address># Format 1 (IPv6 interface)
# ipv6 {
# address ::[email protected];
# }

# Format 2 (IPv6 interface)
# ipv6b {
# address [::1]@53534;
# }

}

# Section 'remotes' contains symbolic names for remote servers.
# Syntax for 'remotes' is the same as for 'interfaces'.
remotes {

# Remote entry
#
# Format 1: { address

<address>; [port ;] }
slave1 { # is an arbitrary symbolic name
address 192.0.2.2; #</address><address>may be ither IPv4 or IPv6 address
port 53; # port is optional (default: 53)
key key1.slave1; # (optional) specification of TSIG key associated for this remote
# via ipv4; # (optional) source interface for queries
# via 82.35.64.59; # (optional) source interface for queries, direct IPv4
# via [::cafe]; # (optional) source interface for queries, direct IPv6
}</address># Format 2: { address

<address>@; }
local {
address [email protected];
}
}</address># Section 'zones' contains information about zones to be served.
zones {

# Shared options for all listed zones
#

# Enable semantic checks for all zones (if 'on')
# Possible values: on|off
# Default value: off
semantic-checks off;

# NOTIFY response timeout
# Possible values: (seconds)
# Default value: 60
notify-timeout 60;

# Number of retries for NOTIFY
# Possible values:
# Default value: 5
notify-retries 5;

# Timeout for syncing changes from zone database to zonefile
# Possible values: (seconds)
# Default value: 1h (1 hour)
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;

# File size limit for IXFR journal
# Possible values:
# Default value: N/A (infinite)
# It is also possible to suffix with unit size [k/M/G]
# f.e. 1k, 100M, 2G
ixfr-fslimit 1G;

# Zone entry
#
# Format: { file ""; }
myzone.demo { # is the DNS name of the zone (zone root)
# may be either absolute or relative, in which case
# it is considered relative to the current directory from which the server
# was started.
file "/etc/knot/myzone.demo.zone";

# Enable zone semantic checks
# Possible values: on|off
# Default value: off
semantic-checks on;

# NOTIFY response timeout (specific for current zone)
# Possible values: (seconds)
# Default value: 60
notify-timeout 60;

# Number of retries for NOTIFY (specific for current zone)
# Possible values:
# Default value: 5
notify-retries 5;

# Timeout for syncing changes from zone database to zonefile
# Possible values: (seconds)
# Default value: inherited from zones.zonefile-sync
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;

# XFR master server
#xfr-in slave1;

# ACL list of XFR slaves
xfr-out local, slave1;

# ACL list of servers allowed to send NOTIFY queries
#notify-in slave1;

# List of servers to send NOTIFY to
notify-out local, slave1;
}
}

# Section 'log' configures logging of server messages.
#
# Logging recognizes 3 symbolic names of log devices:
# stdout - Standard output
# stderr - Standard error output
# syslog - Syslog
#
# In addition, arbitrary number of log files may be specified (see below).
#
# Log messages are characterized by severity and category.
# Supported severities:
# debug - Debug messages. Must be turned on at compile time.
# info - Informational messages.
# notice - Notices and hints.
# warning - Warnings. An action from the operator may be required.
# error - Recoverable error. Some action should be taken.
# fatal - Non-recoverable errors resulting in server shutdown.
# (Not supported yet.)
# all - All severities.
#
# Categories designate the source of the log message and roughly correspond
# to server modules
# Supported categories:
# server - Messages related to general operation of the server.
# zone - Messages related to zones, zone parsing and loading.
# answering - Messages regarding query processing and response creation.
# any - All categories
#
# More severities (separated by commas) may be listed for each category.
# All applicable severities must be listed.
# (I.e. specifying 'error' severity does mean: 'log error messages',
# and NOT 'log all messages of severity error and above'.)
#
# Default settings (in case there are no entries in 'log' section or the section
# is missing at all):
#
# stderr { any error; }
# syslog { any error; }
log {

# Log entry
#
# Format 1:
# {
# [, ...];
# [, ...];
# ...
# }
syslog { # is a symbolic name of a log device (see above)
# log errors of any category
any error; # for and see above
# log also warnings and notices from category 'zone'
zone warning, notice;
# log info from server
server info;
}

# Log fatal, warnings and errors to stderr
stderr {
any error, warning;
}

# Format 2:
# file {
# [, ...];
# [, ...];
# }
file "/tmp/knotd.debug" { # is absolute or relative path to log file
server debug;
}
}

Then restart knot:
sudo knotc restart

and put the zone myzone.demo in /etc/knot/myzone.demo.zone

Here follows the zone:


$ORIGIN myzone.demo.
myzone.demo. 600 IN SOA ns1.myzone.demo. (
hostmaster.myzone.demo.
2012041401
86400
7200
604800
86400
)

@ NS ns1.myzone.demo.
@ NS ns2.myzone.demo.
ns1 A 192.0.2.1
ns2 A 192.0.2.2

@ A 192.0.2.10
www CNAME @
ftp CNAME @
@ MX 0 ASPMX.L.GOOGLE.COM.
@ MX 5 ALT1.ASPMX.L.GOOGLE.COM.
@ MX 5 ALT2.ASPMX.L.GOOGLE.COM.
@ MX 10 ASPMX2.GOOGLEMAIL.COM.
@ MX 10 ASPMX3.GOOGLEMAIL.COM.

then compile and reload knot

sudo knotc compile
sudo knotc reload

In /var/lib/knot you should see two files:
sudo ls /var/lib/knot/
myzone.demo.db
myzone.demo.db.crc

Time to make a quick query:
dig +norec @localhost -t ANY myzone.demo

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

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

;; ANSWER SECTION:
myzone.demo. 3600 IN A 192.0.2.10
myzone.demo. 3600 IN NS ns1.myzone.demo.
myzone.demo. 3600 IN NS ns2.myzone.demo.
myzone.demo. 600 IN SOA ns1.myzone.demo. hostmaster.myzone.demo. 2012041401 86400 7200 604800 86400
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.

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 18 11:58:16 2012
;; MSG SIZE rcvd: 347

Now on your slave server you can use the following configuration file slightly edited for a slave role:

#
# knot.sample.conf
#
# This is a sample configuration file for Knot DNS server.
#

# This is a comment.

#
# There are 4 main sections of this config file:
# system, zones, interfaces and log
#

# Section 'system' contains general options for the server
system {

# Identity of the server (see RFC 4892). Not used yet.
#identity "I have no mouth and must scream";

# Version of the server (see RFC 4892). Not used yet.
#version "0.1";

# Server identifier
# Use string format "text"
# Or hexstring 0x01ab00
#nsid "myserver0";

# Working directory of the server
# Used to store compiled zones and PID file
storage "/var/lib/knot";

# Custom pidfile path
# default: pidfile is created in 'storage'.
pidfile "/var/run/knot.pid";

# Number of workers per interface
# This option is used to force number of threads used per interface
# Default: unset (auto-estimates optimal value from the number of online CPUs)
workers 1;

# User for running server
# May also specify user.group (f.e. knot.users)
user root;
}

# Section 'keys' contains list of TSIG keys
keys {

# TSIG key
#
# format: name key-type "";
# where key-type may be one of the following:
# hmac-md5
# hmac-sha1
# hmac-sha224
# hmac-sha256
# hmac-sha384
# hmac-sha512
# and is the private key
key1.slave1 hmac-md5 "Wg==";

# TSIG key for zone
key0.example.com hmac-md5 "==gW";
}

# Section 'interfaces' contains definitions of listening interfaces.
interfaces {

# Interface entry
#
# Format 1: { address

<address>; [port ;] }
ipv4 { # is an arbitrary symbolic name
address 0.0.0.0; #</address><address>may be ither IPv4 or IPv6 address
port 53; # port is required for XFR/IN and NOTIFY/OUT
}</address># Format 2: { address

<address>@; }
# shortipv4 {
# address [email protected];
#}</address># Format 1 (IPv6 interface)
# ipv6 {
# address ::[email protected];
# }

# Format 2 (IPv6 interface)
# ipv6b {
# address [::1]@53534;
# }

}

# Section 'remotes' contains symbolic names for remote servers.
# Syntax for 'remotes' is the same as for 'interfaces'.
remotes {

# Remote entry
#
# Format 1: { address

<address>; [port ;] }
master { # is an arbitrary symbolic name
address 192.0.2.1; #</address><address>may be ither IPv4 or IPv6 address
port 53; # port is optional (default: 53)
key key1.slave1; # (optional) specification of TSIG key associated for this remote
# via ipv4; # (optional) source interface for queries
# via 82.35.64.59; # (optional) source interface for queries, direct IPv4
# via [::cafe]; # (optional) source interface for queries, direct IPv6
}</address># Format 2: { address

<address>@; }
#server1 {
# address [email protected];
#}
}</address># Section 'zones' contains information about zones to be served.
zones {

# Shared options for all listed zones
#

# Enable semantic checks for all zones (if 'on')
# Possible values: on|off
# Default value: off
semantic-checks off;

# NOTIFY response timeout
# Possible values: (seconds)
# Default value: 60
notify-timeout 60;

# Number of retries for NOTIFY
# Possible values:
# Default value: 5
notify-retries 5;

# Timeout for syncing changes from zone database to zonefile
# Possible values: (seconds)
# Default value: 1h (1 hour)
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;

# File size limit for IXFR journal
# Possible values:
# Default value: N/A (infinite)
# It is also possible to suffix with unit size [k/M/G]
# f.e. 1k, 100M, 2G
ixfr-fslimit 1G;

# Zone entry
#
# Format: { file ""; }
myzone.demo { # is the DNS name of the zone (zone root)
# may be either absolute or relative, in which case
# it is considered relative to the current directory from which the server
# was started.
file "/etc/knot/myzone.demo.zone";

# Enable zone semantic checks
# Possible values: on|off
# Default value: off
semantic-checks on;

# NOTIFY response timeout (specific for current zone)
# Possible values: (seconds)
# Default value: 60
notify-timeout 60;

# Number of retries for NOTIFY (specific for current zone)
# Possible values:
# Default value: 5
notify-retries 5;

# Timeout for syncing changes from zone database to zonefile
# Possible values: (seconds)
# Default value: inherited from zones.zonefile-sync
# It is also possible to suffix with unit size [s/m/h/d]
# f.e. 1s = 1 day, 1m = 1 minute, 1h = 1 hour, 1d = 1 day
zonefile-sync 1h;

# XFR master server
xfr-in master;

# ACL list of XFR slaves
#xfr-out slave1;

# ACL list of servers allowed to send NOTIFY queries
notify-in master;

# List of servers to send NOTIFY to
#notify-out slave1;
}
}

# Section 'log' configures logging of server messages.
#
# Logging recognizes 3 symbolic names of log devices:
# stdout - Standard output
# stderr - Standard error output
# syslog - Syslog
#
# In addition, arbitrary number of log files may be specified (see below).
#
# Log messages are characterized by severity and category.
# Supported severities:
# debug - Debug messages. Must be turned on at compile time.
# info - Informational messages.
# notice - Notices and hints.
# warning - Warnings. An action from the operator may be required.
# error - Recoverable error. Some action should be taken.
# fatal - Non-recoverable errors resulting in server shutdown.
# (Not supported yet.)
# all - All severities.
#
# Categories designate the source of the log message and roughly correspond
# to server modules
# Supported categories:
# server - Messages related to general operation of the server.
# zone - Messages related to zones, zone parsing and loading.
# answering - Messages regarding query processing and response creation.
# any - All categories
#
# More severities (separated by commas) may be listed for each category.
# All applicable severities must be listed.
# (I.e. specifying 'error' severity does mean: 'log error messages',
# and NOT 'log all messages of severity error and above'.)
#
# Default settings (in case there are no entries in 'log' section or the section
# is missing at all):
#
# stderr { any error; }
# syslog { any error; }
log {

# Log entry
#
# Format 1:
# {
# [, ...];
# [, ...];
# ...
# }
syslog { # is a symbolic name of a log device (see above)
# log errors of any category
any error; # for and see above
# log also warnings and notices from category 'zone'
zone warning, notice;
# log info from server
server info;
}

# Log fatal, warnings and errors to stderr
stderr {
any error, warning;
}

# Format 2:
# file {
# [, ...];
# [, ...];
# }
file "/tmp/knotd.debug" { # is absolute or relative path to log file
server debug;
}
}

Then restart knot
sudo knotc restart

Now in your log file you should see that the zone transfer has started:
tail /var/log/syslog
slave1 knot[1473]: AXFR transfer of ‘myzone.demo./IN’ with ‘[email protected]’ key ‘key1.slave1’: Started.

look at /var/lib/knot and you should find 3 files
sudo ls /var/lib/knot
myzone.demo.db
myzone.demo.db.crc
myzone.demo.diff.db

Try a query on your slave just to verify that everything is working:
dig +norec @localhost -t ANY myzone.demo

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

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

;; ANSWER SECTION:
myzone.demo. 3600 IN A 192.0.2.10
myzone.demo. 3600 IN NS ns1.myzone.demo.
myzone.demo. 3600 IN NS ns2.myzone.demo.
myzone.demo. 600 IN SOA ns1.myzone.demo. hostmaster.myzone.demo. 2012041401 86400 7200 604800 86400
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.

;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Apr 18 14:07:58 2012
;; MSG SIZE rcvd: 347

Just to verify on your master’s log:
tail /var/log/syslog
master knot[1150]: NOTIFY query of ‘myzone.demo.’ to ‘[email protected]’: Query issued.
master knot[1150]: AXFR transfer of ‘myzone.demo./OUT’ to ‘[email protected]’ key ‘key1.slave1’: Finished.

What you have now is a fully working scenario where knot serves as master and slave nameserver.
This is just a short and quick guide: you are warmly encouraged to read the background documentation and the manuals:

man 8 knotc
man 8 knotd

Creative Commons License
How to configure master and slave Knot on Ubuntu 11.10 by Antonio Prado is licensed under a Creative Commons Attribution-ShareAlike 4.0 International

Leave a Reply