02- Bind 9.7.3 on CentOS 6.2

Introduction

These are the class notes and assignments to learn the basics of setting up DNS & BIND in a Linux environment.

All of the work in this exercise will be done on the CentOS 6.2 x86-64 virtual machine provided to the class. BIND is relatively common, so these instructions should work on other Linux machines with minor modifications.

We assume that all work is done on an isolated network like the one present in our classroom laboratory.

Good References:

Basic System configuration

To start, perform the basic configuration steps listed for system setup in the notes for a CentOS 6.2 system. For reference in this example, our system is

  • OS: CentOS 6.2 (x64)
  • Hostname: aurora.cosc.tu
  • IP Address: 10.0.2.2
  • Netmask: 255.255.255.0
  • Gateway: 10.0.2.254
  • User: seldon

These settings are correct for the instructor subnet in the classroom. When you build your system, be sure to change these as appropriate.

DNS server with BIND: The basics

The first step is always to verify that BIND is installed; run

[seldon@aurora ~]$ named -v
BIND 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.1

In the virtual machines provided to the class, you will find that the installed version should be a Red Had modified version of 9.7.3

Note that the BIND service is chrooted by default on some versions of CentOS (e.g. CentOS 5.5), so the directory structure in our VM and in this document might be slightly different than what you might see if you look for help online at other locations.

Namespaces

Namespaces can be considered as a directed graph of domains and hosts. You are familiar with the top level domains like .com and .org that live under the root domain ".". In our class, our laboratory is separated from the internet, so we will use ".tu" as our canonical top-level domain.

You have a great deal of flexibility in selecting and defining your namespace(s). In these notes, I will use "cosc.tu" as the primary top-level domain, and when I need a second example I will use "class.tu". Each team is free to select their own namespace(s) and structure. One option would be for each student on a team to select their own sub-namespace, like "alice.team1.tu", "bob.team1.tu" "chris.team1.tu" and so on; then they can name their hosts how they wish. You could instead develop a functional model, so if you are simulating the Acme corporation, you may want a subdomain "sales.acme.tu" but you may want your web presence to be simply "www.acme.tu".

image001

The Forward Zone

The forward zone is used to map human readable names to numerical IP addresses.

With the namespace structure of our class set, let us start to configure the DNS server to return the appropriate IP addresses whenever it is queried- our forward zone.

Start by create the zone file /var/named/db.cosc.tu. We can name this file anything we want, and even put it in any location that we want, but this is a canoncial location for a zone file, and naming the zone file after the domain will make subsequent administration simpler. This file should be created by root; if any authenticated user can make changes to your DNS records, well, that might be amusing. Briefly.

It should be noted that the CentOS 6.2 VM provided to the class has some pre-existing configuration files (in /var/named) and some samples (in /usr/share/doc/bind-9.7.3/sample); we shall not use any of these files.

We begin the file with the following directives

;
$TTL 5m
;
cosc.tu. IN SOA aurora.cosc.tu. seldon.cosc.tu. (
           1 ; Serial
           5m ; Refresh after 5 minutes
           3m ; Retry after 3 minutes
           30m ; Expire after 30 minutes
           5m ) ; Negative TTL of one week

This begins with a time-to-live directive. This will be supplied with any query response, and will let the requester know how long they may cache the results. On an Internet facing system, you probably want this larger- from a few hours up to a few days. In our lab environment, things are much more dynamic, with systems getting built and taken down all of the time, so it makes sense to use a much smaller value. This does result in more traffic to and from the server, but the sizes of our network are such that this should not be a concern.

Next is a record, called a start of authority record, or SOA. It must start in the left column with the namespace that is being configured; in this case it is "cosc.tu.". Notice the trailing dot- this is essential! Remember that the top level of the name space is just ".", so this is the way to tell BIND that this is the FQDN, rather than just an abbreviation.

The record continues with "IN" telling us that this is data for the Internet. All of the examples we will consider will be Internet data.

It continues with "SOA", telling us that this is a start of authority record. Only one SOA record can be in a file.

Next is the FQDN for the host that will act as the primary nameserver for the zone. In this case it is aurora.cosc.tu, and again we end the FQDN in the directive with a period to indicate that this is not an abbreviation.

After the name of the primary nameserver comes the email address of the person responsible for maintaining the zone. At first glance, it does not look like an email address, but the key here is that the first "@" in the email address is replaced by a ".". Thus, our example record states that the email address of the person responsible for the zone in seldon@cosc.tu.

The open parentheses lets us continue the directive on to subsequent lines. The remainder of the record is used primarily for the configuration of any slave nameservers that get their information from this one.

The serial number is just that- a serial number. You can set it to any integer value you want. When a slave nameserver checks the master for an update; if the serial number on the master is greater than the serial number on the slave, it will update its local data. There is no requirement that serial number be assigned consecutively- as long as the new data has a higher serial number that the old data, you are fine. Remember to actually do the update though- many students run into trouble with their DNS changes not propagating to their slaves, and forgetting to update the serial number is often the cause.

Next up is the refresh value; this determines how often a slave nameserver will query the master to see if it has the current data. What happens if the slave is unable to reach the master? Then it will try again after the retry interval.

Next we tell the slave how long it can hold on to the data on the assumption that it cannot reach the master. Last is the negative TTL; this is how long a slave should cache answers from the master that say that a particular name does not exist.

