Let me start by saying that the last time I have configured and managed a DNS server was sometime around 2008. In most circumstances you don’t need one. Virtually all domain name registrars offer to host your DNS for free and they usually do a reasonably good job at it.
Sometimes you have to gain greater control over it, I will not go into the details of why I choose to setup my own, but describe the setup (pretty simple task) plus configuration and management (a more involved task).
My needs are limited to maintain an authoritative DNS server for a few dozen domains with a small traffic footprint. Even if this setup is low stakes, I still need to remember that, should the DNS server be unavailable, the connected websites, emails etc. would also be unavailable.
Consequently I created a setup with a main and a secondary DNS server, both servers are running within two FreeBSD jails and with the two jails configured physically on two separate servers. In this way, should one of the physical servers have a malfunction, the DNS resolution would still work thanks to the second. To be fair it would take more than a simple malfunction to take down one of these servers, they all have redundant everything, but that’s beside the point.
Of course an even more reliable setup would be having more than two servers and located in separate and geographically disperse data centers. This kind of setup is overkill for my needs, but reasonable for some. In any event the configuration is identical either way as the two servers don’t need to be physically located in proximity and the number of secondary servers could be more than one, without changing anything here (beside the need to set them up).
I will not get into jail setup here, only bind within an existing jail configured with a publicly accessible IP. (actually two: one for the primary and one for the secondary DNS server).
For clarity during the installation we will use server antlia (10.1.0.3) as the primary and server aquila (10.2.0.5) as the secondary. Of course 10.x.x.x IP addresses are just used here as example, you will need to use 2 publicly accessible IP’s.
Bind installation could not be more straight forward:
# pkg install bind914
You will need to perform the installation into both jails.
The installation takes a few seconds and here is the message displayed at the end:
Message from bind914-9.14.9:
--
BIND requires configuration of rndc, including a "secret"
key. The easiest, and most secure way to configure rndc is
to run 'rndc-confgen -a' to generate the proper conf file,
with a new random key, and appropriate file permissions.
The /usr/local/etc/rc.d/named script will do that for you.
If using syslog to log the BIND9 activity, and using a
chroot'ed installation, you will need to tell syslog to install
a log socket in the BIND9 chroot by running:
# sysrc altlog_proglist+=named
And then restarting syslogd with: service syslogd restart
I will need to investigate the logging issue, as of now I’m not sure if i want bind to log via the syslog or not (I’m actually unsure what my alternatives are).
Next we will allow bind (the deamon is actually called “named”) to start
# sysrc named_enable="YES"
Last we can actually start it
# service named start
As per the message displayed once bind was installed, as it starts it will generate a “secret” key. In a primary <-> secondary environment this key needs to be identical. So we will need to copy the file “/usr/local/etc/namedb/rndc.key” over to the other server.
At this point our installation is listening on two ports: 53 (the DNS port) and 953 (the port used for primary <-> secondary communications and commands).
Without any modification it will listen on ‘localhost” exclusively. We will need to do a few things:
1. Open port 53 (both TCP and UDP) to the public.
2. Open port 953 (TCP) to allow communications between the primary and secondary bind server.
3. Configure bind.
Steps 1 and 2 are only necessary if you, like me, are using some kind of firewall and limiting traffic in to specific IPs, specific protocols and specific ports.
I will not get into firewall configurations here, all that we need to know is that incoming traffic on port 53 needs to be allowed for both UDP and TCP packets. This is required for a DNS server to “serve”. Incoming TCP traffic to Port 953 needs to be allowed for communication between the primary and the secondary server.
So let’s get to point 3: the configuration of bind.
Bind configuration files are stored under “/usr/local/etc/namedb/” (in FreeBSD). Let’s look at the contents of this directory:
# cd /usr/local/etc/namedb/
# ls -l
total 27
-rw-r--r-- 1 root wheel 1990 Jan 31 07:46 bind.keys
drwxr-xr-x 2 bind bind 2 Jan 31 07:46 dynamic
drwxr-xr-x 2 root wheel 5 Feb 25 16:19 master
-rw-r--r-- 1 root wheel 21693 Jan 31 07:46 named.conf
-rw-r--r-- 1 root wheel 21693 Jan 31 07:46 named.conf.sample
-rw-r--r-- 1 root wheel 3413 Jan 31 07:46 named.root
-rw-r--r-- 1 root wheel 868 Jan 31 07:46 rndc.conf.sample
-rw------- 1 bind wheel 100 Feb 25 16:27 rndc.key
drwxr-xr-x 2 bind bind 2 Jan 31 07:46 slave
drwxr-xr-x 2 bind bind 4 Feb 25 16:27 working
We will be concerned with only a small portion of the files and directories found here. First we will edit the named.conf file, later we will be working in the “dynamic” directory, where we will store the zones files of all the domains we want this server to be the “authority”. If you have not done it yet, copy the “rndc.key” file so that it is identical in both primary and secondary server.
We are not going to look at the entirety of the named.conf file, we will just not a few particular sections.
We need to tell Bind to listen to the public IP address that the jail is using, here are the relevant lines:
// If named is being used only as a local resolver, this is a safe default.
// For named to be accessible to the network, comment this option, specify
// the proper IP address, or delete this option.
listen-on { 127.0.0.1; };
// If you have IPv6 enabled on this system, uncomment this option for
// use as a local resolver. To give access to the network, specify
// an IPv6 address, or the keyword "any".
// listen-on-v6 { ::1; };
You see that there are only 1 directives here, the rest is all comments: “listen-on” the meaning is pretty obvious. The value is a straight forward semi colon separated list of values, eclipsed by curly brackets (and with a directive closing, semicolon at the end). So i will use 10.1.0.3 and the result will be:
listen-on { 127.0.0.1; 10.1.0.3; };
If you are using IP6 you can uncomment the “listen-on-v6” directive and populate the value.
Another thing that we need to do is allow the primary server to control the secondary, we do this by adding a ‘control’ section in the config file and by adding the “rndc.key”.
On the secondary server we add these directives “outside” of the “options” section.
include "/usr/local/etc/namedb/rndc.key";
controls {
inet 127.0.0.1 allow { localhost; } keys { "rndc-key"; };
inet ##SECONDARY_IP## allow { ##PRIMARY_IP##; } keys { "rndc-key"; };
};
Of course you will replace ##SECONDARY_IP## and ##PRIMARY_IP## with the proper IP addresses.
So at this point we should have two servers step, one functioning as primary and one as secondary. If you look through the ‘named.conf’ file you’ll see a who bunch of settings, mostly these are the default zones for the root server, in any event you don’t need to worry about it.
Here are a few useful commands to run:
named-checkconf /usr/local/etc/namedb/named.conf
This command will check the syntax of the named.conf file we just edited. If it return nothing, the syntax os correct.
rndc reload
Note that under certain conditions you might get an error “rndc: ‘reload’ failed: permission denied”, this is usually a permissions issue.
This command will reload the settings from the config file. It can also be run as:
rndc -s 10.2.0.5 reload
Which will force the save server to do the same. (we have not created any zones yet, so reloading the secondary server will not have any effect.
rndc status
Will provide some info about what’s going on with the server.
Finally:
named-checkzone domain.dom /usr/local/etc/namedb/dynamic/db.domain.dom
Is a command that allow you to verify that a newly created zone file has the correct syntax. Of course you’ll need to replace domain.dom with the domain the one is controlling and ‘/usr/local/etc/namedb/dynamic/db.domain.dom’ with the location of the zone file for that domain.
We are going to get into zones files in minute and we will be using ‘/usr/local/etc/namedb/dynamic/’ as the location to store all or zones, ultimately these zone files can be stored anywhere ‘bind’ can read them.
Rather than making this post very long i will keep the zone files info into a separate post.
After setting zones the next step will be setting up dnssec, which I also include init own post.