02- DNS & Bind

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

Hostname

Start by changing the name of your host. You do this by editing the file /etc/sysconfig/network and modify the HOSTNAME line. Be sure to enter
the FQDN here; in my example, I will call the host “shades” with parent domain “cosc.tu” giving me the file:

NETWORKING=yes
HOSTNAME=shades.cosc.tu

Documentation is available in usr/share/doc/initscripts-<version-number>/sysconfig.txt.

You also need to modify the entries in the file /etc/hosts; in particular you need to make sure that all of the aliases for 127.0.0.1 are appropriate. As an example, we can set that file to look like

127.0.0.1   localhost localhost.localdomain shades shades.cosc.tu
::1         localhost localhost.localdomain shades shades.cosc.tu

so that any of the four names “localhost”, “localhost.localdomain”, “shades” and “shades.cosc.tu” will refer to 127.0.0.1

At this point, you can reboot the machine. Mind you, this is not strictly necessary, as the changes can also be made live by using the hostname command. Noe that changes made that way only persist until a reboot when the configuration files are re-read. Given that we are going to do a lot of work with DNS and hostnames, it is better is you simply reboot now and verify that your changes have been made correctly.

Static networking

Because we want to use this system as our master DNS server, it is imperative that it have a static IP address.

Edit the file /etc/sysconfig/network-scripts/ifcfg-eth0 along the following lines

DEVICE="eth0"
ONBOOT="yes"
BOOTPROTO="none"
HWADDR="00:0C:29:C2:89:83"
NETMASK="255.255.255.0"
IPADDR="192.168.1.60"
GATEWAY="192.168.1.1"
TYPE="Ethernet"
USERCTL="no"
IPV6INIT="no"
PEERDNS="no"

where (of course) you change the addresses to match the particulars of your network. Notice that we have decided to disable IPv6 networking for this host. Remember not to use spaces around the equal signs. Documentation for this file is available in usr/share/doc/initscripts-<version-number>/sysconfig.txt

At this point, you have a number of options. The slowest way is to simply reboot the machine. You can also run the script

[root@shades ~]# /etc/init.d/network restart

which is probably the best way to proceed.