Note that the values in this example are tuned for our classroom laboratory environment. Data will update quickly, but will also time out quickly. Keep that in mind as you are setting up your systems. These are probably not suitable for a system meant to function on the wider Internet. Suggestions for more reasonable values can be found many places; you may want to start with

  • TTL- 3 hours
  • Refresh- 3 hours
  • Retry- 1 hour
  • Expire- 1 week
  • Negative cache- 1 hour

We conclude the zone configuration file with a number of additional records- name server records (NS), Address records (A), and alias records (CNAME).

;
; Name Servers
;
cosc.tu.   IN NS    aurora.cosc.tu.

;
; Address Records
;
localhost.cosc.tu.        IN A    127.0.0.1
aurora.cosc.tu.           IN A    10.0.2.2
capella.cosc.tu.          IN A    10.0.2.3
hesperus.cosc.tu.         IN A    10.0.2.4
nexon.cosc.tu.            IN A    10.0.2.5
pallas.cosc.tu.           IN A    10.0.2.6
tethys.cosc.tu.           IN A    10.0.2.7
osiris.cosc.tu.           IN A    10.0.2.8
inferno.cosc.tu.          IN A    10.0.2.9
backtrack.cosc.tu.        IN A    10.0.2.10
rhea.cosc.tu.             IN A    10.0.2.11
solaria.cosc.tu.          IN A    10.0.2.12
gw.cosc.tu.               IN A    10.0.2.254

;
; Aliases
;
dns.cosc.tu.     IN CNAME aurora.cosc.tu.

The nameserver records indicate which name servers are authoritative for this zone. Usually you want at least two hosts (what if one fails!). For now, since we are still setting up our first server, we only have one.

Next, the file sets up the host name records, or address records (A) for each host. These match the hostname on the left with the IP address on the right.

Finally, the file ends with a list of aliases records (CNAME). These are used when you want a multiple names to refer to the same IP address. This configuration file gives a second name (dns.cosc.tu) to the name server (aurora.cosc.tu).

The Reverse Zone

Now we set up the address to name mappings, this is called a reverse zone. Though our server (almost) knows how to return the IP address given a hostname, it does not know how to reverse the process. In fact, a completely separate configuration file is used for the reverse zone. In this example, we will create a reverse zone for the entire 10.0.2.0/24 subnet.

Using the same naming convention, we now create the file /var/named/db.10.0.2; in the following form:

$TTL 5m
;
2.0.10.in-addr.arpa. IN SOA aurora.cosc.tu. seldon.cosc.tu. (
           1 ; Serial
           5m ; Refresh after 5 minutes
           3m ; Retry after 3 minutes
           30m ; Expire after 30 minutes
           5m ) ; Negative TTL of one week

;
; Name Servers
;
2.0.10.in-addr.arpa.      IN NS aurora.cosc.tu.

;
; Address records
;
2.2.0.10.in-addr.arpa.    IN PTR   aurora.cosc.tu. 
3.2.0.10.in-addr.arpa.    IN PTR   capella.cosc.tu.
4.2.0.10.in-addr.arpa.    IN PTR   hesperus.cosc.tu.
5.2.0.10.in-addr.arpa.    IN PTR   nexon.cosc.tu.
6.2.0.10.in-addr.arpa.    IN PTR   pallas.cosc.tu.
7.2.0.10.in-addr.arpa.    IN PTR   tethys.cosc.tu. 
8.2.0.10.in-addr.arpa.    IN PTR   osiris.cosc.tu. 
9.2.0.10.in-addr.arpa.    IN PTR   inferno.cosc.tu
10.2.0.10.in-addr.arpa.   IN PTR   backtrack.cosc.tu.
11.2.0.10.in-addr.arpa.   IN PTR   rhea.cosc.tu.
12.2.0.10.in-addr.arpa.   IN PTR   solaria.cosc.tu.
254.2.0.10.in-addr.arpa.  IN PTR   gw.cosc.tu.

Like the forward zone, we have set the time to live to a short five minutes.

Next comes a start of authority record (SOA) with the same structure we saw for the forward zone. The difference here is we want the zone to named after the address space 10.0.2.0/24. This is what occurs in our file, though it may not be clear at first reading. To construct the name, take the IP range in octet form, reverse the numbers, and end with ".in-addr.arpa.". This convention is a leftover from the original (1980s) days of the Internet as it evolved from the Defence Advanced Research Project Agency (DARPA). If the subnet in question was 192.168.0.0/16, then we would use 168.192.in-addr.arpa and so on.

[My smart students are now asking a deep question- what if we want to create a lookup zone for a smaller address space- say 10.0.2.80/28 (10.0.2.80 – 10.0.2.95)? Yeah, we aren’t going to go there. This is possible, sort of, with a few hacks. Take a look at DNS & BIND by Liu & Albitz, pp. 215 ff.]

The values in the IN SOA record have already been explained, and follow the same convention; in the same way the required Internet nameserver (IN NS) record is as it was before.

The remaining records are Internet pointer (IN PTR) records. The left side is the IP address, written in the reversed ".in-addr.arpa" form, while the right side is the full domain name at that address.

These records should match the forward zone records. Though you can set up more than one host name to point to a single IP address, in the reverse zone there should be only one name for any single IP address.

Loopback

We should also handle name server lookups on the loopback address. Admittedly, this is not strictly necessary, as it can be handled by the host rather than by the DNS server. Still- why not be careful?

Create the file /var/named/db.127.0.0 as follows:

$TTL 5m
;

