Bind DNS Server in Homelab With Split View

One of the most undervalued infrastructure components in my opinion is DNS. A lot of services / components rely upon DNS and if DNS is mis-configured, not available, slow function or somehting else doing that shouldn’t be happening, it can lead to performance and other strange problems. In my homelab I’m running BIND DNS. One of the main reasons I choose BIND is the option to use Views. Views are making sure if I’m internally connected (e.g. WiFi @  Home) I get an internel IP as a response and if I’m externally connected, I get my public IP as response. My installation is based upon Debian 7, I won’t go into much details about this installation, since it is pretty straight forward. Make sure you use an static IP, don’t set your DNS to the server IP yet :) and I prefer to only install SSH, so I can start with a nice clean machine. First let’s install the BIND packages.

aptitude install bind9

Al the configuration files are stored in /etc/bind, so let’s go to this directory and start with creating a forwarder, so all DNS request can go through this DNS server. We will protect this forwarder by an ACL, so only internal cliënts can use this DNS server for relaying.

cd /etc/bind
nano named.conf.options

At the top of this file, before options, create the ACL, I use RFC1918, cause my subnets will vary a lot in my lab.

acl "trusted" {
        192.168.0.0/16;
        172.16.0.0/12;
        10.0.0.0/8;
        localhost;
        localnets;
};

In this example localnets, isn’t necessary assuming the server is already part of one the above listed subnets. Next we will add the lines, which enables the forwarding, these should be placed within the options placeholder.

forwarders {
       8.8.8.8;
       8.8.4.4;
};

allow-query { any; };
allow-recursion { trusted; };
allow-query-cache { trusted; };

That’s it for the forwarding. Now let’s create our own domain. First let’s disable the default configuration.

nano named.conf

and comment the line include “/etc/bind/named.conf.default-zones”;

//include "/etc/bind/named.conf.default-zones";

Open up named.conf.local

nano named.conf.local

and add the following lines.

view "local" {
        match-clients {10/8; 172.16/12; 192.168/16;};
        zone "lab.breekeenbeen.nl" {
                type master;
                file "/etc/bind/zones/lab.breekeenbeen.nl.local";
        };

        zone "11.10.10.in-addr.arpa" {
                type master;
                file "/etc/bind/zones/rev.11.10.10.in-addr.arpa";
        };

};

Here we declare a view, which will only listen to RFC1918 (local) addresses, we than create two different zones, one for forward look-ups and second for reverse look-ups. In his case the domain/zone is “lab.breekeenbeen.nl” and the IP range for the reverse look-up is 10.10.11.*. As you can see, we are pointing to two different files, these files will actually contain the hostnames. So let’s create and edit them. I added the .local for recognitizion that it will contain local addresses.

mkdir zones
touch zones/lab.breekeenbeen.nl.local
touch zones/rev.11.10.10.in-addr.arpa

Let’s start with the forward look-up table.

nano zones/lab.breekeenbeen.nl.local
$TTL 3D
@       IN      SOA     ns1.lab.breekeenbeen.nl. root.localhost(
        2014092201      ; serial number
        28800           ; refresh (i.e. 3h)
        3600            ; retry (i.e. 15M)
        604800          ; expire (i.e. 3W12h)
        38400           ; minimum (i.e. 2h20M)
);

@                       IN      NS      ns1.lab.breekeenbeen.nl.

dnsserver               IN      A       10.10.11.3;
ns1                     IN      A       10.10.11.3;

The above sample is pretty basic, remember everytime you make changes and commit them, you need to change the serial number, I use year-month-date-follow-up as a serialnumber. Every host can be added on a new line, here is one host “dnsserver” which will result in IP 10.10.11.3, the FQDN of this host is dnsserver.lab.breekeenbeen.nl. Restart the DNS server and check if it works with nslookup.

root@dnsserver:/etc/bind# nslookup
> server 10.10.11.3
Default server: 10.10.11.3
Address: 10.10.11.3#53
> dnsserver
Server:         10.10.11.3
Address:        10.10.11.3#53

Name:   dnsserver.lab.breekeenbeen.nl
Address: 10.10.11.3

If it doesn’t work, you can check on errors in the syslog.

tail /var/log/syslog

That’s it, now the last thing to configure is the reverse look-up.

nano zones/rev.11.10.10.in-addr.arpa
$TTL 3D
@       IN      SOA     ns1.lab.breekeenbeen.nl. root.localhost(
        2014092201      ; serial number
        28800           ; refresh (i.e. 3h)
        3600            ; retry (i.e. 15M)
        604800          ; expire (i.e. 3W12h)
        38400           ; minimum (i.e. 2h20M)
);

                        IN      NS      ns1.lab.breekeenbeen.nl.

3                       IN      PTR     dnsserver.lab.breekeenbeen.nl.

Restart the DNS server and check if the reverse look-up works.

root@dnsserver:/etc/bind# nslookup
> server 10.10.11.3
Default server: 10.10.11.3
Address: 10.10.11.3#53
> set type=PTR
> 10.10.11.3
Server:         10.10.11.3
Address:        10.10.11.3#53

3.11.10.10.in-addr.arpa name = dnsserver.lab.breekeenbeen.nl.

Now we can do exactly the same for the external look-ups. We just add another view for the external requests.

nano named.conf.local

view "external" {
        match-clients { any; };

        zone "lab.breekeenbeen.nl" {
                type master;
                file "/etc/bind/zones/lab.breekeenbeen.nl.external";
        };
};

It depends on your configuration if you need/want a reverse lookup for external requests. If you run an e-mail server for example it would be wise to set-up a reverse lookup zone. For now I leave the reverse look-up out of it, but it is exactly the same as described above. Like we did for internal, we create the external look-up file and fill it with the appropriate configuration. To speed things up, we just copy the file.

cp zones/lab.breekeenbeen.nl.local zones/lab.breekeenbeen.nl.external
nano zones/lab.breekeenbeen.nl.external

$TTL 3D
@       IN      SOA     ns1.lab.breekeenbeen.nl. root.localhost(
        2014092201      ; serial number
        28800           ; refresh (i.e. 3h)
        3600            ; retry (i.e. 15M)
        604800          ; expire (i.e. 3W12h)
        38400           ; minimum (i.e. 2h20M)
);

@                       IN      NS      ns1.lab.breekeenbeen.nl.

*                       IN      A       8.8.8.8

dnsserver               IN      A       8.8.8.8

As you can see, you can also add an asterisk (*) to answer the public IP on all public requests ending on .lab.breekeenbeen.nl. Before we can test the external request, you have to make a firewall rule which NAT all the UDP/53 request, to this server. Make sure if you’re going to test the configuration, that you do this from an external client and your DNS server set to your public IP. If you also want other requests for your domain coming to you through other DNS servers, you have to make a so called glue record at your domain hosting provider.

Rob Maas
Rob Maas
Technical Challanger at ON2IT

If it is broken, fix it! If it ain’t broken, make it better!

Related