Note also that changes can be made to the IP of a running system with the ifconfig command (See man ifconfig for details). Be sure to also change the gateway if necessary using the route command (e.g. # route add default gw 192.168.1.1); see man route.

DNS server with BIND: The basics

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

[root@shades ~]# 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.

The Forward Zone

We will start with one top level domain- “cosc.tu”. This DNS server will respond to requests for “hostname.cosc.tu”. This zone is called a forward zone, because it maps names to addresses.

Create the zone file /var/named/db.cosc.tu, and set it up as follows:

;
$TTL 3h
;
cosc.tu. IN SOA shades.cosc.tu. vimes.shades.cosc.tu. (
           1 ; Serial
           3h ; Refresh after 3 hours
           1h ; Retry after 1 hour
           1w ; Expire after 1 week
           1h ) ; Negative TTL of one week

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

;
; Host Addresses
;
localhost.cosc.tu.            IN A 127.0.0.1
gw.cosc.tu.                   IN A 192.168.1.1
shades.cosc.tu.               IN A 192.168.1.60		
dimwell.cosc.tu.              IN A 192.168.1.61		
longwall.cosc.tu.             IN A 192.168.1.62		
scours.cosc.tu.               IN A 192.168.1.63		
hippo.cosc.tu.                IN A 192.168.1.64		
smallgods.cosc.tu.            IN A 192.168.1.65         
naphill.cosc.tu.              IN A 192.168.1.66         
dollysisters.cosc.tu.         IN A 192.168.1.67         
unrealestate.cosc.tu.         IN A 192.168.1.68		
dragonslanding.cosc.tu.       IN A 192.168.1.69		
isleofgods.cosc.tu.           IN A 192.168.1.70         

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

We adopt the naming convention for bind configuration files in /var/named that they have the form db.namespace for forward records. This is not required however, and we could give this file any name we wish.

Reading the file, we first see that the default time to live (TTL) is set to three hours. This is the amount of time that these records could be cached. Because our is a classroom environment where we expect things to change rapidly, we choose the very small value of three hours.

Next in the file comes the SOA record. When reading the file, be sure to notice the periods after the hostnames. These are required.

The first line has the form

domain_name IN SOA dns_server_name mail_address_of_admin

where the ‘@’ in the mail address has been replaced by another ‘.’ Here IN = Internet- this is the class of data in this file, while SOA = Start of authority record. Only one SOA can be in a zone datafile. SOA means that this file is authoritative for this zone.

The file then sets up the Internet (IN) namerserver records (NS); these are all of the nameservers for this zone. More than one nameserver can be specified

Next, the file sets up the host name records, or address records (A) for each host.

Finally, the file ends with a list of aliases records (CNAME). This configuration file gives a second name (dns.cosc.tu) to the name server (shades.cosc.tu).

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.

The Reverse Zone

Now we set up the address to name mappings, this is called a reverse zone.

Create the file /var/named/db.192.168.1 as follows

$TTL 3h
;
1.168.192.in-addr.arpa. IN SOA shades.cosc.tu. vimes.shades.cosc.tu. (
           1 ; Serial
           3h ; Refresh after 3 hours
           1h ; Retry after 1 hour
           1w ; Expire after 1 week
           1h ) ; Negative TTL of one week

;
; Name Servers
;
1.168.192.in-addr.arpa.       IN NS shades.cosc.tu.

;
; Address records
;
1.1.168.192.in-addr.arpa.     IN PTR gw.cosc.tu.
60.1.168.192.in-addr.arpa.    IN PTR shades.cosc.tu.
61.1.168.192.in-addr.arpa.    IN PTR dimwell.cosc.tu.
62.1.168.192.in-addr.arpa.    IN PTR longwall.cosc.tu.
63.1.168.192.in-addr.arpa.    IN PTR scours.cosc.tu.
64.1.168.192.in-addr.arpa.    IN PTR hippo.cosc.tu.
65.1.168.192.in-addr.arpa.    IN PTR smallgods.cosc.tu.
66.1.168.192.in-addr.arpa.    IN PTR naphill.cosc.tu.
67.1.168.192.in-addr.arpa.    IN PTR dollysisters.cosc.tu.
68.1.168.192.in-addr.arpa.    IN PTR unrealestate.cosc.tu.
69.1.168.192.in-addr.arpa.    IN PTR dragonslanding.cosc.tu.
70.1.168.192.in-addr.arpa.    IN PTR isleofgods.cosc.tu.

We again use a naming convention; since this is a reverse zone, we name it db.netaddr, where netaddr is the address of the network.

Like the forward zone, we have set the time to live to three hours.

The remaining records are similar to the db.class file. Numerical addresses are in reverse order, and ended with “.in-addr.arpa.” The primary difference here is that now we use pointer (PTR) records rather than address (A) records.

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 3h
;

0.0.127.in-addr.arpa. IN SOA shades.cosc.tu. vimes.shades.cosc.tu. (
           1 ; Serial
           3h ; Refresh after 3 hours
           1h ; Retry after 1 hour
           1w ; Expire after 1 week
           1h ) ; Negative TTL of one week

;
0.0.127.in-addr.arpa. IN NS shades.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 "1.168.192.in-addr.arpa" in {
      type master;
      file "db.192.168.1";
};

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

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.

As your first test, from the DNS server, run nslookup “hostname” for a hostname that appears in your records; you should get the correct response. Do the same for the an IP address.

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

Clients

Now that the server is configured, we need to set our clients to use it. On a typical linux machine, add the line

nameserver 192.168.1.60

(substitute the correct address!) to the file/etc/resolv.conf. The details of the structure of /etc/resolv.conf can be found by checking man resolv.conf

The situation is slightly different however, with the network manager for CentOS 6.2. The file /etc/resolv.conf is modified based on the contents of the file /etc/sysconfig/network-scripts/ifcfg-eth0. In fact, changes made to that file are reflected in the /etc/resolv.conf almost immediately. Conversely, changes made directly to /etc/resolv.conf will be lost whenever a change is made to /etc/sysconfig/network-scripts/ifcfg-eth0. Thus, rather than change /etc/resolv.conf, the preferred approach is to modify /etc/sysconfig-network-scripts/ifcfg-eth0 to add lines for the DNS server(s) and the search domain as follows:

DEVICE="eth0"
ONBOOT="yes"
BOOTPROTO="none"
HWADDR="00:0C:29:3C:21:1E"
NETMASK="255.255.255.0"
IPADDR="192.168.1.61"
GATEWAY="192.168.1.1"
TYPE="Ethernet"
USERCTL="no"
IPV6INIT="no"
PEERDNS="no"
DNS1="192.168.1.60"
DNS2="192.168.1.61"
DOMAIN="cosc.tu"

Do so, and the contents of the file /etc/resolv.conf become

# Generated by NetworkManager
search cosc.tu
nameserver 192.168.1.60
nameserver 192.168.1.61

The precise method to configure a Windows machine varies by the type of Windows, but in general go through control panel, to network connections, to TCP/IP and make the corresponding change in the GUI.

Setting up a slave nameserver

Why do we want to set up a second nameserver? 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 “dimwell” and the IP address 192.168.1.61. Note that this name/IP combination is already included in DNS zone data for our master nameserver.

The slave named.conf file

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

// BIND Configuration File

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

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

zone "1.168.192.in-addr.arpa" in {
       type slave;
       file "bak.192.168.1";
       masters {192.168.1.60; };
};

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

Check that the zone files have been downloaded and now reside in the directory /var/named/slaves

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.

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@shades ~]# /etc/init.d/named status
rndc: neither /etc/rndc.conf nor /etc/rndc.key was found
named (pid  3439) 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@shades ~]# rndc-confgen > rndcconf

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 "C/TmciFpYhffK/Lu77gwfA==";
};

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 "C/TmciFpYhffK/Lu77gwfA==";
# };
# 
# 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 "C/TmciFpYhffK/Lu77gwfA==";
};

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@shades etc]# ls -l /etc/rndc.key
-rw-r--r--. 1 root root 87 Jan 28 18:19 /etc/rndc.key

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

