Skip to content

Replicating BIND DNS slave configurations from BIND DNS master servers

Internet

Manually copying the BIND master zone configuration to slave servers is a tedious and error-prone process. There are configuration management systems available for large deployments and BIND can support database backends as well which allow synchronization virtually behind the scenes.

For my use these options are overly complex and have unwanted risks associated with it.

The better option is to automate generating the BIND slave configuration from the BIND master named.conf.local.

Setup

The DNS master server has a file /etc/bind/named.conf.local (e.g. on Debian or Ubuntu systems) which looks similar to this:


//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

# ======= ZONE EXAMPLE.[DE|COM|NET|ORG] =======
# Customer: The Example Company
# Contact: joe@example.com, joe@gmail.com ...

zone "example.de" IN {
        type master;
        file "pri/example_multi.zone";
};

zone "example.com" IN {
        type master;
        file "pri/example_multi.zone";
};

zone "example.net" IN {
        type master;
        file "pri/example_multi.zone";
};

zone "example.org" IN {
        type master;
        file "pri/example_multi.zone";
};

# ======= ZONE EXAMPLE2.[COM|NET] =======
# Customer: The Example Company
# Contact: joe@example.com, joe@gmail.com ...

zone "example2.com" IN {
        type master;
        file "pri/example2_multi.zone";
};

zone "example2.net" IN {
        type master;
        file "pri/example2_multi.zone";
};
[...]
 

The interesting twist here is that I re-use zone files for similar zones (hence the _multi.zone file name) to save typing and keep things in sync across multiple (national) TLDs.

Now on the BIND slave these end up all in different zone files as BIND is not clever enough to re-use zone files across domains on the slave as well. So this is again an excerpt from /etc/bind/named.conf.local but this time from a BIND DNS slave:


//
// Do any local configuration here
//

// Consider adding the 1918 zones here, if they are not used in your
// organization
//include "/etc/bind/zones.rfc1918";

# ======= ZONE EXAMPLE.[DE|COM|NET|ORG] =======
# Customer: The Example Company
# Contact: joe@example.com, joe@gmail.com ...

zone "example.de" IN {
        type slave;
        file "/var/cache/bind/db.example.de";
        masters { 168.1.1.1; 168.1.2.1; };
};

zone "example.com" IN {
        type slave;
        file "/var/cache/bind/db.example.com";
        masters { 168.1.1.1; 168.1.2.1; };
};

zone "example.net" IN {
        type slave;
        file "/var/cache/bind/db.example.net";
        masters { 168.1.1.1; 168.1.2.1; };
};

zone "example.org" IN {
        type slave;
        file "/var/cache/bind/db.example.org";
        masters { 168.1.1.1; 168.1.2.1; };
};

# ======= ZONE EXAMPLE2.[COM|NET] =======
# Customer: The Example Company
# Contact: joe@example.com, joe@gmail.com ...

zone "example2.com" IN {
        type slave;
        file "/var/cache/bind/db.example2.com";
        masters { 168.1.1.1; 168.1.2.1; };
};

zone "example2.net" IN {
        type slave;
        file "/var/cache/bind/db.example2.net";
        masters { 168.1.1.1; 168.1.2.1; };
};
[...]
 

So for every zone entry in the master named.conf.local there is a corresponding entry in the slave named.conf.local. Now how nice would it be if they had the same format and the master or slave role could be just selected somewhere in the options section...

Scripting to the rescue

But as that is not the case and I got tired of copying over things manually whenever I add or delete zones, I wrote a small awk script bind_master2slave (2kB) that converts a BIND master named.conf.local into a BIND slave named.conf.local.

For that is needs a template of how to construct a slave zone which will be filled once for every occurrance of the zone keyword in the master named.conf.local piped into stdin. Awk is a bit limited in what in can do, so for templates you need to abuse gsub or sprintf a bit. I chose the first option:


# Template for slave zone entries
# _ZONE_ will be replaced by the zone name read from the master file (well ... stdin)
# End lines with a backslash (\) for continuation and escape quotation marks (\")

SLAVE_TEMPLATE="zone \"_ZONE_\" IN {\n\
       type slave;\n\
       file \"/var/cache/bind/db._ZONE_\";\n\
       masters { 168.1.1.1; 168.1.2.1; };\n\
};"

[...]
        MYTEMPLATE=SLAVE_TEMPLATE
        gsub(/_ZONE_/,ZONE,MYTEMPLATE)
        print MYTEMPLATE
 

You need to change the SLAVE_TEMPLATE variable to match your desired slave zone configuration block.
The template element ZONE will be replaced by the domain given in the master zones configuration file and replicated to the slave zones configuration file.

There is another variable you should customize:
If you set VERBOSE to 1 the script will give you a report of the zone statements it found, like this to stderr:

$ bind_master2slave from_master/named.conf.local > for_slaves/named.conf.local
Processed 2530 lines. Created 440 slave records.

If you set VERBOSE to 2 (default) it will additionally warn you (and exit with error code 1) if your master zone configuration statements were not all well formed. This hints at errors from generating/editing the master zone file. If you have good reasons to have zone statements that have different line counts, you can disable the check by setting VERBOSE to 1 or 0.

I explicitly advise against running bind_master2slave automated and deploying the files without manual review. You could easily break master and slave DNS servers at the same time. That's what should not happen. So review before deploy.

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

Geoff Wild on :

Just wanted to say thanks for sharing your script.

I'm using it from a CentOS master to a Fedora slave.

Rgds...Geoff

Miki on :

Thank you for the scripts, from Canary Island, Spain

Add Comment

Markdown format allowed
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Submitted comments will be subject to moderation before being displayed.