An Ubuntu DNS Server
Sunday, August 2nd, 2009I’ve built DNS servers on Centos before, but never on Ubuntu. Given my recent networking upheavals, however, as documented here in recent posts, the need to have a DNS server running on a laptop running Ubuntu was pretty clear. So here’s how I went about configuring it.
First, you’ll need the relevant software which, in Ubuntu, is called bind9 and not just ‘bind’. You can install that using the Synaptic Package Manager if you like the GUI way of doing things or via the command line if you’re that way inclined: sudo aptitude install bind9 will do the deed well enough.
Creating the Zone Records
Next, you now have to start editing configuration files. There are three of them: the general one (called named.conf.local) which says what the other two are called, and then the two specific ones that set up the details of the DNS zones for which the DNS server you’re configuring is going to be “authoritive”. (Just to confuse things right off the bat, named.conf.local is simply an include file for the file which really does all the heavy lifting, which is just named.conf. In other words, named.conf calls named.conf.local -so you’re supposed to put all your local configuration information in the “local” file, not straight into the main conf file.)
Anyway, to begin with, we edit the named.conf.local file:
sudo gedit /etc/bind/named.conf.local
And now you type in the following:
zone "dizwell.home" {
type master;
file "/etc/bind/zones/dizwell.home.db";
};
zone "43.42.10.in-addr.arpa" {
type master;
file "/etc/bind/zones/rev.43.42.10.in-addr.arpa";
};
That, of course, is specific to me and my situation. What I’m saying here is that my new DNS server is going to be authorative (the “master” server) for resolving ‘dizwell.home’ addresses. That’s the name of my home network -so The Other Half’s machine is called ariadne.dizwell.home and mine is called heracles.dizwell.home -and when “ariadne” needs to know the IP address of “heracles”, it’s this DNS server that will be the authorative way of finding out. The bit in there that reads “file … dizwell.home.db” simply says ‘a file called dizwell.home.db exists in which the details of host names and their IP addresses can be found’. That doesn’t actually exist yet, of course, but I will be creating it shortly. Turning machine names into their underlying IP addresses is called forward names lookup, and thus that soon-to-be created file will be the configuration file for the “forward zone” of my new DNS server.
The other job of a DNS server is to do what’s called reverse names lookups. That is, whilst I think most people understand the need to turn ‘google.com’ into an IP address 74.125.45.100, it’s actually also necessary to be able to do it the other way around -turning an address into a name. The second zone record is setting up the ability of my new DNS server to do this: it’s saying that a file called /etc/bind/zones/rev.43.42.10.in-addr.arpa exists which will contain the necessary information to allow reverse lookups to happen. Again, that file doesn’t actually exist as yet, but I’m here saying that it’s about to. The curious name for this zone and its configuration file, by the way, simply arises from the fact that -as I described in my last post- my home network uses IP addresses in the 10.42.43.x range. If you reverse the order of those IP octets, you get x.43.42.10 -and we simply miss off the ‘x’ bit at the start.
Once you’ve gotten the contents right (and don’t miss out the semi-colon that ends each line!) save your new configuration file.
Configuring the Forward Zone Records
Our master configuration file now says that two zone configuration files exist. Therefore, we’d better create them before we go any further. To start with, I’ll create the ‘forward zone’ configuration file. The relevant commands are:
sudo mkdir /etc/bind/zones sudo gedit /etc/bind/zones/dizwell.home.db
And then you type in all this:
$TTL 10800 dizwell.home. IN SOA cerberus.dizwell.home. hjr@dizwell.com. ( 20090802 ; serial 7200 ; refresh 7200 ; retry 1814400 ; expiry 10800 ; ttl ) @ NS cerberus cerberus A 10.42.43.1 heracles A 10.42.43.2 ariadne A 10.42.43.3
It’s a lot of gobbledygook, I suppose, but if you take it bit by bit, it actually makes sense! Firstly, it’s establishing a Start Of Authority record for the dizwell.home domain that has a Time To Live of 10800 seconds (though that would only be relevant if I went on to set up slave DNS servers, since the TTL tells the slave how long its copy of the record should be considered valid before it has to go back to the master and get a fresh copy. Since I’m only creating the master server in the first place, as I say, the TTL is a bit redundant!) The SOA record simply states that the machine called “cerberus.dizwell.home” is going to be my DNS server, and that its administrator can be emailed at hjr@dizwell.com, which happens to be my real email address. Note, however, that all three of the names specified end with a fullstop (or period, if you prefer). My domain isn’t specified as dizwell.home but dizwell.home. and the machine name isn’t just cerberus.dizwell.home but cerberus.dizwell.home. Even my email address ends in a fullstop here, which it doesn’t in real life of course. The trailing fullstops are very easy to miss, but fatal if you do! They’re very necessary to make things work properly (what they actually do is to say ‘I am the definitive names server for this zone, the root of the zone, so don’t bother going elsewhere for your lookups’.
After that, the SOA contains a lot of stuff which isn’t strictly necessary for a small home DNS server: they are a series of numbers which specify how often slave DNS servers refresh their data from master DNS servers, how often a slave should wait before retrying a failed attempt to refresh their data from a master and so on. Given that I am only going to have one master DNS server, you can see why I say this stuff is, for me, unnecessary. But the serial entry is actually very important: it can be any number you like, provided it doesn’t contain more digits than you see in my example here. I’ve gone for a simple date stamp. The idea is that you increment this number every time you alter the Zone Record. If I ever add details of another PC on my network, for example, to the end of the file, I must remember to increment the serial number. The reason is simply that this number creates a way of establish ‘legitimacy’ in complex DNS setups (if a slave had a higher serial number than a master server, for example, it would suggest something very odd is going on that needs fixing… slaves are supposed to be copies of their masters, not more recently-updated!) -and even in simple DNS setups, it lets anyone see which is the ‘correct’ version of the file (i.e., the one with the most recent -that is, largest- serial number)
Next comes a line which simply states that the machine called ‘cerberus’ is actually the Name Server for this domain. If you have more than one name server, you list them each in turn here, but I don’t.
Finally comes the all-important bit that is the very reason for me setting up this DNS server in the first place: the mapping of machine names to IP addresses in what are known as A Records. I’ve just put a few records here to provide enough material to test with -if you really only had 3 machines in your domain, I’d suggest not using a DNS server at all and just sticking with editing /etc/hosts.
Configuring the Reverse Zone Records
With that zone file created and saved, it’s time to get the reverse names zone sorted. Again, start by creating a new, blank text file:
sudo gedit /etc/bind/zones/rev.43.42.10.in-addr.arpa
And then paste these contents in:
$TTL 10800 @ IN SOA cerberus.dizwell.home. hjr.dizwell.com. ( 20090802 ; serial 7200 ; refresh 7200 ; retry 1814400 ; expire 10800 ; ttl )
@ cerberusNS .dizwell.home.
1 PTR cerberus.dizwell.home. 2 PTR heracles.dizwell.home. 3 PTR ariadne.dizwell.home.
I hope that by now you recognise most of the top part of this stuff, at least. It’s the usual timeouts, retries and refresh directives. The new stuff is in the four last lines, which are PoinTeR records: IP address 10.42.43.1 points to a machine name of cerberus.dizwell.home. Similarly, the IP address 10.42.43.2 points to a machine name of heracles.dizwell.home. The first three octets of the IP address are not mentioned explicitly, because the Zone Record file itself has a name of rev.43.42.10, and it is assumed that the octets mentioned in the file name apply to all the pointer records contained within the file. Again, note that all the domain names mentioned in the file end in a fullstop/period.
Other Bits and Pieces
My new DNS server is almost fully configured as a result of creating those two zone configuration files. There’s just one thing missing: my server is authorative for my home network only. If ariadne wants to find heracles, no problem: my DNS server will be able to supply the relevant IP addresses. But if ariadne wants to talk to google.com, there is most definitely going to be a problem, since my DNS server hasn’t got a clue on how to resolve anything outside its particular zones. For that, we need to configure the address of another DNS server, provided by my ISP, which is ‘authorative’ (sort-of) for the Internet and all its glories. That’s done by configuring the /etc/bind/named.conf.options file (as sudo). You add the following ’stanza’ to that file:
forwarders {
139.130.4.4;
203.50.2.71;
};
Those happen to be the IP addresses for the DNS servers hosted by Bigpond.com (who is my ISP): if you use a different ISP, different DNS addresses are required. That stanza, by the way, needs to go inside the main “options {…}” stanza, not just appended to the end of the file (in other words, edit and replace the bit in the default file at about line 13 – 15, don’t just bolt on extra lines to the end of the default file).
With that done, we now just need to re-start bind so that it picks up on all our new configuration work:
sudo /etc/init.d/bind9 restart
You should see the domain name service first being stopped and then being re-started, with [OK] messages displayed for each. If you get a [fail] on the restart, issue this command to see if the logs are reporting any configuration errors: tail -f /var/log/syslog. Hopefully, you’ll see something obvious there (such as “/etc/bind/named.conf.local: 34: unknown option…”, which will give you the clue you need to go and re-edit the appropriate configuration file (in this case, at around about line 34). If you got the [OK] message, though, your new DNS server is up and running!
Testing it all
Has it worked? Well, you need to move away from the server now and find yourself a desktop PC, since they are the clients who will be making use of the DNS service being provided by the server. I’m using my heracles PC, so let me start by seeing if I can find the cerberus box by name:
hjr@heracles:~$ ping cerberus ping: unknown host cerberus
And it’s a dismal failure, simply because my PC doesn’t yet know there’s a DNS server it can use to resolve that name. So, I need to tell it to use the new DNS Server. On Ubuntu, that is done by right-clicking the Network Manager icon in the top-right panel and selecting the Edit Connections option. Pick your connection and click the Edit button. Select the IPv4 Settings tab and then type in the IP address of the new DNS Server in the relevant spot:
Notice too that I’ve specified a ’search domain’ here of “dizwell.home”. That basically means, if you ask to resolve the hostname “cerberus”, the PC will know to talk to the DNS Server for records relating to ‘cerberus.dizwell.home’, without the domain name bit having to be specified explicitly.
When you’re done, stop your network (right-click the Network Manager icon again, and uncheck the ‘Enable Networking’ option) and then re-start it (do the same as before, only now check the ‘Enable Networking’ option). Now for the acid test:
hjr@heracles:~$ ping cerberus PING cerberus.dizwell.home (10.42.43.1) 56(84) bytes of data. 64 bytes from cerberus.dizwell.home (10.42.43.1): icmp_seq=1 ttl=64 time=0.957 ms 64 bytes from cerberus.dizwell.home (10.42.43.1): icmp_seq=2 ttl=64 time=1.06 ms 64 bytes from cerberus.dizwell.home (10.42.43.1): icmp_seq=3 ttl=64 time=1.07 ms 64 bytes from cerberus.dizwell.home (10.42.43.1): icmp_seq=4 ttl=64 time=1.04 ms
Success!
In my last post, I ended things with every PC on the network being setup to know the address of Bigpond’s DNS servers -which at least meant connections to the Internet worked, but did mean even humble PC-to-PC communications potentially involved a DNS call to Bigpond! Now only one machine on my network needs to know anything about Bigpond’s DNS servers -the one that’s actually using the Wireless Broadband adapter. And that’s exactly the way things should be!