[root@shades etc]# chmod o-r /etc/rndc.key 
[root@shades etc]# ls -l /etc/rndc.key
-rw-r-----. 1 root root 202 Jan 28 18:15 /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@dimwell etc]# chown root:named /etc/rndc.key 
[root@dimwell etc]# ls -l /etc/rndc.key 
-rw-r-----. 1 root named 89 Jan 28 19:06 /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 "1.168.192.in-addr.arpa" in {
      type master;
      file "db.192.168.1";
};

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 “C/TmciFpYhffK/Lu77gwfA==”. 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.

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. As an example, we could run

[root@shades ~]# rndc 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

to find the current status of the server. Other commands include

  • reload: Reload the configuration file or a single zone (if the zone is also specified).
  • reconfig: Reload the configuration file and new zones (only)
  • refresh zone:Schedules an immediate refresh for the specified zone
  • stop:Stop the server, saving any pending updates
  • halt:Stop the server, without saving any pending updates

Take a look at the man page for rndc. You will discover that rndc can also be used to configure remote servers by specifying the appropriate server and port. To do so however, the server must be configured to listen on more than just localhost as we have done so.

Updating the data

Suppose that the data for a zone is changed on the master. How does the slave know to update its data? The answer is through the use of the serial number. If the serial number on the master is larger than the serial number for the slave, then the slave will know that it needs to update its data from the slave. Beyond this, there is no requirement that serial numbers be e.g. consecutive.

To reload the zone data on the master, you can restart the named daemon, or simply run

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

The changes on the master will automatically be propgated to the slaves. This is governed by our refresh interval- which in our example files is set to 3 hours.  If this is too long to wait, this can be done manually using rndc. Suppose that we have modified the zone file for cosc.tu on the master; then on the slave if we run

[root@dimwell ~]# rndc retransfer cosc.tu

the zone file will be updated accordingly. Note that the retransfer command pays no attention to the serial number- if you run a retransfer, the zone will be transferred, regardless of the serial numbers. The refresh command for rndc will also schedule an immediate transfer, but will respect the serial numbers.

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. But- 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 *.class.tu, while team 2 is using the namespace *.cosc.tu. We also suppose that the nameserver for team 2 is located at 192.168.2.24. Then in the named.conf file for team 1, we add the lines:

zone "class.tu" in {
         type forward;
         forwarders {192.168.2.80; };
};

