2015-02 Bind 9.7.2 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: acheron.cosc.tu
  • IP Address: 10.0.2.100
  • Netmask: 255.255.255.0
  • Gateway: 10.0.2.254
  • User: zathras

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

Installing Software on CentOS 6.2

Linux systems use a variety of automated package management solutions to install, configure, and remove software. On CentOS systems, this tool is called yum. By default, that system will go online to obtain the latest version of each package and its dependencies when called upon to install software. Since we are working in a closed laboratory (and don’t want to update the system), we’ll need to modify that behavior.

The locations yum uses to select software are called repositories, and they are configured in the directory /etc/yum.repos.d. The online repositories are configured in the file CentOS-Base.repo, while local sources, including the install disc, are configured in CentOS-Media.repo. To install from the install discs, we need to make two changes to that file; we need to set the enabled flag to 1, and we provide the proper path to the media in the baseurl directive. The final result should look like

# CentOS-Media.repo
#
# This repo is used to mount the default locations for a CDROM / DVD on
#  CentOS-6.  You can use this repo and yum to install items directly off the
#  DVD ISO that we release.
#
# To use this repo, put in your DVD and use it with the other repos too:
#  yum --enablerepo=c6-media [command]
#  
# or for ONLY the media repo, do this:
#
#  yum --disablerepo=\* --enablerepo=c6-media [command]
 
[c6-media]
name=CentOS-$releasever - Media
baseurl=file:///media/CentOS_6.2_Final
gpgcheck=1
enabled=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6

If you are using the base image provided in class, then you do not need to make any changes to this file, as I have already made them for you. (See, I can be nice!) The default CentOS 6.2 file has the media disabled, and leaves a couple of incorrect values for baseurl.

Before we can use yum to install software though, we also need to make sure that the virtual machine’s optical drive points to the installation disc. From the menu of VMWare Workstation, select VM → Settings. From the Hardware tab, select CD/DVD, and be sure that the device is "connected" and that it points to an ISO Image file for CentOS; those image files are online on the lab server. You should end up with something like
Set Up CD

With the install disc mounted, and the changes made to the yum configuration, the installation is a simple one-line command to install BIND.

[root@acheron yum.repos.d]# yum --disablerepo=\* --enablerepo=c6-media install 
bind

Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package bind.x86_64 32:9.7.3-8.P3.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==============================================================================
 Package      Arch           Version                   Repository        Size
==============================================================================
Installing:
 bind         x86_64         32:9.7.3-8.P3.el6         c6-media         3.9 M

Transaction Summary
==============================================================================
Install       1 Package(s)

Total download size: 3.9 M
Installed size: 7.0 M
Is this ok [y/N]: y
Downloading Packages:
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : 32:bind-9.7.3-8.P3.el6.x86_64                              1/1 

Installed:
  bind.x86_64 32:9.7.3-8.P3.el6                                                 

Complete!

Notice that we used the command structure described in CentOS-Media.repo which disabled the online repositories. If we did not do this, then on our closed network yum would have to time out waiting for the network to fail to respond, something which we would like to avoid.

DNS server with BIND: The basics

Now that we have installed BIND, check that it was properly installed:

[root@acheron yum.repos.d]# named -v
BIND 9.7.3-P3-RedHat-9.7.3-8.P3.el6
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 installing BIND has also installed 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 acheron.cosc.tu. zathras.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 acheron.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 zathras@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, then the slave will update its local data. There is no requirement that serial numbers 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    acheron.cosc.tu.

;
; Address Records
;
localhost.cosc.tu.        IN A    127.0.0.1
acheron.cosc.tu.          IN A    10.0.2.100
damocles.cosc.tu.         IN A    10.0.2.101
achilles.cosc.tu.         IN A    10.0.2.3
agamemnon.cosc.tu.        IN A    10.0.2.4
agrippa.cosc.tu.          IN A    10.0.2.5
alexander.cosc.tu.        IN A    10.0.2.6
anubis.cosc.tu.           IN A    10.0.2.7
apollo.cosc.tu.           IN A    10.0.2.8
cadmus.cosc.tu.           IN A    10.0.2.9
cerberus.cosc.tu.         IN A    10.0.2.10
charon.cosc.tu.           IN A    10.0.2.11
churchill.cosc.tu.        IN A    10.0.2.12
delphi.cosc.tu.           IN A    10.0.2.13
excalibur.cosc.tu.        IN A    10.0.2.14
furies.cosc.tu.           IN A    10.0.2.15
heracles.cosc.tu.         IN A    10.0.2.16
hermes.cosc.tu.           IN A    10.0.2.17
hydra.cosc.tu.            IN A    10.0.2.18
juno.cosc.tu.             IN A    10.0.2.19
medusa.cosc.tu.           IN A    10.0.2.20
nemesis.cosc.tu.          IN A    10.0.2.21
nimrod.cosc.tu.           IN A    10.0.2.22
olympic.cosc.tu.          IN A    10.0.2.23
orion.cosc.tu.            IN A    10.0.2.24
persephone.cosc.tu.       IN A    10.0.2.25
pollux.cosc.tu.           IN A    10.0.2.26
roanoke.cosc.tu.          IN A    10.0.2.27
talos.cosc.tu.            IN A    10.0.2.28
theseus.cosc.tu.          IN A    10.0.2.29
vesta.cosc.tu.            IN A    10.0.2.30
zeus.cosc.tu.             IN A    10.0.2.31
gw.cosc.tu.               IN A    10.0.2.254