0.0.127.in-addr.arpa. IN SOA aurora.cosc.tu. seldon.cosc.tu. (
           1 ; Serial
           5m ; Refresh after 5 minutes
           3m ; Retry after 3 minutes
           30m ; Expire after 30 minutes
           5m ) ; Negative TTL of one week

;
0.0.127.in-addr.arpa. IN NS aurora.cosc.tu.

;
1.0.0.127.in-addr.arpa. IN PTR localhost
Root Hints

If we were connected to the Internet, we would also need a root hints file from http://www.internic.net/zones/named.root. An older version of this file is actually present on the VM provided to class. We will not even configure this feature.

named.conf

Finally, we set up the file /etc/named.conf, which configures the name server itself, rather than the individual zones. You may wish to keep a copy of the original file /etc/named.conf provided as part of the system’s initial installation. Using the file names chosen above, we create the file as follows.

// BIND Configuration File

options {
     directory "/var/named";
};

zone "cosc.tu" in {
     type master;
     file "db.cosc.tu";
};

zone "2.0.10.in-addr.arpa" in {
      type master;
      file "db.10.0.2";
};

zone "0.0.127.in-addr.arpa" in {
      type master;
      file "db.127.0.0";
};

If we wanted to configure the root hints file for an Internet accessible server, we would add

zone "." in {
     type hint;
     file "db.root.hints";
};

to the above, were the file db.root.hints is the root hints file we downloaded.

Running and Testing

To start your server, run

[root@shades etc]# /etc/init.d/named start

Be sure to correct any errors that appear! You should be sure to check the system log files as well (e.g. /var/log/messages), as not every error will be reported back to and through the initialization script.

Messages about the rndc key can be ignored for the moment; we will take care of them as we continue to configure the server.

As your first test, from the DNS server, run nslookup from the command line, specifying a host name that appears in your forward zone and the IP address of the name server:

[seldon@aurora ~]$ nslookup nexon.cosc.tu 10.0.2.2
Server:		10.0.2.2
Address:	10.0.2.2#53

Name:	nexon.cosc.tu
Address: 10.0.2.5

Next, check that the reverse zone is functioning by checking an IP address:

[seldon@aurora ~]$ nslookup 10.0.2.254 10.0.2.2
Server:		10.0.2.2
Address:	10.0.2.2#53

254.2.0.10.in-addr.arpa	name = gw.cosc.tu.

It would be convenient as we test our setup further if we did not have to manually specify the location of the DNS server each time. Recall how we set up the system in the first place, and go back and modify the network settings for the system so that it now uses itself for DNS; you can do this by editing /etc/sysconfig/network-scripts/ifcfg-eth0.

Check again that things are as they ought to be:

[seldon@aurora ~]$ nslookup 10.0.2.9
Server:		10.0.2.2
Address:	10.0.2.2#53

9.2.0.10.in-addr.arpa	name = inferno.cosc.tu.

[seldon@aurora ~]$ nslookup rhea
Server:		10.0.2.2
Address:	10.0.2.2#53

Name:	rhea.cosc.tu
Address: 10.0.2.11

Note that errors can sometimes be caught with these tests. Suppose for example, that you accidentally left off the tailing period in your reverse zone, so that you wrote

9.2.0.10.in-addr.arpa.    IN PTR   inferno.cosc.tu

instead of

9.2.0.10.in-addr.arpa.    IN PTR   inferno.cosc.tu.

Then your reverse zone lookups would give you incorrect results in the form

[seldon@aurora ~]$ nslookup 10.0.2.9
Server:		10.0.2.2
Address:	10.0.2.2#53

9.2.0.10.in-addr.arpa	name = inferno.cosc.tu.2.0.10.in-addr.arpa.

I can’t emphasize strongly enough how important it is to be thorough and careful, and to check your work regularly as you proceed. You cannot "zoom through" this in a hurry. Students have tried, oh they have tried. They usually finish a few hours after the folks who are slow, careful and thorough. Check your work after each step, and be critical- look for errors, instead of being happy that nothing seemed wrong.

To ensure the DNS server starts on boot, you can use the menu and navigate System → Administration → Services. Scroll through the list of services to named, and set it to enabled. This method also be used to start & stop the service. The command line equivalent of this tool is chkconfig; see man chkconfig for its use.
Screenshot-Service Configuration

Be sure to open a hole in your firewall to allow for the necessary traffic. DNS runs on UDP 53, with some traffic (e.g. zone transfers) on TCP 53. You can do this from the menu; navigate System → Administration → and Firewall.
Screenshot-Firewall Configuration

Reboot the system, and test that everything starts as it ought; check that you can use other systems to query the nameserver via the nslookup command. [This command is even available on Windows systems, on the command line.]

Setting up a slave nameserver

Why do we want to set up a second nameserver? Well, if the primary goes down and you have no backup, then you are having a bad day!

Start with a new CentOS machine, and configure its hostname and network connection appropriately. In this example, we give it the hostname "solaria.cosc.tu" and the IP address 10.0.2.12. Note that this name/IP combination is already included in DNS zone data for our master nameserver. We do need to modify that file though, to indicate that solaria.cosc.tu should be considered a nameserver for cosc.tu as well. Both the forward zone (in db.cosc.tu) and the reverse zone (in db.10.0.2) need to be updated.

For example, the nameserver section in db.cosc.tu should be updated to read

;
; Name Servers
;
cosc.tu.   IN NS    aurora.cosc.tu.
cosc.tu.   IN NS    solaria.cosc.tu.
The slave named.conf file