Now when a machine that is using the team 1 DNS server is asked for an address from team 2- say mybox.tu- that request will be forwarded to the nameserver 192.168.2.24 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 the 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.

Exercises- Common DNS commands

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@shades ~]# nslookup
> set all

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

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

[root@shades ~]# nslookup
> shades
Server:		192.168.1.60
Address:	192.168.1.60#53

Name:	shades.cosc.tu
Address: 192.168.1.60

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

[root@shades ~]# nslookup
> 192.168.1.66
Server:		192.168.1.60
Address:	192.168.1.60#53

66.1.168.192.in-addr.arpa	name = naphill.cosc.tu.

Another important command to be comfortable using is dig.

$ dig “hostname.domain”

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

[root@shades ~]# dig -x 192.168.1.66

; <> DiG 9.7.3-P3-RedHat-9.7.3-8.P3.el6_2.1 <> -x 192.168.1.66
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 34150
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

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

;; ANSWER SECTION:
66.1.168.192.in-addr.arpa. 10800 IN	PTR	naphill.cosc.tu.

;; AUTHORITY SECTION:
1.168.192.in-addr.arpa.	10800	IN	NS	shades.cosc.tu.

;; ADDITIONAL SECTION:
shades.cosc.tu.		10800	IN	A	192.168.1.60

;; Query time: 1 msec
;; SERVER: 192.168.1.60#53(192.168.1.60)
;; WHEN: Sun Jan 29 15:26:19 2012
;; MSG SIZE  rcvd: 109

It is possible to use dig to pull the entire zone from a host. For example, fire up a Backtrack machine; you don’t even need to set the resolver (etc/resolv.conf). Point dig at your namerserver as follows:

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

; <> DiG 9.7.0-P1 <> @192.168.1.60 cosc.tu axfr
; (1 server found)
;; global options: +cmd
cosc.tu.		10800	IN	SOA	shades.cosc.tu. vimes.shades.cosc.tu. 4 10800 3600 604800 3600
cosc.tu.		10800	IN	NS	shades.cosc.tu.
dimwell.cosc.tu.	10800	IN	A	192.168.1.61
dns.cosc.tu.		10800	IN	CNAME	shades.cosc.tu.
dollysisters.cosc.tu.	10800	IN	A	192.168.1.67
dragonslanding.cosc.tu.	10800	IN	A	192.168.1.69
gw.cosc.tu.		10800	IN	A	192.168.1.1
hippo.cosc.tu.		10800	IN	A	192.168.1.64
isleofgods.cosc.tu.	10800	IN	A	192.168.1.70
localhost.cosc.tu.	10800	IN	A	127.0.0.1
longwall.cosc.tu.	10800	IN	A	192.168.1.62
naphill.cosc.tu.	10800	IN	A	192.168.1.66
scours.cosc.tu.		10800	IN	A	192.168.1.63
shades.cosc.tu.		10800	IN	A	192.168.1.60
smallgods.cosc.tu.	10800	IN	A	192.168.1.65
unrealestate.cosc.tu.	10800	IN	A	192.168.1.68
cosc.tu.		10800	IN	SOA	shades.cosc.tu. vimes.shades.cosc.tu. 4 10800 3600 604800 3600
;; Query time: 23 msec
;; SERVER: 192.168.1.60#53(192.168.1.60)
;; WHEN: Sun Jan 29 18:30:09 2012
;; XFR size: 17 records (messages 1, bytes 463)

From this, we see that we have enumerated the entire network!
In the example above, we could try

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

Security

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 192.168.1.61. 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 { 192.168.1.61; };
};

zone "1.168.192.in-addr.arpa" in {
      type master;
      file "db.192.168.1";
      allow-transfer { 192.168.1.61; };
};

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

zone "class.tu" in {
      type forward;
      forwarders {192.168.2.80; };
};

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 @192.168.1.60 cosc.tu axfr

; <> DiG 9.7.0-P1 <> @192.168.1.60 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:

// BIND Configuration File

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

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

zone "1.168.192.in-addr.arpa" in {
       type slave;
       file "bak.192.168.1";
       masters {192.168.1.60; };
       allow-transfer{ none; };
};

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

zone "class.tu" in {
      type forward;
      forwarders {192.168.2.80; };
};

include "/etc/rndc.key";

controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1; } keys { "rndc-key"; };
};