;
; Aliases
;
dns.cosc.tu.              IN CNAME acheron.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 (acheron.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 acheron.cosc.tu. zathras.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 acheron.cosc.tu.

;
; Address Records
;
100.2.0.10.in-addr.arpa.          IN PTR  acheron.cosc.tu.
101.2.0.10.in-addr.arpa.          IN PTR  damocles.cosc.tu.
3.2.0.10.in-addr.arpa.            IN PTR  achilles.cosc.tu.
4.2.0.10.in-addr.arpa.            IN PTR  agamemnon.cosc.tu.
5.2.0.10.in-addr.arpa.            IN PTR  agrippa.cosc.tu.
6.2.0.10.in-addr.arpa.            IN PTR  alexander.cosc.tu.
7.2.0.10.in-addr.arpa.            IN PTR  anubis.cosc.tu.
8.2.0.10.in-addr.arpa.            IN PTR  apollo.cosc.tu.
9.2.0.10.in-addr.arpa.            IN PTR  cadmus.cosc.tu.
10.2.0.10.in-addr.arpa.           IN PTR  cerberus.cosc.tu.
11.2.0.10.in-addr.arpa.           IN PTR  charon.cosc.tu.
12.2.0.10.in-addr.arpa.           IN PTR  churchill.cosc.tu.
13.2.0.10.in-addr.arpa.           IN PTR  delphi.cosc.tu.
14.2.0.10.in-addr.arpa.           IN PTR  excalibur.cosc.tu.
15.2.0.10.in-addr.arpa.           IN PTR  furies.cosc.tu.
16.2.0.10.in-addr.arpa.           IN PTR  heracles.cosc.tu.
17.2.0.10.in-addr.arpa.           IN PTR  hermes.cosc.tu.
18.2.0.10.in-addr.arpa.           IN PTR  hydra.cosc.tu.
19.2.0.10.in-addr.arpa.           IN PTR  juno.cosc.tu.
20.2.0.10.in-addr.arpa.           IN PTR  medusa.cosc.tu.
21.2.0.10.in-addr.arpa.           IN PTR  nemesis.cosc.tu.
22.2.0.10.in-addr.arpa.           IN PTR  nimrod.cosc.tu.
23.2.0.10.in-addr.arpa.           IN PTR  olympic.cosc.tu.
24.2.0.10.in-addr.arpa.           IN PTR  orion.cosc.tu.
25.2.0.10.in-addr.arpa.           IN PTR  persephone.cosc.tu.
26.2.0.10.in-addr.arpa.           IN PTR  pollux.cosc.tu.
27.2.0.10.in-addr.arpa.           IN PTR  roanoke.cosc.tu.
28.2.0.10.in-addr.arpa.           IN PTR  talos.cosc.tu.
29.2.0.10.in-addr.arpa.           IN PTR  theseus.cosc.tu.
30.2.0.10.in-addr.arpa.           IN PTR  vesta.cosc.tu.
31.2.0.10.in-addr.arpa.           IN PTR  zeus.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 Defense 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. Similarly, 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.

Scripting

Now for any reasonably sized domain, like the ones that we are going to see in our exercises, the number of hosts becomes quite large. Typing them all in the forward zone is a pain, but then needing to do almost the same thing again, without making any typographical errors is just an accident waiting to happen.

Here is a perfect chance to learn a bit of scripting. Suppose that you already have written the forward zone as it is above, with more that 30 hosts. Let’s just copy the address records to another file, and call it forward.txt. It is just the work of a moment to craft a Python script that will turn this into the corresponding reverse zone. Consider

#!/usr/bin/python

input_file_name = "forward.txt"
output_file_name = "reverse.txt"

infile = open(input_file_name,"r")
ofile = open(output_file_name,"w")

for line in infile:
   [host,protocol,record,ipaddr] = line.split()		
   [i1,i2,i3,i4] = ipaddr.split('.')               # Split ip address on dots
   
   revaddr = i4 + '.' + i3 + '.' + i2 + '.' + i1 + '.in-addr.arpa.'
   size = 34 - len(revaddr)
   padding = ' ' * size
   
   ofile.write(revaddr + padding + "IN PTR  " + host + '\n')

infile.close()
ofile.close()

If this is made executable, then it will open the file forward.txt, then split each line into four parts- the host name, the protocol ("IN") the record ("A") and the IP address. The IP address is then split on each octet.

The reversed IP address is built, ending with ".in-addr.arpa." as required. The size of the address string is determined, so we can pad it out so all of the columns are aligned, then the required information is written back out to another output.txt.

Easy! And much less work that doing this all by hand! You should get in the habit or writing your own scripts for simple tasks like this. There are any number of languages that are worth learning- Bash, Powershell, Windows batch scripts, Python, and Perl all come quickly to mind. Personally, I like Python, but you should learn at least a couple of these; this investment will pay dividends in time and effort throughout your career.

Loopback

Returning to the nameserver, 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 acheron.cosc.tu. zathras.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 acheron.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@acheron ~]# /etc/init.d/named start
Starting named:                                            [  OK  ]

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.