With the new system built and the appropriate entries made to our master DNS server, it is time to configure the slave.

First we create a new /etc/named.conf file as follows:

// BIND Configuration File

options {
       directory "/var/named/slaves";
};

zone "cosc.tu" in {
       type slave;
       file "bak.cosc.tu";
       masters {10.0.2.2; };
};

zone "2.0.10.in-addr.arpa" in {
       type slave;
       file "bak.10.0.2";
       masters {10.0.2.2; };
};

zone "0.0.127.in-addr.arpa" in {
       type master;
       file "db.127.0.0";
};

Notice that instead of "type master" they are set to "type slave". For each slave zone, the configuration specifies a set of masters for that zone.

Note however, that the server should still be the master for its own localhost; thus we create the file db.127.0.0 in the same fashion as we did for the master. Because we have set the directory to /var/named/slaves though, then that is the location that file should be kept.

Now when the name server starts on the slave, it will load the necessary data from the master. This way the authoritative data is kept in only one location. There is no need to manually ensure that the servers are in agreement.

Because the name server is going to be writing data, we need to make sure that the directories have the proper permissions set- this is the reason we use the directory /var/named/slaves, as it already has the proper permissions set.

Starting the slave

Start the slave server using /etc/init.d/named as we did for the master, being sure to check for errors, both at the command line and in the log file /var/log/messages.

Check that the zone files have been downloaded and now reside in the directory /var/named/slaves. The log file, /var/log/messages should contain lines like the following that indicate the transfer has occurred:

Jan 26 18:02:30 solaria named[2510]: zone cosc.tu/IN: Transfer started.
Jan 26 18:02:30 solaria named[2510]: transfer of 'cosc.tu/IN' from 10.0.2.2#53: 
connected using 10.0.2.12#58553
Jan 26 18:02:30 solaria named[2510]: zone cosc.tu/IN: transferred serial 1
Jan 26 18:02:30 solaria named[2510]: transfer of 'cosc.tu/IN' from 10.0.2.2#53: 
Transfer completed: 1 messages, 17 records, 439 bytes, 0.003 secs (146333 
bytes/sec)
Jan 26 18:02:31 solaria named[2510]: zone 2.0.10.in-addr.arpa/IN: Transfer 
started.
Jan 26 18:02:31 solaria named[2510]: transfer of '2.0.10.in-addr.arpa/IN' from 
10.0.2.2#53: connected using 10.0.2.12#44443
Jan 26 18:02:31 solaria named[2510]: zone 2.0.10.in-addr.arpa/IN: transferred 
serial 1
Jan 26 18:02:31 solaria named[2510]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.2#53: Transfer completed: 1 messages, 15 records, 419 bytes,
 0.001 secs (419000 bytes/sec)

You can take a look at the downloaded files. They have the same basic structure we saw before, but a number of shortcuts and abbreviations that we did not discuss are used.

[root@solaria ~]# cat /var/named/slaves/bak.10.0.2 
$ORIGIN .
$TTL 300	; 5 minutes
2.0.10.in-addr.arpa	IN SOA	aurora.cosc.tu. seldon.cosc.tu. (
				1          ; serial
				300        ; refresh (5 minutes)
				180        ; retry (3 minutes)
				1800       ; expire (30 minutes)
				300        ; minimum (5 minutes)
				)
			NS	aurora.cosc.tu.
$ORIGIN 2.0.10.in-addr.arpa.
10			PTR	backtrack.cosc.tu.
11			PTR	rhea.cosc.tu.
12			PTR	solaria.cosc.tu.
2			PTR	aurora.cosc.tu.
254			PTR	gw.cosc.tu.
3			PTR	capella.cosc.tu.
4			PTR	hesperus.cosc.tu.
5			PTR	nexon.cosc.tu.
6			PTR	pallas.cosc.tu.
7			PTR	tethys.cosc.tu.
8			PTR	osiris.cosc.tu.
9			PTR	inferno.cosc.tu.

As before, ensure that the DNS server starts on boot, is enabled, and that the firewall will allow traffic to and from the server.

Update each client to use both master and slave as their DNS server. Now the resolver file /etc/resolv.conf will have two entries, not just one.

Check that the slave nameserver is functioning. First try the nslookup command from a client that specifies the nameserver you want. Then shutdown the master and check that the client is still able to resolve both names and addresses.

Windows Weirdness

Suppose we specify 10.0.2.2 as the primary nameserver and 10.0.2.12 as the alternate nameserver on a Windows system- say a Vista system (though this happens on most other versions as well). Then, if the primary goes down, nslookup commands will fail:

C:\Users\seldon>nslookup solaria
DNS request timed out.
    timeout was 2 seconds.
Server:  UnKnown
Address:  10.0.2.2:53

DNS request timed out.
    timeout was 2 seconds.
*** Request to UnKnown timed-out

This does not mean that the slave nameserver has failed; indeed you can even use the alternate nameserver for pings:

C:\Users\seldon>ping solaria

Pinging solaria.cosc.tu [10.0.2.12] with 32 bytes of data:

Reply from 10.0.2.12: bytes=32 time<1ms TTL=64
Reply from 10.0.2.12: bytes=32 time<1ms TTL=64
Reply from 10.0.2.12: bytes=32 time<1ms TTL=64
Reply from 10.0.2.12: bytes=32 time<1ms TTL=64

