Friday, 18 February 2011

HOWTO: MASTER and SLAVE with Bind

So you have built yourself an authoritative nameserver and now you want to build a slave for it to replicate to.

Unfortunately, this is one of those things that is unnecessarily difficult to do on Linux. There are lot's of guides and howto's but they all seem to be missing bits and pieces of the puzzle. The good news is that after a few days of frustration I've figured out how to do it and I'm here to share the secret. Once you know what to do it is really extremely simple.

I'm using Ubuntu LTS Server 10.04 "Lucid Lynx", but as usual any debian based distro should be fine.

Pre-requisites:
Two working authoritative DNS servers built according to this guide. Both of these servers should be able to authoritatively resolve names for your local network.

Note:
In this howto we will using an MD5 key. The key used in this guide is sanitized (ie: not a real key) and should not be used "as is".

Example Network:
For the example network the domain I will be using is tuxnetworks.net, the MASTER server will be on 10.1.1.1 and the SLAVE server on 10.1.1.2. Of course you should substitute these values for ones that are valid on your own network. The two servers will be named ns1 and ns2.

OK, let's get cracking.

First up, before we can start doing zone transfers, we need to enable "dns security extensions" on both servers;

On BOTH servers, edit your named.conf.options file;

sudo vi /etc/bind/named.conf.options

Add this line within the options { }; section;

dnssec-enable yes;

Modify the allow recursions line so that it looks similar to this (using your own IP address's of course).

allow-recursion { 127.0.0.1; 10.1.1.0/24; };

Note:
These are all the hosts and networks that will be allowed to query the server(s) and should include both the Bind servers we are building. Since both our servers are in the 10.1.1.0/24 subnet we don't need to explicitly define them, if they weren't you would put their IP address in here too.

When we install bind, it will create a key that we can use. However, the keys will be different on the two servers. Let's copy the key from the MASTER to the SLAVE.

On the SLAVE, backup the old key file;

sudo cp /etc/bind/rndc.key /etc/bind/default.rndc.key

Cat the rndc.key file on the MASTER;

sudo cat /etc/bind/rndc.key
key "rndc-key" {
algorithm hmac-md5;
secret "BCRNAwUG2DRqz3fYleLO/g==";
};


On the SLAVE edit the rndc.key file and change the "secret" so that it is the same as the secret in the MASTER key.

sudo vi /etc/bind/rndc.key

The "secret" line should be changed to look the same as on the MASTER;

secret "BCRNAwUG2DRqz3fYleLO/g==";

Great. Now we need to edit the zone definition files on both servers. If you followed my guide to build your servers then it will be in named.conf.myzone-net. Other guides might put this info into named.conf or named.conf.options. The file is the one with the zone myzone { }; definition for your zone in it.

On BOTH servers, edit your zone definition file;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Add this line to the end of the file.

include "/etc/bind/rndc.key";

Now we reach the part where the MASTER and SLAVE servers are configured differently.

We will begin with the MASTER server. On the MASTER, edit your zone definition file again;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Add this section (using the IP address of the SLAVE server);
server 10.1.1.2 {
keys {
rndc-key;
};
};


Next we configure the SLAVE. Again, we edit the zone definition file;

sudo vi /etc/bind/named.conf.tuxnetworks-net

Inside the definition for the zone change the type from "master" to "slave" and add two lines to define the master servers details and specifically allow it to update the SLAVE.

Here is an example (use the IP address of your MASTER server here);
# This is the zone definition for the tuxnetworks.net zone.
zone "tuxnetworks.net" {
type slave;
file "/etc/bind/db.tuxnetworks.net";
masters { 10.1.1.1; };
allow-notify { 10.1.1.1; };
};

Also, add another section (using the MASTER IP address) to tell it to use the rndc-key;
server 10.1.1.1 {
keys {
rndc.key;
};
};


And that's it. We also need to ensure that both the servers are listed in the SOA section of your zone file (the zone file is the one where all the IP addresses for your network are located.

On BOTH servers open your zone file;

sudo vi /etc/bind/db.tuxnetworks.net

The top or second line should look like this (ie it should be showing both your DNS servers);

tuxnetworks.net. IN SOA ns1.tuxnetworks.net. ns2.tuxnetworks.net. (


Your NS servers should be defined properly;
; DNS Servers
tuxnetworks.net. IN NS ns1.tuxnetworks.net.
tuxnetworks.net. IN NS ns2.tuxnetworks.net.

We also need to define the IP address for both servers;
ns1             IN      A       10.1.1.1
ns2 IN A 10.1.1.2


Finally, for replication to occur, the two servers must be in close time sync. To ensure their internal clocks are synced properly, we will install ntpdate on both servers (this may already be installed on your systems)

sudo apt-get install ntpdate

Update the system time on both servers;

sudo ntpdate ntp.ubuntu.com

Check that the times are both in sync with the date command on both servers;

date
Wed Feb 11 10:30:16 EST 2011


Both systems should be within a few seconds. If they are way out, check that the timezones on both systems are the same;

dpkg-reconfigure tzdata

NOTE:
There is a bug in Ubuntu 10.04 bind package. When you it installs bind it fails to set the permissions correctly on the /etc/bind directory. I'm not sure if this affects other debian based distro's or not. A tell tale sign that the bug is in place (apart from slave updates not working) is an error in the syslog "bind dumping master file permission denied". To fix this change the ownership of the directory to the bind user;

sudo chown bind:bind /etc/bind

To make all the changes, restart bind on both servers;

sudo service bind9 restart

To test if your replication is working, go to the master server and edit the zone file. Increment the "serial" by one and issue a reload command on both servers;

sudo rndc reload

Now, if you look at the zone file on the slave, it should have been updated with the new serial.

When you are satisfied that both servers are working properly, you should remember to update your clients (or more likely your DHCP server) so that all your clients use both of your servers for resolving names.

Troubleshooting:
- Check your server times are in sync
- Check the permissions on /etc/bind
- Check that there are no firewalls between the two servers

A word on zone files:
Any time you make a change to the zone file on the master you need to update the serial. There is no set rule as to how the serial number should be formed. It can simply be an integer that you increment for each change if you like. I prefer to use the date in the form YYYMMDD with two trailing digits to allow for multiple increments within a day. That way I can know the date the last time the file was modified. As always YMMV.

I've tried to make this as simple to follow as possible. If there is something I haven't made clear enough then by all means leave me a message in the comments and I will tweak this howto accordingly.

Also, to make things a bit easier, you might like to download copies of all the example config files and modify them to suit your network.

Otherwise, enjoy your new DNS servers!

3 comments:

Keith Shum said...

Very nice, works well on CentOS6.4 too. Except one little thing in the zone files:

Instead of this...

tuxnetworks.net. IN SOA ns1.tuxnetworks.net. ns2.tuxnetworks.net. (

Add only the corresponding NS server there...

Liked Master:

tuxnetworks.net. IN SOA ns1.tuxnetworks.net. (

Liked Slave:

tuxnetworks.net. IN SOA ns1.tuxnetworks.net. (

Otherwise error occurs while starting named as invalid number.

David McNeill said...

For the slave, wrong syntax...

keys { rndc.key; };

should be

keys { rndc-key; };

David McNeill said...
This comment has been removed by the author.