Now this approach solves the problem of unauthorized hosts grabbing our zone files, but one problem remains- what would happen if an impostor spoofed the IP address of the master, and sent a malicious set of zone data to the slave? Then the attacker could redirect traffic that used the data provided by the slave.

To avoid this problem, we will take advantage of transaction signatures, or TSIG. We start by creating a key that we will share between the master and the slave. On the master, we run

[root@shades ~]# dnssec-keygen -a HMAC-MD5 -b 128 -n HOST shades.cosc.tu
Kshades.cosc.tu.+157+04598

This generates two files in the current directory:

  • Kshades.cosc.tu.+157+04598.key
  • Kshades.cosc.tu.+157+04598.private

We can examine their contents:

[root@shades ~]# cat Kshades.cosc.tu.+157+04598.key 
shades.cosc.tu. IN KEY 512 3 157 KlK46jAKc13AhjVSttLZCA==

[root@shades ~]# cat Kshades.cosc.tu.+157+04598.private 
Private-key-format: v1.3
Algorithm: 157 (HMAC_MD5)
Key: KlK46jAKc13AhjVSttLZCA==
Bits: AAA=
Created: 20120130003230
Publish: 20120130003230
Activate: 20120130003230

With this data in hand, we start by creating a file, which we will call /etc/named.keys.conf with contents:

key tsig.shades.cosc.tu {
     algorithm hmac-md5;
     secret "KlK46jAKc13AhjVSttLZCA==";
};

Note that the secret here is just the secret that we created with the dnssec-keygen command above.

Like other secrets, we do not want this to be world readable; so we make the necessary changes:

[root@shades etc]# ls -l /etc/named.keys.conf 
-rw-r--r--. 1 root root 95 Jan 29 16:45 /etc/named.keys.conf
[root@shades etc]# chmod o-r /etc/named.keys.conf 
[root@shades etc]# chown root:named /etc/named.keys.conf 
[root@shades etc]# ls -l /etc/named.keys.conf 
-rw-r-----. 1 root named 95 Jan 29 16:45 /etc/named.keys.conf

We then add another include line to /etc/named.conf

include "/etc/named.keys.conf";

Now we modify the allow-transfer directive so that now it calls for the key we just defined; the result is the following named.conf on the master:

// BIND Configuration File

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

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

zone "1.168.192.in-addr.arpa" in {
      type master;
      file "db.192.168.1";
      allow-transfer { key tsig.shades.cosc.tu; };
};

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

zone "class.tu" in {
      type forward;
      forwarders {192.168.1.80; };
};

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

Now we head over to the slave. We again create the file /etc/named.keys.conf with the identical contents, change its permissions, and include in /etc/named.conf. Then we adjust the masters directive to require the signature; this yields the following /etc/named.conf for the slave:

// BIND Configuration File

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

zone "cosc.tu" in {
       type slave;
       file "bak.cosc.tu";
       masters {192.168.1.60 key tsig.shades.cosc.tu; };
       allow-transfer{ none; };
};

zone "1.168.192.in-addr.arpa" in {
       type slave;
       file "bak.192.168.1";
       masters {192.168.1.60 key tsig.shades.cosc.tu; };
       allow-transfer{ none; };
};

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

zone "class.tu" in {
      type forward;
      forwarders {192.168.1.80; };
};

include "/etc/rndc.key";
include "/etc/named.keys.conf";

controls {
       inet 127.0.0.1 port 953
       allow { 127.0.0.1; } keys { "rndc-key"; };
};

Be sure to test your results!

Errors will not, in general be thrown by the scripts or tools like rndc; you will need to look at the logs (/var/log/messages). Don’t forget to reload your configuration file or restart named if you make changes.

Exercise

Set up a functioning DNS environment. It should

  • Have a master
  • Have a slave
  • Correctly forward queries aimed at the domain of one of your teammates
  • Not allow arbitrary zone transfers
  • Use TSIG to ensure security of zone transfers from the master to the slave
  1. Brian C.
    February 2, 2012 at 12:27 pm

    another great reference that has an entire book, setup as a website. It covers concepts and terminology indepth and at a high level, all while staying organized and easy to understand

    http://www.zytrax.com/books/dns/

  1. No trackbacks yet.

Leave a comment