<HEAD><TITLE>Being a slave DNS server</TITLE>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">

</HEAD><BODY>

<!-- Copyright 2005 Sam Trenholme

    TERMS

    Redistribution and use, with or without modification, are permitted
    provided that the following condition is met:

    1. Redistributions must retain the above copyright notice, this
       list of conditions and the following disclaimer.

    This documentation is provided 'as is' with no guarantees of
    correctness or fitness for purpose.

 -->

<H1>Having MaraDNS be a slave DNS server</H1>

MaraDNS does not have direct support for being a slave DNS server.
However, MaraDNS can transfer zone files from other servers by using
the <tt>fetchzone</tt> client.  

<p>

<tt>fetchzone</tt> is a program that can transfer a zone from another
name server; the transferred zone is in the csv2 zone file format, which
can then be loaded by MaraDNS.

<p>

Here is an example of using <tt>fetchzone</tt> to transfer the zone
example.com from the server with the IP 10.5.6.7, placing the output
in the file "db.example.com":

<pre>
fetchzone example.com 10.5.6.7 > db.example.com
</pre>

<h2>Automating this with a shell script</h2>

If one wishes to use fetchzone to grab a number of zones, this can
be automated with a shell script:

<pre>
#!/bin/bash

cd /etc/maradns
fetchzone example.com 10.5.6.7 > db.example.com
fetchzone example.org 192.168.5.67 > db.example.org
fetchzone example.net 172.19.2.83 > db.example.net
</pre>

This shell script, however, has a problem.  Should there be a problem
getting a zone file from a remote system, the zone file in question will be
destroyed.  This can be avoided by checking the exit status of 
<tt>fetchzone</tt> in the shell script, making sure that the zone
was obtained normally before overwriting the zone file:

<pre>
#!/bin/bash

# For security reasons, put this file in a directory that only root
# may write to.  
TEMP=/root/tmp/foo

cd /etc/maradns
fetchzone example.com 10.5.6.7 > $TEMP
if [ $? -eq 0 ] ; then
	mv $TEMP db.example.com
fi
fetchzone example.org 192.168.5.67 > $TEMP
if [ $? -eq 0 ] ; then
	mv $TEMP db.example.org
fi
fetchzone example.net 172.19.2.83 > $TEMP
if [ $? -eq 0 ] ; then
	mv $TEMP db.example.net
fi
</pre>

Note that this script needs a directory, which only root may write
to, named <tt>/root/tmp</tt> (Linux has a long-standing tradition of
making root's home directory /root; place this file elsewhere on a system
with a different root directory).

<p>

While this script is workable for a small number of zones, this script will
quickly become unwieldy for a large number of zones.  If one wants
to grab a large number of zones, it makes more sense to have the list
of zones in a separate file.  We then have the shell script read this
file (list of zones and IPs), and make the zone files live if the
zones have been successfully fetched.

<p>

Here is what a shell script may look like:

<pre>
#!/bin/bash

ZONELIST=/etc/maradns.zonelist
# For security reasons, put this file in a directory that only root
# may write to.  
TEMP=/root/tmp/foo

cd /etc/maradns

cat $ZONELIST | awk '{print "fetchzone "$1" "$2" > '$TEMP'"
                      print "if [ $? -eq 0 ] ; then"
		      print "    mv '$TEMP' db."$1
		      print "fi";}' | sh
</pre>

The list of zones, which is in the file <tt>/etc/maradns.zonelist</tt> in
the above example, will look like this:

<pre>
example.com 10.5.6.7 
example.org 192.168.5.67 
example.net 172.19.2.83 
</pre>

Note that the presence of a given db.<i>name</i> file in the /etc/maradns
directory is not sufficient for MaraDNS to load a given zone file; the
zone file in question must be pointed to in the <tt>mararc</tt> file.
Note also that <tt>maradns</tt> must be restarted to reload the updated
zone files.

<p>

More complicated scripting, such as checking the serial number before loading
a given zone, is left as an exercise for the reader.

<h2>Bailiwick</h2>

For security reasons, the <tt>fetchzone</tt> client only allows records that 
end in the zone name to be in a given zone.  In other words, let us suppose we
have a zone for example.com that looks like this:

<pre>
example.com.      10.1.2.3
www.example.com.  10.99.88.76
www.google.com.   10.99.88.76
</pre>

<tt>fetchzone</tt>, when grabbing this zone, will disable the "www.google.com"
record because it doesn't end with "example.com".  The disabling will 
look something like this when the zone file is grabbed:

<pre>
example.com. 10.1.2.3
www.example.com. 10.99.88.76
# Disabled out-of-bailiwick record follows
#www.google.com. 10.99.88.76
</pre>

</BODY></HTML>
