<HEAD><TITLE>Recursive DNS serving</TITLE>

<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">

</HEAD><BODY>

<!-- Copyright 2005-2006 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>Using MaraDNS as a recursive DNS server</H1>

This document is a step-by-step guide to setting up MaraDNS as a recursive 
DNS server.  It assumes that MaraDNS is already <A 
href=compile.html>compiled and installed</A>.

<A name=toc>
<H2>Table of contents</H2>
</A>

<ul>
<li><A href=#basic>Basic configuration</A>
<li><A href=#slow>Using MaraDNS on a slow network</A>
<li><A href=#upstream>Using other recursive DNS servers</A>
<li><A href=#otherroot>Using different root servers</A>
<li><A href=#private>Having private host names</A>
<li><A href=#custom>Customizing the resolution of some names</A>
</ul>

<A name=basic>
<H2>Basic configuration</H2>
</A>

Once MaraDNS is installed, the <tt>mararc</tt> file needs to be set up
before MaraDNS will function as a recursive DNS server.  This file only 
needs to be three lines long:

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
</pre>

<p>
This three-line file needs to be called <tt>/etc/mararc</tt>.

<p>
The first line is the IP address or addresses MaraDNS will use.  Here, it
has the address 127.0.0.1, which means that only the machine running MaraDNS
will be able to access the MaraDNS server--other machines will not be able
to see it.  

<p>
If the machine running MaraDNS will be accessed by other machines, this
IP needs to be changed to an IP that the machine running MaraDNS has.

<p>
It is possible to have MaraDNS run on multiple IP addresses:

<pre>
ipv4_bind_addresses = "10.1.3.2, 192.168.0.1, 127.0.0.1"
</pre>

The second line, <tt>chroot_dir</tt> is the directory MaraDNS will be 
run from.  When MaraDNS is being used as a recursive DNS server, this just 
has to be an empty directory, ideally owned by the root user.

<p>

The third line, <tt>recursive_acl</tt>, determines the
range of IPs that can access the
recursive DNS server.  This is in IP/netmask format.
For example, if one has an office
which uses IPs in the form 192.168.1.1, 192.168.1.2, etc.,
and wishes to have only 192.168.1.<i>any</i> be allowed to make
recursive queries:

<pre>
recursive_acl = "<b>192.168.1.0/24</b>"</tt>
</pre>

Here the "/24" indicates that we ignore the fourth number in an IP
when determining who can contact MaraDNS.

<p>
Once this is done, other machines can contact the MaraDNS server to
perform DNS queries.  For example, MaraDNS is now a DNS server which 
Windows 98 can use in "Control Panel -> Network -> TCP/IP -> DNS 
configuration", or a UNIX system can point to from 
<tt>/etc/resolv.conf</tt>.

<A name=slow>
<h2>Using MaraDNS on a slow network</h2></A>

MaraDNS, on a slow network, may time out.  MaraDNS normally only waits
two seconds for a reply from a remote DNS server.  This is not enough
time to process queries on some slow networks.  This can be changed by
increasing the <tt>timeout_seconds</tt> value.

<p>

Here is a mararc file which waits six seconds (instead of the default two)
for a reply from a remote DNS server:

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
timeout_seconds = 6
</pre>

<!-- Guess what?  All of the supported OSes that MaraDNS compiles on,
     with the exception of the mingw32 semi-port (which has its own
     workaround), have /dev/urandom support.  So we don't need to tell
     people how to set up a random_seed_file in the tutorial. -->

<A name=upstream>
<h2>Using other recursive DNS servers</h2> 
</A>

It is possible to have MaraDNS contact other recursive name servers,
instead of contacting the actual root servers to process recursive
queries by using the variable <tt>upstream_servers</tt> in the mararc file.

<p>

In other words, one can use one's, say, ISP's DNS servers to resolve the
names, and have MaraDNS act as a cache for the ISP's DNS servers.  Supposing
that the ISP name servers have the IPs 10.66.77.88 and 10.99.11.22, the
mararc file will look like this:

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
upstream_servers = {}
upstream_servers["."] = "10.66.77.88, 10.99.11.22"
</pre>

<A name=otherroot>
<h2>Using different root servers</h2></A>

MaraDNS, by default, uses the ICANN name servers as the root name servers.
The reason for this default is practical: In my experience, the ICANN root
name servers are the ones which least frequently change their IP addresses.
They are the best name servers for simple "set and forget" recursive
environments.

<p>

