Dynamic Address Management using DHCP and DNS

Why

We had been using a D-Link DFL-300 as our Internet gateway. While it provides a DHCP server and DNS server, it does not support dynamic DNS. Therefore, it cannot provide name resolution for hosts that I have not manually entered into its DNS server. In addition, while its DNS server does support A records, its DNS server does not support CNAME and MX records. Finally, while its DHCP server does support the most basic DHCP attributes, its DHCP server does not support some of the DHCP attributes that we need. As a result of all these things, I decided to disable the DHCP server and the DNS server on the D-Link DFL-300 and run a DHCP server and DNS server on the GNU/Linux server.

What

There are numerous DHCP and DNS servers available for GNU/Linux. However, for GNU/Linux in general and CentOS in particular, the DHCP server of choice is ISC DHCP and the DNS server of choice is ISC BIND. Therefore, that is what I chose.

Domain Name Selection

For DNS to work effectively, we needed a domain name for our network. I have the domain name 'bendercasa.net' registered, so I use it for our network.

However, before registering 'bendercasa.net', I needed to pick a private domain name that would not conflict with the public DNS namespace. Unfortunately, there is no private DNS namespace to parallel the private IP addresses. As a result, there is no way to be sure that the domain name that I picked would not conflict with the public DNS namespace in the future.

Initially, I picked 'local' as our private domain name. This worked well until some visitors with MacOS X laptops connected to our network. DNS name resolution would not work on their laptops. I recalled having read that Apple's Rendezvous (now Bonjour) was using 'local' in some manner. Therefore, I suspected that the use of 'local' as our private domain name was conflicting with Rendezvous. As a result, I changed our private domain name to 'private'. Once I did this, DNS name resolution worked on their laptops.

Later reading revealed that 'local' was conflicting with the multicast DNS name resolution used by Rendezvous. The Multicast DNS Internet Draft proposes using 'local' as the link-local top level domain. As a result, it suggests that people avoid using the '.local.' DNS namespace, and proposes other possible private DNS namespaces for people to use. As it turns out, 'private' is in this list of possible private DNS namespaces.

In order to ensure that the name in the certificate and the name of the host match, our web server rewrites the URL so that the host is always the name in the certificate (at the time 'www.private'). One day, I accessed our web server from an external computer using our external dynmaic DNS name. Since the computer was external, it was not using our network's DNS server and could not resolve 'www.private'. Trying to be helpful, the web browser added '.com' to the end. I did not want to visit 'www.private.com'.

While I reconfigured our web server so that it did not rewrite the URL with the internal name when accessing with the external name. However, in order to prevent something similar from happening in the future, I changed our network's domain name to 'home'. The website 'www.home.com' is more benign than the website 'www.private.com'.

Of course, now that our network uses a domain name that is part of the DNS namespace, there are no longer any private domain name related problems.

ISC DHCP

Installation

There are some installation things to note.

CentOS ships with a couple ISC DHCP 3 related packages: dhcp and dhclient. I installed the dhcp package, since it contains the DHCP server. I did not install the dhclient package, since it contains the DHCP client package and is not needed for running a DHCP server.

Configuration

Our configuration files (/etc/dhcpd.conf, /etc/sysconfig/dhcpd and /etc/sysconfig/network-scripts/ifcfg-eth0) /etc/sysconfig/network-scripts/ifcfg-eth1) are simple. There is little to say that is not already said by the comments of the files.

The GNU/Linux server has two interfaces: eth0 which is the LAN interface and eth1 which is the WAN interface. The LAN interface uses a static IP address since it is a server. The WAN interface uses a static IP address since it is connected to the DMZ port of the D-Link DFL-300.

I wanted the DHCP server to run only on the LAN interface. I accomplished this by modifying /etc/sysconfig/dhcpd.