You should see a line in the log file like

Jan 25 11:57:03 acheron named[8347]: starting BIND 9.7.3-P3-RedHat-9.7.3-
8.P3.el6 -u named

showing that named was started. You should also find lines like

Jan 25 11:57:03 acheron named[8347]: zone 2.0.10.in-addr.arpa/IN: loaded 
serial 1
Jan 25 11:57:03 acheron named[8347]: zone 0.0.127.in-addr.arpa/IN: loaded 
serial 1
Jan 25 11:57:03 acheron named[8347]: zone cosc.tu/IN: loaded serial 1

that show that your three zones loaded succesfully. Finally, you should see

Jan 25 11:57:03 acheron named[8347]: running

telling you that the service is running.

You will see some messages about the rndc key file not being found; these 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:

[zathras@acheron ~]$ nslookup zeus.cosc.tu 10.0.2.100
Server:		10.0.2.100
Address:	10.0.2.100#53

Name:	zeus.cosc.tu
Address: 10.0.2.31

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

[zathras@acheron ~]$ nslookup 10.0.2.31 10.0.2.100
Server:		10.0.2.100
Address:	10.0.2.100#53

31.2.0.10.in-addr.arpa	name = zeus.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:

[zathras@acheron ~]$ nslookip nemesis
bash: nslookip: command not found
[zathras@acheron ~]$ nslookup juno
Server:		10.0.2.100
Address:	10.0.2.100#53

Name:	juno.cosc.tu
Address: 10.0.2.19

[zathras@acheron ~]$ nslookup 10.0.2.9
Server:		10.0.2.100
Address:	10.0.2.100#53

9.2.0.10.in-addr.arpa	name = cadmus.cosc

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

24.2.0.10.in-addr.arpa.           IN PTR  orion.cosc.tu

instead of

24.2.0.10.in-addr.arpa.           IN PTR  orion.cosc.tu.

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

[zathras@acheron ~]$ nslookup 10.0.2.24
Server:		10.0.2.100
Address:	10.0.2.100#53

24.2.0.10.in-addr.arpa	name = orion.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 "damocles.cosc.tu" and the IP address 10.0.2.101. 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 damocles.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    acheron.cosc.tu.
cosc.tu.   IN NS    damocles.cosc.tu.

while the corresponding section in db.10.0.2 becomes

;
; Name Servers
;
2.0.10.in-addr.arpa.              IN NS acheron.cosc.tu.
2.0.10.in-addr.arpa.              IN NS damocles.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 on the slave as follows:

// BIND Configuration File

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

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

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

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.

The log file, /var/log/messages should contain lines like the following that indicate the transfer has occurred:

Jan 25 12:33:03 damocles named[7859]: zone cosc.tu/IN: Transfer started.
Jan 25 12:33:03 damocles named[7859]: transfer of 'cosc.tu/IN' from 
10.0.2.100#53: connected using 10.0.2.101#35283
Jan 25 12:33:03 damocles named[7859]: zone cosc.tu/IN: transferred serial 1
Jan 25 12:33:03 damocles named[7859]: transfer of 'cosc.tu/IN' from 
10.0.2.100#53: Transfer completed: 1 messages, 38 records, 931 bytes, 
0.001 secs (931000 bytes/sec)
Jan 25 12:33:03 damocles named[7859]: zone cosc.tu/IN: sending notifies 
(serial 1)
Jan 25 12:33:04 damocles named[7859]: zone 2.0.10.in-addr.arpa/IN: Transfer 
started.
Jan 25 12:33:04 damocles named[7859]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.100#53: connected using 10.0.2.101#50428
Jan 25 12:33:04 damocles named[7859]: zone 2.0.10.in-addr.arpa/IN: 
transferred serial 1
Jan 25 12:33:04 damocles named[7859]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.100#53: Transfer completed: 1 messages, 35 records, 920 bytes, 
0.001 secs (920000 bytes/sec)

Check that the zone files have been downloaded and now reside in the directory /var/named/slaves. They have the same basic structure we saw before, but a number of shortcuts and abbreviations that we did not discuss are used.

[root@damocles ~]# cat /var/named/slaves/bak.cosc.tu 
$ORIGIN .
$TTL 300	; 5 minutes
cosc.tu			IN SOA	acheron.cosc.tu. zathras.cosc.tu. (
				1          ; serial
				300        ; refresh (5 minutes)
				180        ; retry (3 minutes)
				1800       ; expire (30 minutes)
				300        ; minimum (5 minutes)
				)
			NS	acheron.cosc.tu.
			NS	damocles.cosc.tu.
$ORIGIN cosc.tu.
acheron			A	10.0.2.100
achilles		A	10.0.2.3
agamemnon		A	10.0.2.4
agrippa			A	10.0.2.5
alexander		A	10.0.2.6
anubis			A	10.0.2.7
apollo			A	10.0.2.8
cadmus			A	10.0.2.9
cerberus		A	10.0.2.10
charon			A	10.0.2.11
churchill		A	10.0.2.12
damocles		A	10.0.2.101
delphi			A	10.0.2.13
dns			CNAME	acheron
excalibur		A	10.0.2.14
furies			A	10.0.2.15
gw			A	10.0.2.254
heracles		A	10.0.2.16
hermes			A	10.0.2.17
hydra			A	10.0.2.18
juno			A	10.0.2.19
localhost		A	127.0.0.1
medusa			A	10.0.2.20
nemesis			A	10.0.2.21
nimrod			A	10.0.2.22
olympic			A	10.0.2.23
orion			A	10.0.2.24
persephone		A	10.0.2.25
pollux			A	10.0.2.26
roanoke			A	10.0.2.27
talos			A	10.0.2.28
theseus			A	10.0.2.29
vesta			A	10.0.2.30
zeus			A	10.0.2.31
[root@damocles ~]# cat /var/named/slaves/bak.10.0.2 
$ORIGIN .
$TTL 300	; 5 minutes
2.0.10.in-addr.arpa	IN SOA	acheron.cosc.tu. zathras.cosc.tu. (
				1          ; serial
				300        ; refresh (5 minutes)
				180        ; retry (3 minutes)
				1800       ; expire (30 minutes)
				300        ; minimum (5 minutes)
				)
			NS	acheron.cosc.tu.
$ORIGIN 2.0.10.in-addr.arpa.
10			PTR	cerberus.cosc.tu.
100			PTR	acheron.cosc.tu.
101			PTR	damocles.cosc.tu.
11			PTR	charon.cosc.tu.
12			PTR	churchill.cosc.tu.
13			PTR	delphi.cosc.tu.
14			PTR	excalibur.cosc.tu.
15			PTR	furies.cosc.tu.
16			PTR	heracles.cosc.tu.
17			PTR	hermes.cosc.tu.
18			PTR	hydra.cosc.tu.
19			PTR	juno.cosc.tu.
20			PTR	medusa.cosc.tu.
21			PTR	nemesis.cosc.tu.
22			PTR	nimrod.cosc.tu.
23			PTR	olympic.cosc.tu.
24			PTR	orion.cosc.tu.
25			PTR	persephone.cosc.tu.
254			PTR	gw.cosc.tu.
26			PTR	pollux.cosc.tu.
27			PTR	roanoke.cosc.tu.
28			PTR	talos.cosc.tu.
29			PTR	theseus.cosc.tu.
3			PTR	achilles.cosc.tu.
30			PTR	vesta.cosc.tu.
31			PTR	zeus.cosc.tu.
4			PTR	agamemnon.cosc.tu.
5			PTR	agrippa.cosc.tu.
6			PTR	alexander.cosc.tu.
7			PTR	anubis.cosc.tu.
8			PTR	apollo.cosc.tu.
9			PTR	cadmus.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.100 as the primary nameserver and 10.0.2.101 as the alternate nameserver on a Windows system- say a Windows 7 (though I have seen this on most other versions as well). Then, if the primary goes down, nslookup commands will fail:

C:\Users\zathras>nslookup acheron
DNS request timed out.
    timeout was 2 seconds.
Server:  UnKnown
Address:  10.0.2.100

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

This does not mean that the slave nameserver has failed; you can check by directly querying the slave nameserver

C:\Users\zathras>nslookup acheron 10.0.2.101
Server:  damocles.cosc.tu
Address:  10.0.2.101

Name:    acheron.cosc.tu
Address:  10.0.2.100

The weirdness is that, even though nslookup will fail, you can still use the backup nameserver, for example for pings

C:\Users\zathras>ping acheron

Pinging acheron.cosc.tu [10.0.2.100] with 32 bytes of data:
Reply from 10.0.2.100: bytes=32 time<1ms TTL=64
Reply from 10.0.2.100: bytes=32 time<1ms TTL=64
Reply from 10.0.2.100: bytes=32 time<1ms TTL=64
Reply from 10.0.2.100: bytes=32 time<1ms TTL=64

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

Why does Windows behave this way? Beats me. This is why I labelled this behavior "weird". Linux systems don’t act this way, 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

zathras@acheron ~]$ nslookup damocles
;; Got SERVFAIL reply from 10.0.2.101, trying next server
;; connection timed out; no servers could be reached

while on a Windows system you may end up with

C:\Users\zathras>nslookup damocles
DNS request timed out.
    timeout was 2 seconds.
Server:  UnKnown
Address:  10.0.2.100

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

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@acheron ~]# /etc/init.d/named status
rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
named (pid  3744) 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@acheron ~]# 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 "FaL1U0WjL4nh3z898cY6fg==";
};

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 "FaL1U0WjL4nh3z898cY6fg==";
# };
# 
# 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 copied contents

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

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@acheron ~]# ls -l /etc/rndc.key 
-rw-r--r--. 1 root root 77 Jan 25 14:01 /etc/rndc.key

Not so secret, as it is world readable. Still, a little change, and we should be good to go

[root@acheron ~]# chmod o-r /etc/rndc.key 
[root@acheron ~]# ls -l /etc/rndc.key 
-rw-r-----. 1 root root 77 Jan 25 14:01 /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@acheron ~]# chown root:named /etc/rndc.key 
[root@acheron ~]# ls -l /etc/rndc.key 
-rw-r-----. 1 root named 77 Jan 25 14:01 /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 "FaL1U0WjL4nh3z898cY6fg==". 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@acheron ~]# /etc/init.d/named status
version: 9.7.3-P3-RedHat-9.7.3-8.P3.el6
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  3972) 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.

Logging queries

Suppose that you want to know more about the queries that your DNS server receives? Did you notice the line

query logging is OFF

when you ran rndc status? We can set that variable to on

[root@acheron ~]# rndc querylog on

and verify the change

[root@acheron ~]# rndc status
version: 9.7.3-P3-RedHat-9.7.3-8.P3.el6
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 ON
recursive clients: 0/0/1000
tcp clients: 0/100
server is up and running

Now every time the server receives a DNS request, the information will be stored in the logs

Jan 25 14:13:03 acheron named[3972]: received control channel command 
'querylog on'
Jan 25 14:13:03 acheron named[3972]: query logging is now on
Jan 25 14:13:18 acheron named[3972]: client 10.0.2.8#51734: query: 
100.2.0.10.in-addr.arpa IN PTR + (10.0.2.100)
Jan 25 14:13:18 acheron named[3972]: client 10.0.2.8#51735: query: 
cerberus.cosc.tu IN A + (10.0.2.100)
Jan 25 14:13:18 acheron named[3972]: client 10.0.2.8#51736: query: 
cerberus.cosc.tu IN AAAA + (10.0.2.100)
Jan 25 14:13:40 acheron named[3972]: client 10.0.2.101#22509: query: 
2.0.10.in-addr.arpa IN SOA -E (10.0.2.100)
Jan 25 14:14:24 acheron named[3972]: client 10.0.2.8#51737: query: 
100.2.0.10.in-addr.arpa IN PTR + (10.0.2.100)
Jan 25 14:14:24 acheron named[3972]: client 10.0.2.8#51738: query: 
orion.cosc.tu IN A + (10.0.2.100)
Jan 25 14:14:24 acheron named[3972]: client 10.0.2.8#51739: query: 
orion.cosc.tu IN AAAA + (10.0.2.100)