It is possible, however, to change the root DNS servers used by setting the
<tt>root_servers</tt> variable in the mararc file.  Here is what such a
recursive configuration (this example uses the ICANN root servers;
change this example to use another set of root servers as needed)
looks like:

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
ipv4_alias = {}
ipv4_alias["icann"]  = "198.41.0.4,"     
ipv4_alias["icann"] += "192.228.79.201,"
ipv4_alias["icann"] += "192.33.4.12,"
ipv4_alias["icann"] += "128.8.10.90,"
ipv4_alias["icann"] += "192.203.230.10,"
ipv4_alias["icann"] += "192.5.5.241,"
ipv4_alias["icann"] += "192.112.36.4,"
ipv4_alias["icann"] += "128.63.2.53,"
ipv4_alias["icann"] += "192.36.148.17,"
ipv4_alias["icann"] += "192.58.128.30,"
ipv4_alias["icann"] += "193.0.14.129,"
ipv4_alias["icann"] += "198.32.64.12,"
ipv4_alias["icann"] += "202.12.27.33"
root_servers["."] = "icann"
</pre>

This file will do the exact same thing as the following <tt>mararc</tt> file:

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
</pre>

The ICANN servers listed above are the ones that MaraDNS uses when no
root servers are specified.

<p>

As an aside, the <tt>ipv4_alias</tt> variable is a general purpose way of
giving names to any set of IPs in a <tt>mararc</tt> file.  We can use 
shortcuts like this, in fact:

<pre>
ipv4_alias = {}
ipv4_alias["localhost"] = "127.0.0.1"
ipv4_bind_addresses = "localhost"
chroot_dir = "/etc/maradns"
recursive_acl = "localhost"
ipv4_alias["icann-a"] = "198.41.0.4"
ipv4_alias["icann-b"] = "192.228.79.201"
ipv4_alias["icann-c"] = "192.33.4.12"
ipv4_alias["icann-d"] = "128.8.10.90"
ipv4_alias["icann-e"] = "192.203.230.10"
ipv4_alias["icann-f"] = "192.5.5.241"
ipv4_alias["icann-g"] = "192.112.36.4"
ipv4_alias["icann-h"] = "128.63.2.53"
ipv4_alias["icann-i"] = "192.36.148.17"
ipv4_alias["icann-j"] = "192.58.128.30"
ipv4_alias["icann-k"] = "193.0.14.129"
ipv4_alias["icann-l"] = "198.32.64.12"
ipv4_alias["icann-m"] = "202.12.27.33"
ipv4_alias["icann"] = "icann-a,icann-b,icann-c,icann-d,icann-e,icann-f,"
ipv4_alias["icann"] += "icann-g,icann-h,icann-i,icann-j,icann-k,icann-l,"
ipv4_alias["icann"] += "icann-m"
root_servers["."] = "icann"
</pre>

This works the same as the above two examples.  The reason why we don't have
commas in any of the aliases besides icann is because the comma before 
the quote is only needed on a line before a line that uses 
the <tt>+=</tt> operator.

<p>

Here is what a configuration file which uses OpenNIC's glue root servers
as the root servers.  This list is current as of February 22, 2006; note
that OpenNIC frequently changes these IPs and you need to verify that
these IPs are current at <A 
href=http://www.opennic.unrated.net/>http://www.opennic.unrated.net/</A>.
A number of alternate root server organizations no longer exist; please
make sure these people still exist before using this list.

<pre>
ipv4_bind_addresses = "127.0.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "127.0.0.1"
ipv4_alias = {}
# This ends with a comma because the next line is a += line
ipv4_alias["opennic"]  = "131.161.247.232,"
ipv4_alias["opennic"] += "208.185.249.250,"
ipv4_alias["opennic"] += "66.227.42.140,"
ipv4_alias["opennic"] += "66.227.42.149,"
ipv4_alias["opennic"] += "64.81.44.251,"
ipv4_alais["opennic"] += "216.87.84.214,"
ipv4_alias["opennic"] += "208.185.249.251,"
ipv4_alias["opennic"] += "131.161.247.231,"
# This is the last line, so no comma at the end
ipv4_alias["opennic"] += "65.243.92.254"
# Considering how often alternate root DNS server lists change or disappear,
# we will have the ICANN list on hand as a backup.
ipv4_alias["icann"]  = "198.41.0.4,"     
ipv4_alias["icann"] += "192.228.79.201,"
ipv4_alias["icann"] += "192.33.4.12,"
ipv4_alias["icann"] += "128.8.10.90,"
ipv4_alias["icann"] += "192.203.230.10,"
ipv4_alias["icann"] += "192.5.5.241,"
ipv4_alias["icann"] += "192.112.36.4,"
ipv4_alias["icann"] += "128.63.2.53,"
ipv4_alias["icann"] += "192.36.148.17,"
ipv4_alias["icann"] += "192.58.128.30,"
ipv4_alias["icann"] += "193.0.14.129,"
ipv4_alias["icann"] += "198.32.64.12,"
ipv4_alias["icann"] += "202.12.27.33"
# Now, set the root servers; chance this to icann if you want to use the
# icann servers instead.
root_servers["."] = "opennic"
</pre>

