Installation

_$: apt-get install bind

Configuration (Slave)

  • Master: 192.168.254.195
  • Slave: 192.168.254.199

We will add the master’s IP address in every zone of the slave server for which it is slave.

/etc/bind/named.conf.default-zones:
-----------------------------------
...
zone "example.com" {
	type slave;
	file "/var/lib/bind/slave.example.com";
	masters { 192.168.254.195; };           <=== Master's IP address
};

In the rest of its zones it will be a master:

/etc/bind/named.conf.local:
---------------------------
zone "254.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192.168.254";
};

zone "1.168.192.in-addr.arpa" {
    type master;
    file "/etc/bind/db.192.168.1";
};

Configuration (Master)

Allow zone transfers to the slave:

/etc/bind/named.conf.local:
---------------------------
...
zone "example.com" {
    type master;
    file "/etc/bind/db.example.com";
    notify yes;
    also-notify { 192.168.254.199; };           <=== Slave's IP address
    allow-transfer { 192.168.254.199; };        <=== Slave's IP address
};
root@dns:/etc/bind# named-checkconf

Configuration (Network hosts)

/etc/resolv.conf:
-----------------
nameserver 192.168.254.195      (master)
nameserver 192.168.254.199      (slave)
nameserver 192.168.1.1          (default gateway)

Check

root@dns-slave:/etc/bind# dig @localhost example.com any

; <<>> DiG 9.7.3 <<>> @localhost example.com any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26477
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 0, ADDITIONAL: 5

;; QUESTION SECTION:
;example.com.           IN  ANY

;; ANSWER SECTION:
example.com.    604800  IN  SOA dns.example.com. info.example.com. 2013011501 7200 120 2419200 604800
example.com.    604800  IN  TXT "v=spf1 +a +mx -all"
example.com.    604800  IN  MX  10 mail-d6.example.com.
example.com.    604800  IN  NS  dns.example.com.
example.com.    604800  IN  NS  dns-slave.example.com.

;; ADDITIONAL SECTION:
mail-d6.example.com.    604800  IN  A   192.168.254.193
dns.example.com.        604800  IN  A   192.168.254.195
dns-slave.example.com.  604800  IN  A   192.168.254.199

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Jan 15 17:10:58 2013
;; MSG SIZE  rcvd: 293

In the first line of the ANSWER SECTION note the serial: 2013011501. Let’s update the serial in the master server:

root@dns:/etc/bind# vi db.example.com
/etc/bind/db.example.com:
-------------------------
...
			2013011502	; Serial
...
root@dns:/etc/bind# /etc/init.d/bind9 reload
Reloading domain name service...: bind9.

And let’s repeat the query in the slave server

root@dns-slave:/etc/bind# dig @localhost -t SOA example.com +norecurs

; <<>> DiG 9.7.3 <<>> @localhost -t SOA example.com +norecurs
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9846
;; flags: qr aa ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 3

;; QUESTION SECTION:
;example.com.                IN  SOA

;; ANSWER SECTION:
example.com.         604800  IN  SOA dns.example.com. info.example.com. 2013011502 7200 120 2419200 604800

;; AUTHORITY SECTION:
example.com.         604800  IN  NS  dns-slave.example.com.
example.com.         604800  IN  NS  dns.example.com.

;; ADDITIONAL SECTION:
dns.example.com.         604800  IN  A   192.168.254.195
dns-slave.example.com.   604800  IN  A   192.168.254.199

;; Query time: 0 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Tue Jan 15 17:20:54 2013
;; MSG SIZE  rcvd: 175

The serial has changed to 2013011502 so that is good.

Check the log

