01- DNS & Bind

Introduction

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

Required Machines: CentOS 5.5

All of the work in this exercise will be done on a CentOS 5.5 machine. 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:

Changing the host name

Start by changing the name of your host. You do this by editing the file /etc/sysconfig/network and modify the HOSTNAME line.

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.

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.

Set up the system to use a static IP address

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

DEVICE=eth0
ONBOOT=yes
BOOTPROTO=none
HWADDR=00:0C:29:DE:7A:B2
NETMASK=255.255.255.0
IPADDR=192.168.1.201
GATEWAY=192.168.1.1
TYPE=Ethernet
USERCTL=no
IPV6INIT=no
PEERDNS=no

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 /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

# named -v

In the virtual machines provided to the class, you will find that the installed version should be 9.3.6

Note that the BIND service is chrooted by default on CentOS, 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- “class”. This DNS server will respond to requests for “hostname.class”. This zone is called a forward zone, because it maps names to addresses.

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

;
$TTL 3h
;
class. IN SOA centos1.class. user.centos1.class. (
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
;
class. IN NS centos1.class.
;
; Host Addresses
;
localhost.class. IN A 127.0.0.1
gw.class. IN A 192.168.1.1
centos1.class. IN A 192.168.1.201
centos2.class. IN A 192.168.1.202
centos3.class. IN A 192.168.1.203
xp1.class. IN A 192.168.2.211
;
; Aliases
;
dns.class. IN CNAME centos_1.class.

From this, we first see that the default time to live (TTL) is set to 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 is

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 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.class) to the name server (centos_1.class).

The Reverse Zone

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

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

;
$TTL 3h
;
1.168.192.in-addr.arpa. IN SOA centos1.class. user.centos1.class (
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 centos1.class.
;
; Address records
;
1.1.168.192.in-addr.arpa. IN PTR gw.class.
201.1.168.192.in-addr.arpa. IN PTR centos1.class.
202.1.168.192.in-addr.arpa. IN PTR centos2.class.
203.1.168.192.in-addr.arpa. IN PTR centos3.class
211.1.168.192.in-addr.arpa. IN PTR xp1.class.

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 PTR records rather than 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/chroot/var/named/db.127.0.0 as follows:

$TTL 3h
;
0.0.127.in-addr.arpa. IN SOA centos1.class user.centos1.class (
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 centos1.class.
;
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 ftp://198.41.0.6/domain/db.cache

named.conf

Finally, we set up the file /var/named/chroot/etc/named.conf, which configures the name server itself, rather than the individual zones. Using the file names chosen above, we create the file as follows.

// BIND Configuration File

options {
directory “/var/named”;
};

zone “class” in {
type master;
file “db.class”;
};

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

/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/Server Settings/Services. Check the box for named and save. This method also be used to start & stop the system. The command line equivalent of this tool is chkconfig

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/Security Level and Firewall.  You need to specify the ports manually.

Clients

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

nameserver 192.168.1.201

(substitute the correct address!) to the file/etc/resolv.conf.

The details of the structure of /etc/resolv.conf can be found by man resolv.conf

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

The named.conf file

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

// BIND Configuration File

options {
directory “/var/named”;
};

zone “class” in {
type slave;
file “bak.class”;
masters {192.168.1.201; };
};

zone “1.168.192.in-addr.arpa” in {
type slave;
file “bak.192.168.1”;
masters {192.168.1.201; };
};

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.

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. No need to manually ensure that the servers are in agreement.

Before we start the nameserver though, we need to be sure that the nameserver has the file permissions needed to write to the directory /var/named/chroot/var. That directory is owned by user root and group named.  In this case, root has has rwx permissions, while named has rx permissions- meaning it can read the directory and its files (only).

The minimal change is to give the group named write permissions on the directory

# chmod g+w /var/named/chroot/named/

There is no need to grant permissions beyond this!

Starting the slave

Start the slave server using /etc/init.d/named

SELinux will throw an error. SELinux can set up and enforce more fine grained policies, and feels that, in general, the service named should not be creating zone files or renaming files. SELinux is a sophisticated system to secure a linux system, but we do not have time in class to cover it in any detail. Thus, in the image I provided to the class, I set the SELinux policy to warn, rather than to deny. Though the SELinux system noted the problem and threw the warning, it did not prevent the access.

Note that, if you want to set SELinux to enforcing, that the system indicates how to solve the problem in the setroubleshoot program.

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

As before, check System/Administration/Server Settings/Services to ensure it starts on boot.

As before, ensure that the firewall allows TCP 53 & UDP 53.

Update each client to use both master and slave as their DNS server.

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.

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

# rndc reload

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 by running

# rndc retransfer “zone”

on the slave for each zone that has been updated on the master.

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, while team 2 is using the namespace *.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 “tu” in {
type forward;
forwarders {192.168.2.24; };
};

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.

Of course, you need to specify forwarders for both your forward zone and your reverse zone.

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

i. $ nslookup “hostname”
ii. $ nslookup “IP_address”
iii. $ nslookup -type=ns “yourdomain.”

[Note the trailing . in the last command!]

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

> 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

Also run the following from within the lookup shell:

> “hostname” (e.g. in my example above, use > xp1)
> “IP_address” (e.g. in my example above, use > 192.168.1.211)
> server “slave_server_name
“> “hostname”

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

$ dig -x “IP_addr”
$ dig @”server.domain” “domain” afxr

In the example above, we could try

$ dig @centos1.class class afxr

to perform a zone transfer

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

Security

Why is allowing a zone transfer a bad idea?

To prevent zone transfers except from authorized servers, in the zone statement, use the directive allow-transfer in the named.conf file; as an example you could use the following named.conf file

// BIND Configuration File

options {
directory “/var/named”;
};

zone “class” in {
type master;
file “db.class”;
allow-transfer {192.168.1.202; };
};

zone “1.168.192.in-addr.arpa” in {
type master;
file “db.192.168.1”;
allow-transfer {192.168.1.202; };
};

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

zone “tu” in {
type forward;
forwarders {192.168.1.24; };
};

For additional security, we can even require that the server requesting the transfer use a pre-shared key; see e.g.
http://www.bind9.net/manual/bind/9.3.2/Bv9ARM.ch04.html

if you want to try it out.

Exercise- Forwarders

Set up a second nameserver / namespace. [Recommended- Use the servers set up by a classmate!] In this example, suppose that your namespace is “*.class” on 10.0.2.0/24 and your classmate’s is “*.tu” on 10.0.3.0/24.

Set up your nameserver correctly so that it forwards requests for “*.tu” to your classmate. Verify that this process works by having a client (host.class) run nslookup on a name from your classmate’s namespace (otherhost.tu) and validate the result.

Set up your nameserver correctly so that it also handles the reverse
lookups. Verify the process works correctly by having a client (10.0.2.x) run nslookup on an IP from your classmates IP range (10.0.3.y) and validate the result.

  1. No comments yet.
  1. No trackbacks yet.

Leave a comment