Ping statistics for 10.0.2.12:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

If you reconfigure the windows system, so that the slave at 10.0.2.12 (which is up) is the primary nameserver, and the master at 10.0.2.2 (which is down) is the alternate nameserver, then nslookup will succeed:

C:\Users\seldon>nslookup solaria
Server:  solaria.cosc.tu
Address:  10.0.2.12:53

Name:    solaria.cosc.tu
Address:  10.0.2.12

Why does Windows behave this way? Shrug. Linux systems don’t, and nslookup commands will properly fall through to the alternate if the primary is down. It can trip you up as a student though, when you are first getting nameservers up and running.

Timeout Errors

Remember that we set the timing values for the slaves to be qute short. For example, with the given settings if your primary nameserver is down for more than 30 minutes, then your slave namersvers will no longer respond, as you will have exceeded the TTL, even if the slave is otherwise fully functional. On a Linux system, you would see errors of the form

seldon@nexon ~ $ nslookup solaria
;; Got SERVFAIL reply from 10.0.2.12, trying next server
;; connection timed out; no servers could be reached

while on a Windows system you may end up with

C:\Users\seldon>nslookup solaria
Server:  UnKnown
Address:  10.0.2.12:53

*** UnKnown can't find solaria: Server failed

These errors are not immediately fixed if the master starts, as it takes more time for the slave to freshen its data with the (now started) master.

Controlling the nameserver

The tool rndc can be used to control the state of a nameserver- either located locally or on another server. If you were smart and have been paying attention, you will have noticed some unusual warnings as the nameserver was configured; if you ask the initialization script for the status of the nameserver, you are presented with a warning about rndc:

[root@aurora ~]# /etc/init.d/named status
rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
named (pid  2701) is running...

We will now solve these problems and correctly configure rndc.

We start by running the tool rndc-confgen, and storing the results in the file rndcconf

[root@aurora ~]# rndc-confgen > rndconf

Taking a look at the contents of this file, we are presented with something like the following:

# Start of rndc.conf
key "rndc-key" {
	algorithm hmac-md5;
	secret "WTAS7hhNlqAVvQiLN8JNHA==";
};

options {
	default-key "rndc-key";
	default-server 127.0.0.1;
	default-port 953;
};
# End of rndc.conf

# Use with the following in named.conf, adjusting the allow list as needed:
# key "rndc-key" {
# 	algorithm hmac-md5;
# 	secret "WTAS7hhNlqAVvQiLN8JNHA==";
# };
# 
# controls {
# 	inet 127.0.0.1 port 953
# 		allow { 127.0.0.1; } keys { "rndc-key"; };
# };
# End of named.conf

When rndc is used, it authenticates to BIND via the use of a pre-shared secret; this is one of the purposes of the rndc-confgen script. It has generated a pre-shared secret for us and moreover provided the different components that can simply be copied into the proper files.

We do not need to create the file rndc.conf. Instead we start by creating the file /etc/rndc.key with the contents

key "rndc-key" {
	algorithm hmac-md5;
	secret "WTAS7hhNlqAVvQiLN8JNHA==";
};

Now if this file is world readable, then, well it is not much good as a shared "secret" is it? The whole point of a "secret" is that we aren’t going to tell everyone right? Well, take a look at the defaults…

[root@aurora ~]# ls -l /etc/rndc.key 
-rw-r--r--. 1 root root 77 Jan 27 08:32 /etc/rndc.key

Not so secret. Still, a little change, and we should be good to go

[root@aurora ~]# chmod o-r /etc/rndc.key 
[root@aurora ~]# ls -l /etc/rndc.key 
-rw-r-----. 1 root root 77 Jan 27 08:32 /etc/rndc.key

Good to go? Well, not so much. On the one hand, now only root can read the rndc.key file, but the thing is the named server also has to be able to read it. We handle this by changing the group owner of the file to the group named, which includes the user named which runs the named service. [At least they were consistent with their nameds, umm names.]

[root@aurora ~]# chown root:named /etc/rndc.key 
[root@aurora ~]# ls -l /etc/rndc.key 
-rw-r-----. 1 root named 77 Jan 27 08:32 /etc/rndc.key

Next we update the primary configuration file /etc/named.conf. In the case of the master, the file now becomes

// BIND Configuration File

options {
     directory "/var/named";
};

zone "cosc.tu" in {
     type master;
     file "db.cosc.tu";
};

zone "2.0.10.in-addr.arpa" in {
      type master;
      file "db.10.0.2";
};

zone "0.0.127.in-addr.arpa" in {
      type master;
      file "db.127.0.0";
};

include "/etc/rndc.key";
 
controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1; } keys { "rndc-key"; };
};

The changes occur at the bottom of the file. First is the inclusion of the key file we just created. That key file defines the key "rndc-key" with the secret "WTAS7hhNlqAVvQiLN8JNHA==". The second change is the controls section; this tells the server to open up TCP port 953 on localhost (127.0.0.1) only and to require that connections to that control provide the key named "rndc-key".

At this point you can re-start the named server, and there should no longer be any mention of rndc warnings.

[root@aurora ~]# /etc/init.d/named status
version: 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.1
CPUs found: 1
worker threads: 1
number of zones: 19
debug level: 0
xfers running: 0
xfers deferred: 0
soa queries in progress: 0
query logging is OFF
recursive clients: 0/0/1000
tcp clients: 0/100
server is up and running
named (pid  2950) is running...

