# Split DNS done right: 2 servers; NSD and BIND9



Open recursors are a problem. They can be used by attackers to amplify a packet
stream to a victim. As such you should *only* be running a
recursor on your internal network and an authoritative server on your
interfaces facing the big, bad Internet.

You can run [BIND9](http://www.isc.org/bind) with a split view (also
called 'split brain'), or use my setup: a
[NSD](http://www.nlnetlabs.nl/nsd/) serving the outside world, and using
BIND9 as recursor for your internal network.

# Zones
I'm the owner of multiple domains, among which `miek.nl` is just one. For the purpose
of this article I will pretend this is the only domain I have. The goal here is to
have this domain available *both* inside my network and on the outside. And to have
recursion on the inside, but *not* on the outside.

# Internet side
The config for `miek.nl` looks like this. This does assume how to read these kind 
of files. The zone file is relatively short and nothing fancy happens.

> For completeness, I'm using [puppet](/2008/february/02/puppet_with_git/index.html) 
> for my `/etc/` configuration -- you should too! :)

    ;
    ; NSD data file for miek.nl for public use
    ; ## configured with puppet ##
    ;
    $TTL    1D
    $ORIGIN miek.nl.
    @       IN      SOA     open.nlnetlabs.nl. miekg.atoom.net. (
                       2007032000     ; Serial
                         4H         ; Refresh
                         1H         ; Retry
                         7D         ; Expire
                         1D )       ; Negative Cache TTL
                IN      NS      open.nlnetlabs.nl.
                IN      NS      omval.tednet.nl.
                IN      NS      elektron.atoom.net.

                IN      MX      20 mail.atoom.net.
                IN      MX      30 sol.nlnetlabs.nl.

    miek.nl.	IN	A	80.127.17.126
    localhost	IN	A	127.0.0.1
    a	    	IN	A	80.127.17.126
    www     	IN 	CNAME 	a

This zonefile contains *real* IP addresses, which can be resolved on the Internet.

 Internal side
For internal use I'm using a slightly different zone (the joy of NAT), which looks like this:

    ;
    ; BIND data file for miek.nl for internal use
    ;
    $TTL    1H
    @       IN      SOA     elektron.atoom.net. miekg.atoom.net. (
                   2005060700         ; Serial
                         6H         ; Refresh
                         2H         ; Retry
                         7D         ; Expire
                         1H )       ; Negative Cache TTL

    @      IN      NS      elektron.atoom.net.
    @      IN      MX      10 elektron.atoom.net.
    @      IN      A      192.168.1.2

    localhost   IN      A      127.0.0.1
    a           IN      A      192.168.1.2
    www         IN      CNAME   a

And you can see that only RFC1918 addresses are used here.

# Setup
So how do you actually perform the setup so that you have two servers running? First install the
software packages you'll need (This is on Ubuntu/Debian):

Install nsd: 

    apt-get install nsd

Install	bind9

    apt-get install bind9

# Configuration
 BIND
Well, `BIND` is pretty well known and you can find loads of howtos on how to setup this daemon. 
I'm only interested in making is listening on the *intra*net interfaces, in my 
case (i'm only showing the relevant parts of the `named.conf` configuration file):

    // This is the primary configuration file for the BIND DNS server named.
    // ## configured with puppet ##

    options {
          directory "/var/cache/bind";
          recursion yes;
          listen-on { 127.0.0.1; 192.168.1.2; ::1; 10.0.0.1; };
    };

Note the `recursion yes`, without this I wouldn't be able to resolve names on my internal 
network. 

My `/etc/resolv.conf` ofcourse lists my own server as nameserver:

    # ## configured with puppet ##
    nameserver 127.0.0.1
    search atoom.net. dmz.atoom.net.

So this takes care of my *internal* needs.

 NSD
For NSD (version 2) I need to configure which zones are to be loaded. This is done in the
`nsd.zones` file:

    ; ## configured with puppet ##
    ; forward
    zone miek.nl                  zones/db.miek.nl        notify 213.154.224.1 213.154.224.17

Next I need to tell `NSD` that it *should* listen on my *external* network interfaces. 
On debian/Ubuntu this is handled in the file `/etc/default/nsd`. On my system it looks like this
(only the relevant parts are shown):

    # Flags to pass to nsd on startup
    flags="-u nsd -a 80.127.17.126 -a 2001:7b8:2ff:c8::2"

This tells `NSD` to listen on my external IPv4 and IPv6 addresses. Setting up and requesting 
a domain name goes beyond this article.

# Restart the services
Basicly that was it... now BIND9 is *only* used on my internal network, and NSD is used
for the outside. Just the way I like it; just the way it should be.

Just restart the services and you should be done:

    /etc/init.d/nsd restart && /etc/init.d/bind9 restart

Check `/var/log/messages/` and `/var/log/daemon.log` for any errors you might get.