<A name=private>
<h2>Having private host names</h2>
</A>

One may wish to have private host names when running MaraDNS as a recursive
name server.  These are names that are not attached to the root servers,
but will resolve on the recursive name server.  For example, it might make
sense to have "router.example.com." resolve to the IP of a router in an
office.

<p>

This is done by taking advantage of the fact that MaraDNS 
can act as both a recursive and authoritative name server on the same IP.
MaraDNS first looks up authoritative names before performing recursion.
For example, if <tt>www.google.com</tt> is defined in a MaraDNS zone
file, MaraDNS will use the value in the zone file instead of contacting
nameservers on the internet to get the IP for <tt>www.google.com</tt>.

<p>

The procedure to do this is as follows:

<ul>
<li>Have an authoritative and recursive DNS server share the same IP.  Make
  sure this DNS server is not accessible from the public internet.
<li>For this authoritative server, have zone files for the zones which one
  wants to have non-public information.  Recursive queries will be resolved
  as usual (since the authoritative server is also a recursive server);
  authoritative queries for the special zones will get the special data.
<li>The <A href=man.maradns.html>maradns man page</A> has a section on 
  firewall configuration which 
  describes how to set up an IP filter to allow MaraDNS to send packets.
  Basically, don't allow outside IPs to hit this combined server on port
  53 (UDP); instead allow UDP connections to ports 15000-19095.
</ul>

Here is how the configuration may look:

<pre>
ipv4_bind_addresses = "192.168.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "192.168.0.0/24"
csv2 = {}
csv2["example.com."] = "db.example.com"
</pre>

Replace 192.168.0.1 with the IP of the machine running the recursive MaraDNS;
replace 192.168.0.0/24 (This means "anything that begins with 192.168.0")
with the IP range allowed to access the recursive DNS server.

<p>

The file "db.example.com." will be a csv2 zone file with records for the 
bogus example.com domain, such as router.example.com.

<p>

If you want to have some of these private names be CNAMES for hostnames
on the internet (e.g. "google.example.com. CNAME www.google.com."), please 
read the <A href=dangling.html>dangling CNAME document</A>.

<p>

More information on having host names for an internal network is available
in the <A href="authoritative.html#network">network section of the
authoritative document</A>.

<A name=custom>
<h2>Customizing the resolution of some names</h2>
</A>

One may wish to customize the resolution of certain names when using
MaraDNS as both an authoritative and recursive name server.  For example,
if a high-profile domain is hijacked (such as what happened with
panix.com in January of 2005), it may be desirable to have the correct
name for the domain be temporarily locally set.  This is also useful for 
a list of blocked sites (so the user gets a friendly "this site is blocked"
instead of just being unable to connect to the site in question), and for
setups where some machines need special DNS resolution for names that
other machines do not need DNS resolution for.

<p>

The procedure for doing this is almost identical to the procedure for
having private host names as described above.  Here is an example
relevant <tt>mararc</tt> file:

<pre>
ipv4_bind_addresses = "192.168.0.1"
chroot_dir = "/etc/maradns"
recursive_acl = "192.168.0.0/24"
csv2 = {}
csv2["example.com."] = "db.example.com"
</pre>

The only things that need to be changed in this mararc file are
the <tt>ipv4_bind_addresses</tt> and the <tt>recursive_acl</tt>
parameters.  The <tt>csv2["example.com."]</tt> is <i>not</i> changed.

<p>

Now, let us suppose we want to have the A records for "www.phishsite.foo" 
and "phishsite.foo" resolve to an IP address that we control the web
site for.  We would add the following records (lines) to the file
<tt>/etc/maradns/db.example.com</tt>

<pre>
www.phishsite.foo. 192.168.0.2
phishsite.foo. 192.168.0.2
</pre>

We can also add a star record:

<pre>
*.phishsite.foo. 192.168.0.2
</pre>

</BODY>