The modification of the named.conf file for a slave server is done in precisely the same fashion.

Oh yes, one more thing. You did remember to delete that file rndcconf right? That file contains our secret, and it better not be world readable, or all of this work is for naught.

With rndc correctly configured, we can query and control the behavior of the named server. We can run rndc status to get the same status for the server we saw above.

Updating Zone Data

Suppose we add a new host to our zone files- say we add the line

proclas.cosc.tu.	  IN A    10.0.2.13

to our db.cosc.tu file for the forward zone, and the corresponding line

13.2.0.10.in-addr.arpa.   IN PTR   proclas.cosc.tu.

to the file db.10.0.2 for the reverse zone. How do we tell the BIND to reload the configuration? We could use the startup scripts in /etc/init.d, but it is simpler to just use rndc and tell the server to reload its data:

[root@aurora ~]# nslookup proclas
Server:		10.0.2.2
Address:	10.0.2.2#53

** server can't find proclas: NXDOMAIN

[root@aurora ~]# nslookup 10.0.2.13
Server:		10.0.2.2
Address:	10.0.2.2#53

** server can't find 13.2.0.10.in-addr.arpa.: NXDOMAIN

[root@aurora ~]# rndc reload
server reload successful
[root@aurora ~]# nslookup proclas
Server:		10.0.2.2
Address:	10.0.2.2#53

Name:	proclas.cosc.tu
Address: 10.0.2.13

[root@aurora ~]# nslookup 10.0.2.13
Server:		10.0.2.2
Address:	10.0.2.2#53

13.2.0.10.in-addr.arpa	name = proclas.cosc.tu.

What happens on the slave? Provided we updated the serial number (don’t forget!) the slaves will be notified by the master that new zone files are available. Now the slave does not necessarily immediately download the new zone data, as the slave determines when that should be scheduled. However because we are using such aggressive timing, this happens almost immediately. Here are the logs (/var/log/messages) for the master:

Jan 27 09:33:14 aurora named[3614]: received control channel command 'reload'
Jan 27 09:33:14 aurora named[3614]: loading configuration from '/etc/named.conf'
Jan 27 09:33:14 aurora named[3614]: using default UDP/IPv4 port range: 
[1024, 65535]
Jan 27 09:33:14 aurora named[3614]: using default UDP/IPv6 port range: 
[1024, 65535]
Jan 27 09:33:14 aurora named[3614]: reloading configuration succeeded
Jan 27 09:33:14 aurora named[3614]: reloading zones succeeded
Jan 27 09:33:14 aurora named[3614]: zone 2.0.10.in-addr.arpa/IN: loaded 
serial 4
Jan 27 09:33:14 aurora named[3614]: zone cosc.tu/IN: loaded serial 4
Jan 27 09:33:14 aurora named[3614]: zone 2.0.10.in-addr.arpa/IN: sending 
notifies (serial 4)
Jan 27 09:33:14 aurora named[3614]: zone cosc.tu/IN: sending notifies
(serial 4)
Jan 27 09:33:14 aurora named[3614]: client 10.0.2.12#33574: transfer of 
'2.0.10.in-addr.arpa/IN': AXFR-style IXFR started
Jan 27 09:33:14 aurora named[3614]: client 10.0.2.12#33574: transfer of 
'2.0.10.in-addr.arpa/IN': AXFR-style IXFR ended
Jan 27 09:33:14 aurora named[3614]: client 10.0.2.12#49592: transfer of 
'cosc.tu/IN': AXFR-style IXFR started
Jan 27 09:33:14 aurora named[3614]: client 10.0.2.12#49592: transfer of 
'cosc.tu/IN': AXFR-style IXFR ended

You can see that the reload took place at 9:33:14, two notifies (one for the changed forward zone and one for the changed reverse zone) took place almost immediately thereafter, and the zone transfers right after that. The slave’s logs show the same process from that perspective:

Jan 27 09:33:14 solaria named[3241]: client 10.0.2.2#56868: received notify 
for zone '2.0.10.in-addr.arpa'
Jan 27 09:33:14 solaria named[3241]: zone 2.0.10.in-addr.arpa/IN: Transfer 
started.
Jan 27 09:33:14 solaria named[3241]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.2#53: connected using 10.0.2.12#33574
Jan 27 09:33:14 solaria named[3241]: zone 2.0.10.in-addr.arpa/IN: transferred 
serial 4
Jan 27 09:33:14 solaria named[3241]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.2#53: Transfer completed: 1 messages, 18 records, 483 bytes, 
0.001 secs (483000 bytes/sec)
Jan 27 09:33:14 solaria named[3241]: zone 2.0.10.in-addr.arpa/IN: sending 
notifies (serial 4)
Jan 27 09:33:14 solaria named[3241]: client 10.0.2.2#11154: received notify 
for zone 'cosc.tu'
Jan 27 09:33:14 solaria named[3241]: zone cosc.tu/IN: Transfer started.
Jan 27 09:33:14 solaria named[3241]: transfer of 'cosc.tu/IN' from 
10.0.2.2#53: connected using 10.0.2.12#49592
Jan 27 09:33:14 solaria named[3241]: zone cosc.tu/IN: transferred serial 4
Jan 27 09:33:14 solaria named[3241]: transfer of 'cosc.tu/IN' from 
10.0.2.2#53: Transfer completed: 1 messages, 20 records, 501 bytes, 0.002 
secs (250500 bytes/sec)
Jan 27 09:33:14 solaria named[3241]: zone cosc.tu/IN: sending notifies 
(serial 4)