The dhcpd daemon is run using the /etc/init.d/dhcpd script provided by the dhcp package. I wanted the dhcpd daemon to start on boot, so I configured the dhcpd service to start on boot using the commands 'chkconfig --add dhcpd' and 'chkconfig dhcpd on', where 'chkconfig' is privided by the chkconfig package.

ISC BIND

Installation

There are some installation things to note.

CentOS ships with several BIND 9 related packages: bind, bind-libs, bind-utils, bind-chroot, caching-nameserver and system-config-bind. While I installed bind, bind-libs and bind-utils, I did not install bind-chroot, caching-nameserver packages or system-config-bind. I installed bind and bind-libs, because they are needed to set up a DNS server using BIND. I installed bind-utils, because I wanted utilities such as 'dig'. I did not install bind-chroot, because I had no desire to deal with running BIND in a chroot environment. I did not install caching-nameserver package, becuase it installs configuration files that I already have (and have included below). I did not install system-config-bind, because I have no desire to use the somewhat limited system-config-bind UI to configure BIND.

By default, the CentOS bind package sets the ownership on the directory '/var/named' so that the BIND daemons ('named' and 'rndc') do not have write access. For dynamic DNS updates, the BIND daemons need write access to the directory '/var/named'. Therefore, you need to override this using the 'ENABLE_ZONE_WRITE' variable in /etc/sysconfig/named.

Configuration

Our configuration file (/etc/named.conf and /etc/resolv.conf) and zone files (/var/named/null, /var/named/root, /var/named/localhost.forward, /var/named/localhost.reverse, /var/named/bendercasa.net.forward, /var/named/bendercasa.net.reverse.192.168.000, /var/named/bendercasa.net.reverse.192.168.001 and /var/named/bendercasa.net.reverse.192.168.100) are simple. I did not include the /etc/rndc.conf and /etc/rndc.key configuration files, because these files are unchanged (except for the key) from the files installed by the bind package. However, there are some things to note.

Our external website http://www.bendercasa.net/ is hosted by hosting company rather than by our home network. Therefore, its A record in /var/named/bendercasa.net.forward specifies the IP address provided by the hosting company.

When BIND performs a DDNS update, it reformats the /var/named/bendercasa.net.* files. While the BIND zone file format supports including multiple domains in one zone file, BIND screws up zone files with multiple domains when a DDNS update is performed. Therefore, I split the /var/named/bendercasa.net.reverse zone file into three zone files based on subnet so that each zone file contains one domain.

I copied the /var/named/root file from the caching-nameserver package. The file is called named.root in the package and /var/named/named.ca' when it is installed. This file is provides BIND with the IP addresses of the root DNS servers.

I have attempted to keep inappropiate DNS traffic from leaving our network. I configured BIND to act as the authority for forward lookups on typical home and site-local domains. In addition, I configured BIND to act as the authority for reverse lookups on private, link-local and site-local addresses. I am doing this, because studies show that forward lookups on non-existant top level domains and reverse lookups on private addresses are resulting in noticable load on the root DNS servers.

According to RFC 2142, the mailbox hostmaster should exist to receive messages related to the DNS server. Therefore, I have added an entry in the LDAP server ('cn=hostmaster,ou=aliases,dc=bendercasa,dc=net') that aliases hostmaster to root.

Before the GNU/Linux server become the DNS server, the GNU/Linux server used the D-Link DFL-300 as its DNS server. Once the the GNU/Linux server became the DNS server, the GNU/Linux server needed to be configured to use itself as the DNS server. I accomplished this by modifying /etc/resolv.conf.

With the GNU/Linux server was running a DNS server, there appears to be little need to resolve addresses using the /etc/hosts file. Therefore, in the future, I may modify the /etc/host.conf and /etc/nssswitch.conf files to not resolve using files.

The BIND daemons ('named' and 'rndc') are run using the /etc/init.d/named script provided by the bind package. I wanted the BIND daemons to start on boot, so I configured the named service on boot using the commands 'chkconfig --add named' and 'chkconfig  named on', where 'chkconfig' is privided by the chkconfig package.