/var/log/bind/dns.log:
----------------------
...
transfer of 'example.com/IN' from 192.168.254.195#53: Transfer completed: 1 messages, 15 records, 637 bytes, 0.001 secs (637000 bytes/sec)
root@dns-slave:/etc/bind# ls -la /var/lib/bind/
total 16
drwxrwxr-x  2 root bind 4096 Jan 15 17:33 .
drwxr-xr-x 29 root root 4096 Dec 27 10:25 ..
-rw-r--r--  1 bind bind  975 Jan 15 17:33 slave.example.com
root@dns-slave:/etc/bind# cat /var/lib/bind/slave.example.com
$ORIGIN .
$TTL 604800 ; 1 week
example.com     IN SOA     dns.example.com. info.example.com. (
                2013011502 ; serial
                7200       ; refresh (2 hours)
                120        ; retry (2 minutes)
                2419200    ; expire (4 weeks)
                604800     ; minimum (1 week)
                )
            NS  dns.example.com.
            NS  dns-slave.example.com.
            MX  10 mail.example.com.
            TXT "v=spf1 +a +mx -all"
$ORIGIN example.com.
example.com._domainkey	TXT	"v=DKIM1\; g=*\; k=rsa\; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHPWNGNc8lKhfeywkE6gZg77oE6dIFm8EuqZ5VLyX9dbOi+zLxy7442o5bEEpXl+l1HPWfwzqjXpkbOMtK3ac5xxopgJ2U/nUpFffhM0CtDN2h3prDIfjyuAXSENHRRz4UQv4qdKyD902yQhT/nYAfuCvw9Sn8H5LCjYRSNjRVsQIDAQAB"
dns         A   192.168.254.195
dns-slave   A   192.168.254.199
git         A   192.168.254.191
mail        A   192.168.254.193
samba       A   192.168.254.192
zabbix      A   192.168.254.190

The IP addresses might appear unsorted, but they are the same.

Simlulate a failure on the master

1) Remove the default gateway so as non-local DNS queries are not sent to the outside world.

_$: vi /etc/resolv.conf
/etc/resolv.conf:
-----------------
nameserver 192.168.254.195
nameserver 192.168.254.199

2) Stop the master

root@dns:/etc/bind# /etc/init.d/bind9 stop
Stopping domain name service...: bind9 waiting for pid 2308 to die.

Check that the master is not answering:

_$: dig @192.168.254.195 example.com any
^C

but the slave is:

_$: dig @192.168.254.199 example.com any

; <<>> DiG 9.8.1-P1 <<>> @192.168.254.199 example.com any
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20238
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 0, ADDITIONAL: 5

;; QUESTION SECTION:
;example.com.                IN	ANY

;; ANSWER SECTION:
example.com.			604800	IN	SOA	dns.example.com. info.example.com. 2013011502 7200 120 2419200 604800

3) Ping hosts

From another host in the network we can ping the zabbix host. At the same time, you can check the log in the slave server:

_$: ping zabbix.example.com
PING zabbix.example.com (192.168.254.190) 56(84) bytes of data.
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=1 ttl=64 time=0.185 ms
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=2 ttl=64 time=0.260 ms
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=3 ttl=64 time=0.313 ms
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=4 ttl=64 time=0.291 ms
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=5 ttl=64 time=0.197 ms
64 bytes from zabbix.example.com (192.168.254.190): icmp_req=6 ttl=64 time=0.195 ms
^C
--- zabbix.example.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5001ms
rtt min/avg/max/mdev = 0.185/0.240/0.313/0.051 ms
root@dns-slave: tail -f /var/log/bind/dns.log
client @0x7fc77c3db1f0: udprecv
client 192.168.254.191#55675: UDP request
client 192.168.254.191#55675: using view '_default'
client 192.168.254.191#55675: request is not signed
client 192.168.254.191#55675: recursion available
client 192.168.254.191#55675: query
client 192.168.254.191#55675: query 'zabbix.example.com/A/IN' approved
client 192.168.254.191#55675: send
client 192.168.254.191#55675: sendto
client 192.168.254.191#55675: senddone
client 192.168.254.191#55675: next
client 192.168.254.191#55675: endrequest

And we can also do a lookup:

_$: nslookup zabbix.example.com
Server:		192.168.254.199         # Slave answering => OK
Address:	192.168.254.199#53

Name:	zabbix.example.com
Address: 192.168.254.190