Configure bind9 as master/slave pair on CentOS / RHEL 5

There are plenty of HOWTO documents on this and I've discovered that nearly all of them are full of unnecessary fluff that can be both confusing and misleading. It's probably because they are reworks of older HOWTOs from the bind8 era. Configuring bind9 in master/slave is far easier and requires far fewer configuration changes than the existing HOWTOs suggest.

You need to edit the named.conf files on both systems. I'm assuming that you begin with a functioning but otherwise default configuration on both machines.

  • On the master machine, create a dns key and put it in a secure file that you can include.

    sudo dns-keygen > /etc/named-tsig-key.conf

    Then edit the output file: /etc/named-tsig-key.conf so it looks something like this:

    key ddns_key
    {
      algorithm hmac-md5;
      secret "lw8MPJFqapeAG3ehTuvDBPUhRWzX1hyz5Ov3UvIXhmGh4XkPKIcPNCsz5f8v";
    };
    

    Where the hex string is the one you just generated (not the one I've used as an example), which you should find in the file, because we just put it there.

    Fix up the permissions on the key file:

    sudo chmod og-rw /etc/named-tsig-key.conf
    sudo chown named:named /etc/named-tsig-key.conf
    
  • Include the dns key file in your named.conf on both machines:

    In your named.conf, after the logging section in named.conf add:

    include "/etc/named-tsig-key.conf";

    You can call this key file whatever you like, and put it wherever you choose (think is most secure), but I've put mine in /etc/ and named it in a way that makes sense to me.

  • Copy the key file you generated on the master to the slave machine. You will need to put it in the same place and ensure that the permissions and ownership are the same as used on the master. There are lots of ways you could copy the file, from sftp/scp to simple cut and paste from one putty session to another.
  • Add server descriptions to both machines following the include directive:
    server 123.456.789.123 {
        keys {  ddns_key;
        };
    };
    

    The address here is the address of the other machine. If you are on the master, list the address of the slave. If you are on the slave, list the address of the master.

    You need to use an IP here, don't use the server's name.

    This directive tells bind that it should use the key we generated for communication with that server.

  • Add the zones to the slave configuration:

    I'm going to assume you already know how to add zones to the master, and that they are already configured - there is no additional change required to the master. The master does not need any special configuration to serve zones to the slave. Setting up an ordinary master zone is nothing specific to the master-slave set-up, so no point going into it here, you can find info on it almost anywhere.

    There is already an example internal slave zone in the default config file in the internal view:

    //zone "my.slave.internal.zone" {
    //      type slave;
    //      file "slaves/my.slave.internal.zone.db";
    //      masters { // put master nameserver IPs here
    //      127.0.0.1;
    //    } ;
    // put slave zones in the slaves/ directory so named can update them
    

    However, if you are using your slave as a second nameserver of an authoritative pair (and this is probably the reason you want to set up master slave) you need to put your slave zones in the external view not the internal, or else your slave nameserver will not serve them to anyone else. You don't really need the zone in internal view at all on the slave, as internal look-ups on the name through localhost_resolver will do an external DNS lookup (which might end up eventually looking at our external view anyway) and then be cached - one external lookup, hardly a big overhead, and saves the complexity of adding the zone to different views.

    So for a typical zone, add something like this to the external view:

    zone "mydomain.tld" IN {
      type slave;
      file "slaves/db.mydomain.zone";
      masters { 123.456.789.122; }; // The IP of the master server
    };
    
  • So, that's all you really need to do to get master-slave working. Most of the HOWTO docs I found suggested making all kinds of pervasive changes to named.conf, particularly in the options section. When I looked at what those changes were intended to do, they either replicated default behaviour and were thus utterly pointless, or they were actually wrong and would only cause trouble.

    You can do other stuff, like enabling zone transfers to the slave on the master, but there's really no need to do that.

    All you need to get a working setup is the key declaration, a server declaration, and addition of the slave zones on the slave server (assuming the zones already exist on the master).

    All the other changes that people suggest are simply not necessary to get a working master-slave pair under CentOS / RHEL 5.X using bind9, and are as likely to result in harm rather than any benefit. The defaults of bind9 are pretty much what you want, and I don't recommend changing any of them unless you really know why you are doing it.