Setting up forwarders

On the internet, if the name server is unable to answer a query it sends the request on to one of the root nameservers, and gets its results. In our lab, we don’t have access to the Internet. Suppose that team 1 and team 2 each set up their own nameservers. How do we let team 1 query the nameserver for team 2 whenever it is given a name from team 2? One answer is to use a forwarder.

Suppose that team 1 is using the namespace .team1.tu, while team 2 is using the namespace .acme.tu. We also suppose that the nameserver for team 2 is located at 10.0.4.77. Then in the named.conf file for team 1, we add the lines:

zone "acme.tu" in {
         type forward;
         forwarders {10.0.4.77; };
};

Now when a machine that is using the team 1 DNS server is asked for an address from team 2- say http://www.acme.tu- that request will be forwarded to the nameserver 10.0.4.77 maintained by team 2, and the nameserver for team 1 will cache the reply and send the result back to the requestor.

Exercises- Set Up

Build your own CentOS based DNS server. Include records for the server, a slave server (to be built), a windows machine, and the class gateway (10.0.x.254).

Set up a slave server. Verify that the slave server is able to perform the zone transfer to get its records.

Set up the server, the slave, and a windows machine to use your DNS server. Verify that they work. Verify that the master can be shut down and that the slave will still serve data.

Common DNS commands

nslookup

For each example, run the command & understand the output. [Use windows and/or linux versions.]

  • nslookup “hostname”
  • nslookup “IP_address”
  • nslookup -type=ns “yourdomain.”
  • nslookup “hostname” “IP_address_of_other_server”

Run nslookup with no arguments to get the nslookup shell. Run each of these commands from within the nslookup shell. [Use the linux version.]

seldon@nexon ~ $ nslookup
> set all
Default server: 10.0.2.2
Address: 10.0.2.2#53
Default server: 10.0.2.12
Address: 10.0.2.12#53

Set options:
  novc			nodebug		nod2
  search		recurse
  timeout = 0		retry = 3	port = 53
  querytype = A       	class = IN
  srchlist = cosc.tu

This shows the nslookup options currently set. Options include

  • [no]vc- Use UDP (no) or TCP (yes).
  • [no]debug- Hmmm- can we guess what this option is?
  • [no]d2- Debugging at level 2.
  • [no]search- when on, add the domain name if the hostname does not end with a .
  • [no]recurse- default is to use recursive queries

The Windows equivalent is similar; here is the output from a Windows 8 command prompt:

Microsoft Windows [Version 6.2.9200]
(c) 2012 Microsoft Corporation. All rights reserved.

C:\Users\Harry Seldon>nslookup
Default Server:  aurora.cosc.tu
Address:  10.0.2.2

> set all
Default Server:  aurora.cosc.tu
Address:  10.0.2.2

Set options:
  nodebug
  defname
  search
  recurse
  nod2
  novc
  noignoretc
  port=53
  type=A+AAAA
  class=IN
  timeout=2
  retry=1
  root=A.ROOT-SERVERS.NET.
  domain=cosc.tu
  MSxfr
  IXFRversion=1
  srchlist=cosc.tu

>

From within the nslookup shell, you can get information about a host by simply giving the name like the following:

seldon@nexon ~ $ nslookup
> solaria
Server:		10.0.2.2
Address:	10.0.2.2#53

Name:	solaria.cosc.tu
Address: 10.0.2.12

Do so. Do the same with an IP address, e.g.

C:\Users\Harry Seldon>nslookup
Default Server:  aurora.cosc.tu
Address:  10.0.2.2

> 10.0.2.7
Server:  aurora.cosc.tu
Address:  10.0.2.2

Name:    tethys.cosc.tu
Address:  10.0.2.7
dig

Another important command to be comfortable using is dig. Unlike nslookup, this is not available by default on Windows systems. However it is available as part of the BIND package for Windows available at ISC; I will make a copy available on the lab share.

It is simplest to use when your resolv.conf uses the nameserver you want to test. Try

seldon@nexon ~ $ dig -x 10.0.2.5

; <> DiG 9.7.3 <> -x 10.0.2.5
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31868
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;5.2.0.10.in-addr.arpa.		IN	PTR

;; ANSWER SECTION:
5.2.0.10.in-addr.arpa.	300	IN	PTR	nexon.cosc.tu.

;; AUTHORITY SECTION:
2.0.10.in-addr.arpa.	300	IN	NS	aurora.cosc.tu.
2.0.10.in-addr.arpa.	300	IN	NS	solaria.cosc.tu.

;; ADDITIONAL SECTION:
aurora.cosc.tu.		300	IN	A	10.0.2.2
solaria.cosc.tu.	300	IN	A	10.0.2.12

;; Query time: 2 msec
;; SERVER: 10.0.2.2#53(10.0.2.2)
;; WHEN: Sun Jan 27 13:17:47 2013
;; MSG SIZE  rcvd: 141

We performed a full reverse lookup on this address; note that we got quite a bit more data than simply the hostname that lives at 10.0.2.5.

We can also try a forward query; here is an example using the Windows version of the tool on a Windows 8 command prompt

C:\Users\Harry Seldon\Desktop\BIND>dig rhea.cosc.tu

; <> DiG 9.9.2-P1 <> rhea.cosc.tu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55398
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;rhea.cosc.tu.                  IN      A