You can see how this would be helpful. Just remember that this will log all of the requests, and this could put a strain on resources on a busy server.

Updating Zone Data

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

clarkstown.cosc.tu.       IN A    10.0.2.32

to our db.cosc.tu file for the forward zone, updating the serial number in the file, and we add the corresponding line

32.2.0.in.in-addr.arpa.           IN PTR  clarkstown.cosc.tu.

to the file db.10.0.2 for the reverse zone and again updating the serial number in that file. 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@acheron ~]# nslookup clarkstown
Server:		10.0.2.100
Address:	10.0.2.100#53

** server can't find clarkstown: NXDOMAIN

[root@acheron ~]# nslookup 10.0.2.32
Server:		10.0.2.100
Address:	10.0.2.100#53

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

[root@acheron ~]# rndc reload
server reload successful

[root@acheron ~]# nslookup clarkstown
Server:		10.0.2.100
Address:	10.0.2.100#53

Name:	clarkstown.cosc.tu
Address: 10.0.2.32
[root@acheron ~]# nslookup 10.0.2.32
Server:		10.0.2.100
Address:	10.0.2.100#53

32.2.0.10.in-addr.arpa	name = clarkstown.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 25 16:15:21 acheron named[3972]: received control channel command 
'reload'
Jan 25 16:15:21 acheron named[3972]: loading configuration from 
'/etc/named.conf'
Jan 25 16:15:21 acheron named[3972]: using default UDP/IPv4 port 
range: [1024, 65535]
Jan 25 16:15:21 acheron named[3972]: using default UDP/IPv6 port 
range: [1024, 65535]
Jan 25 16:15:21 acheron named[3972]: reloading configuration succeeded
Jan 25 16:15:21 acheron named[3972]: reloading zones succeeded
Jan 25 16:15:21 acheron named[3972]: zone 2.0.10.in-addr.arpa/IN: 
loaded serial 3
Jan 25 16:15:21 acheron named[3972]: zone cosc.tu/IN: loaded serial 3
Jan 25 16:15:21 acheron named[3972]: zone 2.0.10.in-addr.arpa/IN: 
sending notifies (serial 3)
Jan 25 16:15:21 acheron named[3972]: zone cosc.tu/IN: sending notifies 
(serial 3)
Jan 25 16:15:21 acheron named[3972]: client 10.0.2.101#31567: query: 
2.0.10.in-addr.arpa IN SOA -E (10.0.2.100)
Jan 25 16:15:21 acheron named[3972]: client 10.0.2.101#42366: query: 
2.0.10.in-addr.arpa IN IXFR -T (10.0.2.100)
Jan 25 16:15:21 acheron named[3972]: client 10.0.2.101#42366: transfer 
of '2.0.10.in-addr.arpa/IN': AXFR-style IXFR started
Jan 25 16:15:21 acheron named[3972]: client 10.0.2.101#42366: transfer 
of '2.0.10.in-addr.arpa/IN': AXFR-style IXFR ended
Jan 25 16:15:22 acheron named[3972]: client 10.0.2.101#49703: transfer 
of 'cosc.tu/IN': AXFR-style IXFR started
Jan 25 16:15:22 acheron named[3972]: client 10.0.2.101#49703: transfer 
of 'cosc.tu/IN': AXFR-style IXFR ended

You can see that the reload took place at 16:5:21, 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 25 16:15:21 damocles named[9745]: client 10.0.2.100#2774: received 
notify for zone '2.0.10.in-addr.arpa'
Jan 25 16:15:21 damocles named[9745]: zone 2.0.10.in-addr.arpa/IN: 
Transfer started.
Jan 25 16:15:21 damocles named[9745]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.100#53: connected using 10.0.2.101#42366
Jan 25 16:15:21 damocles named[9745]: zone 2.0.10.in-addr.arpa/IN: 
transferred serial 3
Jan 25 16:15:21 damocles named[9745]: transfer of '2.0.10.in-addr.arpa/IN' 
from 10.0.2.100#53: Transfer completed: 1 messages, 37 records, 962 bytes, 
0.001 secs (962000 bytes/sec)
Jan 25 16:15:21 damocles named[9745]: zone 2.0.10.in-addr.arpa/IN: 
sending notifies (serial 3)
Jan 25 16:15:22 damocles named[9745]: client 10.0.2.100#18094: received 
notify for zone 'cosc.tu'
Jan 25 16:15:22 damocles named[9745]: zone cosc.tu/IN: Transfer started.
Jan 25 16:15:22 damocles named[9745]: transfer of 'cosc.tu/IN' from 
10.0.2.100#53: connected using 10.0.2.101#49703
Jan 25 16:15:22 damocles named[9745]: zone cosc.tu/IN: transferred 
serial 3
Jan 25 16:15:22 damocles named[9745]: transfer of 'cosc.tu/IN' from 
10.0.2.100#53: Transfer completed: 1 messages, 39 records, 958 bytes, 
0.001 secs (958000 bytes/sec)
Jan 25 16:15:22 damocles named[9745]: zone cosc.tu/IN: sending notifies 
(serial 3)

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.

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.]

