Bind9 DNS on a Rasberry Pi

Bind9 DNS on a Rasberry Pi

December 29, 2017 Off By kex

Recently I’ve found a need for more consistency in my homelab (no more hostfile hacks) so I decided to repurpose a Raspberry Pi as a DNS server. I could’ve used a virtual machine but that would require me to have my main PC on all the time, or use a VPS which costs money so this was a good compromise.

DNS Overview

DNS(Domain Name Service) is a way for machines to be accessible via a hostname rather than an IP address, this makes it far easier to remember which machine you’re connected to as it’s much easier to remember a name than an IP address (especially IPv6 addresses).

The service itself uses port 53 on UDP, the process consists of a single request followed by a single reply. Although DNS uses UDP it can also require TCP, as if the response size exceeds 512kb it will change to TCP, some actions such as zone transfers will also default to TCP. DNS is comprised of records, records are just pointers to a certain location. There are different types of records that work like so:

  • A – The most common type of records, this consists of a network location (such as google.com) and an IP address (such as 8.8.8.8) where the network location resolves to the IP address.
  • CNAME – Another common record, this is where one network location points to another (such as gewgle.com redirecting to google.com).
  • MX – This record indicates where the mail server for a domain is located.
  • TXT – Used to insert any text, these are flexible and can be used for almost anything.
  • Grouping of these records is called a ‘zone’, the above were examples of forward lookup zones (where we resolve names), we also have reverse lookup zones. Reverse Lookup Zones are used to resolve IP Addresses to DNS names using PTR records, these are effectively A records in reverse.

    Pi Setup

    To start with we will do the normal setup of a raspberry pi, download raspbian/pidora onto your SD card and install it into the pi, plug it into the router and turn it on.

    Next we need to find which IP address the Pi has gotten from the router, we can use nmap for this. As the machine boots into DHCP by default we can safely assume it will be on the same range as any other machine that connects to your router, run the following command on a different machine after your Pi has had a minute to boot (if you’re using a different IP range on your local network please change it accordingly):

    nmap -v -sn 192.168.1.0/24

    After a while the scan will finish and display your results, look for a result like so:

    Expected results of the nmap scan

    Next we need to SSH to the Pi, using PuTTY connect to that IP on port 22:
    An example of how to connect to the Pi over SSH

    You should see a login prompt appear, if not then it’s probably the wrong IP in which case you should see if the nmap scan found any other IP addresses that you don’t recognise and try those.

    The default login credentials for a Pi are:

    Username: pi
    Password: raspberry

    If you’re like me then you’ll just want to be able to login as root, just run this command after you’ve logged in and set your own root password:

    sudo passwd root

    The enter the root password you want to use. After that you’ll need to open the /etc/ssh/sshd_config file in an editor, and ensure the following value exists:
    PermitRootLogin yes

    Now you should be able to reboot the Pi and login as root at the prompt.

    We will probably want to update everything on the Pi before we continue, for Raspbian run apt-get update followed by apt upgrade, for pidora run dnf upgrade then reboot the Pi.

    Now we will want to give the Pi a static IP address, this is so that the other machines on the network can be sure that their DNS lookups will always be served from the same address. The easiest way to do this is to use the command ip a and make a note of the inet value, and route -n which will give us our Gateway.

    For raspian you’ll need to open the /etc/dhcpcd.conf file and add the values you discovered above in this context:

    interface eth0
    
    static ip_address=
    static routers=
    static domain_name_servers=
    

    For pidora you’ll need to edit the file that exists in /etc/sysconfig/network-scripts/ifcfg-emX

    If you run systemctl restart networking after making these changes you should now get the same IP address every time.

    Installing and Configuring Bind

    For the following steps I will be using raspbian, however the steps should be exactly the same for both OS’s, I will also be setting up DNS for a zone called ‘wxdis’, just replace that with whatever you want your domain to be.

    Install the following packages:
    apt-get install bind9 bind9utils dnsutils

    Hopefully that worked, now we can get to configuring the server. First of all we need to create our zones, a zone in DNS represents a ‘district’ or portion of the domain space. To start with we will create a directory for our zone configurations to live in mkdir /etc/bind/zones/, you can use any directory for this but I like to keep it all together. We will define our zones within the /etc/bind/named.conf.local file, open it in a text editor and add something like the following:

        zone "wxdis" IN {
                type master;
                file "/etc/bind/zones/db.wxdis";
          };
        zone "1.168.192.in-addr.arpa" {
                type master;
                file "/etc/bind/zones/1.168.192.in-addr.arpa";
          };
    
    

    Again – it doesn’t matter where you store them or what the zone is called, we just need to ensure that we have a forward and reverse zone specified.

    Now we need to define our A records for the zone we created, open the /etc/bind/zones/db.wxdis and add something like the following:

    $TTL 7200
    @               IN SOA pi.wxdis. hostmaster.wxdis. (
                            2017122800 ; serial
                            8H ; refresh
                            4H ; retry
                            4W ; expire
                            1D ; minimum
                    )
    wxdis.                  IN NS pi.wxdis.
    
    localhost               IN A 127.0.0.1
    router                  IN A 192.168.1.1
    pi                      IN A 192.168.1.147
    desktop1                IN A 192.168.1.32
    desktop2                IN A 192.168.1.110
    vm-docker               IN A 192.168.1.111
    

    This is where you add your A records, anywhere after the SOA declaration, do not put spaces in front of the records as you will encounter problems. You can also add stuff like MX records here, the syntax is the same unless it is a CNAME, for a CNAME you must add a ‘.’ after the target name like a reverse lookup (if this isn’t clear look below for where to place the ‘.’. The ‘pi’ record is the IP address of the Pi that is running this bind service.

    Now we need to create our reverse lookup zone, this is useful if you need to find the DNS record of a machine on the network by its IP address, but can be skipped. Open the /etc/bind/zones/1.168.192.in-addr.arpa file in an editor and add something like the following:

    $TTL 7200
    @       IN SOA pi.wxdis. hostmaster.wxdis. (
                    2017122800 ; serial
                    8H ; refresh
                    4H ; retry
                    4W ; expire
                    1D ; minimum
            )
               IN NS pi.wxdis.
    1          IN PTR router.wxdis.
    147        IN PTR pi.wxdis.
    32         IN PTR desktop1.wxdis.
    110        IN PTR desktop2.wxdis.
    111        IN PTR vm-docker.wxdis.
    

    So here we told the server that ‘if someone performs a lookup against these IP addreses, then tell them the corresponding DNS name’.

    Now we have a problem in that if the DNS record doesn’t exist the server will tell the user there is nothing there, the easy way to solve this is to tell the server to delegate the requests to another server if it cannot find the records in it’s own ‘cache’. To do this we need to open the file /etc/bind/named.conf.options, uncomment the ‘forwarders’ section and make it look like the following:

             forwarders {
                    8.8.8.8;
                    8.8.4.4;
             };
    

    This makes it so that any query the server cannot match will be thrown off to one of the Google DNS servers in the hope it can be resolved there, this is useful as some devices only let you specify one DNS server.

    Testing Our Config

    We should be done now, be aware that this setup is not secure in any way and under no circumstances should be internet facing. To test if everything worked run:

    systemctl restart bind9 && sleep 5 && systemctl status bind9 -l

    If all is green then that means we got the configuration right, now we can check to see if the named (the named daemon is what bind runs as) process is listening on the correct ports:

    netstat -tulpn | grep named

    You should see something like this:

    Shows if the daemon is listening correctly or not

    The example above shows us that the daemon is listening on port 53 which is the correct DNS port. Now we can attempt to test the server from another machine, I’ll be using Windows desktop. To start with open a CMD and start nslookup. At the prompt enter

    server

    . Now you can try to reach any of the IP addresses you added in your zone configuration by typing either the DNS name or IP address, you should see something like the following if it’s working correctly:

    The expected results of an nslookup against the bind server

    You should also check to ensure it can correctly forward requests to the 8.8.8.8 address, just query any web address against your Pi and see if it produces the expected results.

    If you do not see the expected results, try opening a telnet session to port 53 of your Pi and see if it lets you connect, it may be being blocked by firewalld on the Pi or by Windows Firewall.

    After we’ve verified it’s working then we can change our Windows configuration to use the Pi for DNS resolution (on Linux machines change it either in the nic configuration file or in resolv.conf) to do this open Control Panel > Network and Sharing Center > Change adaptor settings > Right click on your nic and select properties > highlight Internet Protocol Version 4 > Properties. Here you can set the DNS servers and network configuration for your machine, here are mine as an example:

    Example configuration for a nic within Windows

    At this point it’s worth checking you can reach the zones we configured by pinging them or using nslookup along with checking we can access websites on the internet. At this point we are done with our configuration, in the next section we will go over how to add/remove records from the bind configuration.