;; ANSWER SECTION:
rhea.cosc.tu.           300     IN      A       10.0.2.11

;; AUTHORITY SECTION:
cosc.tu.                300     IN      NS      aurora.cosc.tu.
cosc.tu.                300     IN      NS      solaria.cosc.tu.

;; ADDITIONAL SECTION:
aurora.cosc.tu.         300     IN      A       10.0.2.2
solaria.cosc.tu.        300     IN      A       10.0.2.12

;; Query time: 0 msec
;; SERVER: 10.0.2.2#53(10.0.2.2)
;; WHEN: Sun Jan 27 13:20:08 2013
;; MSG SIZE  rcvd: 132

The Linux version of the tool returns the same data.

It is possible to use dig to pull the entire zone from a host, and you don’t even need to use it as your nameserver. [Hmmm. How could this be handy in a live-fire exercise?] Here is a Backtrack host (getting its IP from DHCP and with no name server) finding out all there is to know about the cosc.tu namespace:

root@bt:~# dig @10.0.2.2 cosc.tu axfr

; <> DiG 9.7.0-P1 <> @10.0.2.2 cosc.tu axfr
; (1 server found)
;; global options: +cmd
cosc.tu.		300	IN	SOA	aurora.cosc.tu. seldon.cosc.tu. 4 300 180 1800 300
cosc.tu.		300	IN	NS	aurora.cosc.tu.
cosc.tu.		300	IN	NS	solaria.cosc.tu.
aurora.cosc.tu.		300	IN	A	10.0.2.2
backtrack.cosc.tu.	300	IN	A	10.0.2.10
capella.cosc.tu.	300	IN	A	10.0.2.3
dns.cosc.tu.		300	IN	CNAME	aurora.cosc.tu.
gw.cosc.tu.		300	IN	A	10.0.2.254
hesperus.cosc.tu.	300	IN	A	10.0.2.4
inferno.cosc.tu.	300	IN	A	10.0.2.9
localhost.cosc.tu.	300	IN	A	127.0.0.1
nexon.cosc.tu.		300	IN	A	10.0.2.5
osiris.cosc.tu.		300	IN	A	10.0.2.8
pallas.cosc.tu.		300	IN	A	10.0.2.6
pallena.cosc.tu.	300	IN	A	10.0.2.14
proclas.cosc.tu.	300	IN	A	10.0.2.13
rhea.cosc.tu.		300	IN	A	10.0.2.11
solaria.cosc.tu.	300	IN	A	10.0.2.12
tethys.cosc.tu.		300	IN	A	10.0.2.7
cosc.tu.		300	IN	SOA	aurora.cosc.tu. seldon.cosc.tu. 4 300 180 1800 300
;; Query time: 24 msec
;; SERVER: 10.0.2.2#53(10.0.2.2)
;; WHEN: Sun Jan 27 13:26:04 2013
;; XFR size: 20 records (messages 1, bytes 501)

From this, we see that we have enumerated the entire network! We did so by asking the DNS server for a full zone transfer.

There is some nice (old) documentation for dig at http://www.madboa.com/geek/dig/

Security

Zone Transfers

Why is allowing a zone transfer a bad idea?

Suppose that we want the master name server to only allow zone transfers to the slave, which we have set at 10.0.2.12. Then in the zone section of /etc/named.conf we add the allow-transfer directive, and specify a semicolon denumerated list of allowable addresses that can request a zone transfer.

Adding this to our existing file, we end up with a named.conf file for the master like

// BIND Configuration File

options {
     directory "/var/named";
};

zone "cosc.tu" in {
     type master;
     file "db.cosc.tu";
     allow-transfer {10.0.2.12;} ;
};

zone "2.0.10.in-addr.arpa" in {
      type master;
      file "db.10.0.2";
      allow-transfer {10.0.2.12;} ;
};

zone "0.0.127.in-addr.arpa" in {
      type master;
      file "db.127.0.0";
};

include "/etc/rndc.key";
 
controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1; } keys { "rndc-key"; };
};

Once this is implemented, our zone transfer request from the attacker’s Backtrack box will fail:

root@bt:~# dig @10.0.2.2 cosc.tu axfr

; <> DiG 9.7.0-P1 <> @10.0.2.2 cosc.tu axfr
; (1 server found)
;; global options: +cmd
; Transfer failed.

The slave should not be transferring its zone to anyone, so we secure it:

options {
	directory "/var/named/slaves";
};

zone "cosc.tu" in {
	type slave;
	file "bak.cosc.tu";
	masters {10.0.2.2; };
        allow-transfer{ none; };
};

zone "2.0.10.in-addr.arpa" in {
	type slave;
	file "bak.10.0.2";
	masters {10.0.2.2; };
        allow-transfer{ none; };
};

zone "0.0.127.in-addr.arpa" in {
	type master;
	file "db.127.0.0";
};

include "/etc/rndc.key";
 
controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1; } keys { "rndc-key"; };
};
  1. Rohan Vazarkar
    February 5, 2013 at 5:38 pm

    Loopback configuration file specifies an email address that is inconsistent from other configuration files

  2. Alec Thorne
    February 5, 2013 at 5:38 pm

    Within the “Reverse Zone” section, the last line is missing a “.”

    254.2.0.10.in-addr.arpa. IN PTR gw.cosc.tu

    Should be:
    254.2.0.10.in-addr.arpa. IN PTR gw.cosc.tu.

  1. No trackbacks yet.

Leave a comment