[root@acheron ~]# nslookup
> set all
Default server: 10.0.2.100
Address: 10.0.2.100#53
Default server: 10.0.2.101
Address: 10.0.2.101#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 PowerShell prompt:

PS C:\Users\zathras>nslookup
Default Server:  acheron.cosc.tu
Address:  10.0.2.100

> set all
Default Server:  acheron.cosc.tu
Address:  10.0.2.100

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:

[root@acheron ~]# nslookup
> apollo
Server:		10.0.2.100
Address:	10.0.2.100#53

Name:	apollo.cosc.tu
Address: 10.0.2.8

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

PS C:\Users\zathras> nslookup
Default Server:  acheron.cosc.tu
Address:  10.0.2.100

> 10.0.2.7
Server:  acheron.cosc.tu
Address:  10.0.2.100

Name:    anubis.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. Here is an example from a Windows 8 system

PS C:\Users\zathras> cd .\Desktop\BIND9.9.2-P1
PS C:\Users\zathras\Desktop\BIND9.9.2-P1> .\dig.exe -x 10.0.2.100

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

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;100.2.0.10.in-addr.arpa.       IN      PTR

;; ANSWER SECTION:
100.2.0.10.in-addr.arpa. 300    IN      PTR     acheron.cosc.tu.

;; AUTHORITY SECTION:
2.0.10.in-addr.arpa.    300     IN      NS      acheron.cosc.tu.
2.0.10.in-addr.arpa.    300     IN      NS      damocles.cosc.tu.

;; ADDITIONAL SECTION:
acheron.cosc.tu.        300     IN      A       10.0.2.100
damocles.cosc.tu.       300     IN      A       10.0.2.101

;; Query time: 0 msec
;; SERVER: 10.0.2.100#53(10.0.2.100)
;; WHEN: Sat Jan 25 21:12:59 2014
;; MSG SIZE  rcvd: 150

The syntax and results on a Linux system would be the same.

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.100.

We can also try a forward query; here is an example using the Linux version of the tool

[zathras@acheron ~]$ dig heracles.cosc.tu

; <<>> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6 <<>> heracles.cosc.tu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49001
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;heracles.cosc.tu.		IN	A

;; ANSWER SECTION:
heracles.cosc.tu.	300	IN	A	10.0.2.16

;; AUTHORITY SECTION:
cosc.tu.		300	IN	NS	damocles.cosc.tu.
cosc.tu.		300	IN	NS	acheron.cosc.tu.

;; ADDITIONAL SECTION:
acheron.cosc.tu.	300	IN	A	10.0.2.100
damocles.cosc.tu.	300	IN	A	10.0.2.101

;; Query time: 0 msec
;; SERVER: 10.0.2.100#53(10.0.2.100)
;; WHEN: Sat Jan 25 18:17:39 2014
;; MSG SIZE  rcvd: 127

Again, the Windows 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 Kali host (getting its IP from DHCP and with no name server) finding out all there is to know about the cosc.tu namespace:

root@kali32:~# dig @10.0.2.100 cosc.tu axfr

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @10.0.2.100 cosc.tu axfr
; (1 server found)
;; global options: +cmd
cosc.tu.		300	IN	SOA	acheron.cosc.tu. zathras.cosc.tu. 3 300 180 1800 300
cosc.tu.		300	IN	NS	acheron.cosc.tu.
cosc.tu.		300	IN	NS	damocles.cosc.tu.
acheron.cosc.tu.	300	IN	A	10.0.2.100
achilles.cosc.tu.	300	IN	A	10.0.2.3
agamemnon.cosc.tu.	300	IN	A	10.0.2.4
agrippa.cosc.tu.	300	IN	A	10.0.2.5
alexander.cosc.tu.	300	IN	A	10.0.2.6
anubis.cosc.tu.		300	IN	A	10.0.2.7
apollo.cosc.tu.		300	IN	A	10.0.2.8
cadmus.cosc.tu.		300	IN	A	10.0.2.9
cerberus.cosc.tu.	300	IN	A	10.0.2.10
charon.cosc.tu.		300	IN	A	10.0.2.11
churchill.cosc.tu.	300	IN	A	10.0.2.12
clarkstown.cosc.tu.	300	IN	A	10.0.2.32
damocles.cosc.tu.	300	IN	A	10.0.2.101
delphi.cosc.tu.		300	IN	A	10.0.2.13
dns.cosc.tu.		300	IN	CNAME	acheron.cosc.tu.
excalibur.cosc.tu.	300	IN	A	10.0.2.14
furies.cosc.tu.		300	IN	A	10.0.2.15
gw.cosc.tu.		300	IN	A	10.0.2.254
heracles.cosc.tu.	300	IN	A	10.0.2.16
hermes.cosc.tu.		300	IN	A	10.0.2.17
hydra.cosc.tu.		300	IN	A	10.0.2.18
juno.cosc.tu.		300	IN	A	10.0.2.19
localhost.cosc.tu.	300	IN	A	127.0.0.1
medusa.cosc.tu.		300	IN	A	10.0.2.20
nemesis.cosc.tu.	300	IN	A	10.0.2.21
nimrod.cosc.tu.		300	IN	A	10.0.2.22
olympic.cosc.tu.	300	IN	A	10.0.2.23
orion.cosc.tu.		300	IN	A	10.0.2.24
persephone.cosc.tu.	300	IN	A	10.0.2.25
pollux.cosc.tu.		300	IN	A	10.0.2.26
roanoke.cosc.tu.	300	IN	A	10.0.2.27
talos.cosc.tu.		300	IN	A	10.0.2.28
theseus.cosc.tu.	300	IN	A	10.0.2.29
vesta.cosc.tu.		300	IN	A	10.0.2.30
zeus.cosc.tu.		300	IN	A	10.0.2.31
cosc.tu.		300	IN	SOA	acheron.cosc.tu. zathras.cosc.tu. 3 300 180 1800 300
;; Query time: 5 msec
;; SERVER: 10.0.2.100#53(10.0.2.100)
;; WHEN: Sat Jan 25 21:21:03 2014
;; XFR size: 39 records (messages 1, bytes 958)

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.101. 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.101;} ;
};

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

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 Kali box will fail:

root@kali32:~# dig @10.0.2.100 cosc.tu axfr

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @10.0.2.100 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. Emily
    February 28, 2014 at 5:52 pm

    Ran into a little trouble while I was working on BIND with forwarders; nslookup of an address that would be forwarded to another DNS was working on the local network, but as soon as I was querying from outside the network (specifically on nagios), I was getting the error: ” server can’t find x.x.x.10.in-addr.arpa name: REFUSED”.
    If you turn query logging on, in the /var/messages file you’ll see something like “clientip#blahblah: query (cache) ‘hostname/A/IN’ denied.”
    After some research and help from Dr. O’Leary, we found that the issue is in the named.conf file. In order for the forwarding process to work properly when querying from outside a network, we need to allow recursion. In order to do this, all we have to do is add an extra line in the ‘options’ section of our BIND named.conf. The line is:
    ” allow-recursion { any; }; “

  2. Jamie
    April 27, 2014 at 8:08 pm

    recursion is off, obviously, so the dns server can’t be used for DDoS attack via DNS amplification…
    “attacker sending a DNS name lookup request to an open DNS server with the source address spoofed to be the target’s address. When the DNS server sends the DNS record response, it is sent instead to the target. Attackers will typically submit a request for as much zone information as possible to maximize the amplification effect. In most attacks of this type observed by US-CERT, the spoofed queries sent by the attacker are of the type, “ANY,” which returns all known information about a DNS zone in a single request. Because the size of the response is considerably larger than the request, the attacker is able to increase the amount of traffic directed at the victim. By leveraging a botnet to produce a large number of spoofed DNS queries, an attacker can create an immense amount of traffic with little effort. Additionally, because the responses are legitimate data coming from valid servers, it is extremely difficult to prevent these types of attacks. While the attacks are difficult to stop, network operators can apply several possible mitigation strategies.”

  3. James Crumpler
    February 5, 2015 at 5:46 pm

    Two really helpful tools for verifying bind zones and configurations:

    named-checkzone
    named-checkconf

    These tools will report errors, some warnings, or an “ok” depending on how successful you were in creating these files.

  1. No trackbacks yet.

Leave a comment