Linux Home Server HOWTO
Previous
Home Next

Chapter 8 - Domain Name System (BIND)

Version: - bind 9.3.2

Initial Configuration
Setting Daemon Options
Adding Your Domain
Starting BIND
Testing The Server
Configuring Dynamic DNS

The Domain Name System (or Service) provides a naming resolution service that makes it easy for us humans to use the Internet, among other tasks. Every computer located on the Internet that is publicly accessible uses an unique Internet address, but these Internet addresses are numerical in nature and difficult to remember. To download the latest Linux kernel I point my browser to www.kernel.org, but the server is located at the Internet address of 204.152.191.5, I know which address I would prefer to remember.

The global DNS provides listings for publicly accessible addresses. If you need to access any computer resources inside your own network and your network is using RFC1918 private address allocation, then you will not be able to use the public DNS to resolve your internal network resources. This can be fixed by introducing your own DNS for the internal network.

This chapter will provide the steps necessary to configure your own DNS server to assist in internal name resolution and to provide a caching service for external domains. The Berkeley Internet Name Domain (BIND) software is installed on most Linux distributions, and is also available from the Internet Systems Consortium site.

Note !! If you are using a dynamic IP address and you would like to host your own website and email servers, then you will also need to review the Dynamic DNS details in Chapter 5.

Initial Configuration

For a Linux host to use DNS, the system resolver must be told which name servers to use. This information is stored in the /etc/resolv.conf file. As with any configuration, we should always backup the original configuration file before editing it.

[bash]# cp /etc/resolv.conf /etc/resolv.conf.original
[bash]# vi /etc/resolv.conf

The resolver on the new DNS server needs to be adjusted so it points to itself for name resolution. Be sure to substitute "example.com" for the domain(s) you are configuring.

search example.com
nameserver 127.0.0.1

The search parameter defines a list of domains that will be searched when doing hostname queries. The nameserver parameter lists the DNS servers that the host should use for name resolution, in this case itself.

For more information on the system resolver, type "man resolv.conf" at the command prompt.

Setting Daemon Options

The name of the DNS daemon in the BIND package is funnily enough called named, and the main configuration file is located in /etc/named.conf. The configuration can be quite daunting to the new, so lets back it up before making any changes.

[bash]# cp /etc/named.conf /etc/named.conf.original
[bash]# vi /etc/named.conf

The main configuration file is split into many sections. To configure named to only allow queries from the local server and internal network hosts, add the "listen-on" and "allow-query" options. This will restrict unwanted queries on your server.

options {
     directory "/var/named";
     dump-file "/var/named/data/cache_dump.db";
     statistics-file "/var/named/data/named_stats.txt";
     /*
      * If there is a firewall between you and nameservers you want
      * to talk to, you might need to uncomment the query-source
      * directive below.  Previous versions of BIND always asked
      * questions using port 53, but BIND 8.1 uses an unprivileged
      * port by default.
      */
     //query-source address * port 53;
     listen-on { 127.0.0.1; 192.168.1.1; };
     allow-query { 127.0.0.1; 192.168.1.0/24; };
};

If your DNS server is located behind a firewall and is having difficulty with resolving names, you may need to uncomment this directive.

query-source address * port 53;

The "." zone below tells named to check this file for a list of the root name servers, so it knows where to send external queries. This enables the caching nameserver feature of BIND, by forwarding any unknown requests to the root nameservers listed in the file. This zone should already be listed in the configuration.

zone "." IN {
        type hint;
        file "named.ca";
};

You may find that sending every new DNS query to the root name servers will be a little slow. This can be improved by sending all of your queries to a quicker "upstream" DNS server which will process your request for you. An upstream DNS server (like the ones at your ISP) may already have the query you're after in its cache, or it will normally have a faster backbone link to the root name servers.

To use forwarders you need to have at least one upstream DNS server IP address. Forwarders are a configuration option which needs to be placed inside the "options" section (place under the "allow-query" option above).

#Place INSIDE 'options'

     forward first;
     forwarders { xxx.xxx.xxx.xxx; xxx.xxx.xxx.xxx; };         <-- Add your ISP's DNS servers in here (IP addresses ONLY)

Note !! Pay particular attention to the format of the configuration file, missing semicolons will cause the daemon to function irrationally, if at all.

Adding Your Domain

To provide resolution for the network and computer resources inside your own private network, you need to configure your DNS with your own master DNS zone. The examples below will now guide the configuration of a master zone. These examples are more designed to provide DNS for an internal private network (the home or small office user), and should be used only as a basis for a full authoritative zone. It is also suggested that you configure your domain externally for people to find you on the Internet, see DDNS Service Providers in Chapter 5 if you don't have external name resolution.

Firstly we need to set the zone information in the same named configuration file we used earlier, place the following configuration settings at the bottom of the "/etc/named.conf" file.

[bash]# vi /etc/named.conf

Caution !! The "example.com" domain name must be substituted for your domain in the following examples.

zone "example.com" IN {
        type master;
        file "data/master-example.com";
        allow-update { none; };
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "data/reverse-192.168.1";
        allow-update { none; };
};

The "example.com" zone will be configured as a master using the file "master-example.com" to store all the details about the zone entities (inside the "/var/named/chroot/var/named/data" directory).

You should notice the configuration file is located inside a chroot() jail directory, this is a secure configuration typical of BIND installations. We will not cover chroot here, but be aware of the importance of the directory structure (some Linux versions may differ slightly though).

[bash]# vi /var/named/chroot/var/named/data/master-example.com

The following is an example FORWARD zone file for the "example.com" domain name, it is using private addressing for internal only name resolution.

;
;       Zone File for "example.com" - Internal Use ONLY
;
$TTL 1D
@             IN      SOA       galaxy.example.com.  sysadmin.example.com.  (
                                10             ; Serial
                                8H             ; Refresh
                                2H             ; Retry
                                4W             ; Expire
                                1D )           ; Minimum
;
              IN      NS       galaxy          ; Name Server for the domain
              IN      MX  10   galaxy          ; Mail Exchange
;
example.com.  IN      A        192.168.1.1     ; IP address for the domain 'example.com'
galaxy        IN      A        192.168.1.1     ; IP address for 'galaxy'
www           IN      CNAME    galaxy          ; 'galaxy' is also known as www
ftp           IN      CNAME    galaxy          ; 'galaxy' is also known as ftp
;
wkstn1        IN      A        192.168.1.201   ; MANUAL IP address entry for 'wkstn1'
wkstn2        IN      A        192.168.1.202   ; MANUAL IP address entry for 'wkstn2'

The forward zone file allows name resolution from NAME to IP address. To allow name resolution from IP address to NAME, we need to configure a REVERSE zone file.

[bash]# vi /var/named/chroot/var/named/data/reverse-192.168.1

The reverse zone file looks similar to the forward zone file, however you will note the IP addresses are listed first, with the names listed after the pointer directive (PTR).

;
;       Reverse File for network "192.168.1.0/24" - Internal ONLY
;
$TTL 1D
@             IN      SOA       galaxy.example.com.  sysadmin.example.com.  (
                                10             ; Serial
                                8H             ; Refresh
                                2H             ; Retry
                                4W             ; Expire
                                1D )           ; Minimum
;
              IN      NS        galaxy.example.com.
1             IN      PTR       galaxy.example.com.
;
201           IN      PTR       wkstn1.example.com.     ; MANUAL entry for 'wkstn1' reverse delegation
202           IN      PTR       wkstn2.example.com.     ; MANUAL entry for 'wkstn2' reverse delegation

Caution !! When configuring the forward and reverse zone files, ensure the IP addresses and the host names are identical in both files. Also, DO NOT add DHCP names and addresses into the files, they will change over time - this can be resolved by using Dynamic DNS below.

The following are some of the common parameters (and definitions) required to configure our zone files.

Parameter
Definition
$TTL
Time To Live for the zone file
IN
The Internet system
SOA
Start Of Authority to administer zone
NS
Name Server for the zone
MX
Mail Exchange for the zone (needs a priority value)
A
Address records for hosts / network equipment
CNAME
Canonical name for an alias (points to "A" record)

This line specifies that the host galaxy.example.com is the SOA for the zone, and that sysadmin.example.com is the email address of the zone's technical contact ([email protected]). It is important to note that a period "." at the end of the domain names indicates they are fully qualified.

@       IN      SOA     galaxy.example.com.  sysadmin.example.com. 

Warning !! The periods "." located at the end of fully qualified domain names are required. Failure to use periods for FQDNs will cause irregular name resolution.

The following entry specifies that galaxy.example.com is the mail exchange for the zone, which has been set to priority 10. Leave this as standard unless you know what you are doing, or remove it if you are not running your own email servers.

                MX      10      galaxy  ; Mail Exchange

That completes the configuration of named and the new forward/reverse zone files for our "example.com" domain name. The zone files now need to be chown'd to the named user account and a symbolic link created to the new chroot() jailed file.

[bash]# chown named.named /var/named/chroot/var/named/data/master-example.com
[bash]# ln -s /var/named/chroot/var/named/data/master-example.com /var/named/data/master-example.com

[bash]# chown named.named /var/named/chroot/var/named/data/reverse-192.168.1
[bash]# ln -s /var/named/chroot/var/named/data/reverse-192.168.1 /var/named/data/reverse-192.168.1

Note !! The file naming convention is typical of Fedora Core and may differ slightly between Linux distributions.

Checking Your Work

There are several small programs that are in the BIND package that allow integrity checking of the named configuration and zone files. These are great tools to maintain your sanity for testing purposes, as named can be quite particular about problems in the configuration and zone files.

[bash]# named-checkconf /etc/named.conf

Note !! The most common errors for misconfiguration in the named file are missing semicolons ";" after parameter settings.

The zone file should be checked for format consistency, and should resemble the above example.com zone file (substitutions should be made for the domain and hosts being configured).

[bash]# named-checkzone -d example.com /var/named/data/master-example.com
loading "example.com" from "/var/named/master-example.com" class "IN"
zone example.com/IN: loaded serial 10
OK

The reverse zone file should also be checked for any errors.

[bash]# named-checkzone -d 1.168.192.in-addr.arpa /var/named/data/reverse-192.168.1
loading "1.168.192.in-addr.arpa" from "/var/named/data/reverse-192.168.1" class "IN"
zone 1.168.192.in-addr.arpa/IN: loaded serial 10
OK

Note !! The most common errors for misconfiguration in zone files are missing periods "." at the end of fully qualified domain names - especially for the SOA line.

Starting BIND

After BIND has been configured and there are no errors being returned from the check applications, it is time to set the runlevels and start the service.

[bash]# chkconfig --level 2345 named on
[bash]# /etc/init.d/named restart

A manual check after setting the runlevels confirms that named should start properly after a system reboot.

[bash]# chkconfig --list named

Once the service has been started, check the system log to see if there are any runtime errors, and that your newly configured zone is being served successfully. The entries "zone example.com/IN: loaded serial 10"  and "zone 1.168.192.in-addr.arpa/IN: loaded serial 10" confirms the zone load was successful and can now be queried.

[bash]# grep named /var/log/messages

galaxy named[19111]: starting BIND 9.3.2 -u named -t /var/named/chroot
galaxy named[19111]: found 2 CPUs, using 2 worker threads
galaxy named[19111]: loading configuration from '/etc/named.conf'
galaxy named[19111]: listening on IPv4 interface lo, 127.0.0.1#53
galaxy named[19111]: listening on IPv4 interface eth1, 192.168.1.1#53
galaxy named[19111]: command channel listening on 127.0.0.1#953
galaxy named[19111]: zone 0.in-addr.arpa/IN: loaded serial 42
galaxy named[19111]: zone 0.0.127.in-addr.arpa/IN: loaded serial 1997022700
galaxy named[19111]: zone 1.168.192.in-addr.arpa/IN: loaded serial 10      <-- Successful load
galaxy named[19111]: zone 255.in-addr.arpa/IN: loaded serial 42
galaxy named[19111]: zone example.com/IN: loaded serial 10                 <-- Successful load
galaxy named[19111]: zone localdomain/IN: loaded serial 42
galaxy named[19111]: zone localhost/IN: loaded serial 42
galaxy named[19111]: running

Testing The Server

Now that you have configured your Linux server to query itself for DNS and you have configured the caching server and added your own zone files, its time to test that everything we did was successful. Using the dig application we can check a name resolution for www.example.com, remembering that www in our configuration was an alias that really pointed to galaxy.example.com.

[bash]# dig www.example.com
; <<>> DiG 9.3.2 <<>> www.example.com
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48535
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 0

;; QUESTION SECTION:
;www.example.com.               IN      A

;; ANSWER SECTION:
www.example.com.        86400   IN      CNAME   galaxy.example.com.
galaxy.example.com.     86400   IN      A       192.168.1.1                   <-- Correct IP address returned

;; AUTHORITY SECTION:
example.com.            86400   IN      NS      galaxy.example.com.

;; Query time: 3 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)               <-- Query from local server
;; WHEN: Wed May 17 21:16:38 2006
;; MSG SIZE  rcvd: 84

The above results return the true CNAME for www, and also the A record for galaxy.example.com being 192.168.1.1. In the footer area the query server is set as 127.0.0.1#53, this is the nameserver we originally set in the /etc/resolv.conf file, itself.

We can now check a complete listing of the whole zone file with the following command.

[bash]# dig example.com AXFR @localhost
; <<>> DiG 9.3.2 <<>> example.com AXFR @localhost
; (1 server found)
;; global options:  printcmd
example.com.            86400   IN      SOA     galaxy.example.com. sysadmin.example.com. 10 28800 7200 2419200 86400
example.com.            86400   IN      NS      galaxy.example.com.
example.com.            86400   IN      MX      10 galaxy.example.com.
example.com.            86400   IN      A       192.168.1.1
ftp.example.com.        86400   IN      CNAME   galaxy.example.com.
galaxy.example.com.     86400   IN      A       192.168.1.1
wkstn1.example.com.     86400   IN      A       192.168.1.201
wkstn2.example.com.     86400   IN      A       192.168.1.202
www.example.com.        86400   IN      CNAME   galaxy.example.com.
example.com.            86400   IN      SOA     galaxy.example.com. sysadmin.example.com. 10 28800 7200 2419200 86400
;; Query time: 2 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)               <-- Query from local server
;; WHEN: Wed May 17 21:17:21 2006
;; XFR size: 9 records (messages 1)

The most important test is that we are able to successfully resolve domain names that are listed externally to our private network, and cached from the many Internet DNS servers.

[bash]# dig fedora.redhat.org
; <<>> DiG 9.3.2 <<>> fedora.redhat.org
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2193
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;fedora.redhat.org.             IN      A

;; ANSWER SECTION:
fedora.redhat.org.      120     IN      A       65.38.107.197

;; AUTHORITY SECTION:
redhat.org.             86400   IN      NS      ns1.ireithost.com.
redhat.org.             86400   IN      NS      ns2.ireithost.com.

;; ADDITIONAL SECTION:
ns1.ireithost.com.      156739  IN      A       65.38.107.198
ns2.ireithost.com.      156739  IN      A       65.38.109.156

;; Query time: 395 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)               <-- Query from local server
;; WHEN: Wed May 17 21:18:36 2006
;; MSG SIZE  rcvd: 132

Our last test is to confirm that reverse name lookup is available by querying the reverse delegation zone.

[bash]# host 192.168.1.201
201.1.168.192.in-addr.arpa domain name pointer wkstn1.example.com.

Now that the DNS set up is complete, the rest of the workstations inside the private network must be configured to use DNS 192.168.1.1 as the primary name server. For Linux clients this should be listed in /etc/resolv.conf, for Windows clients this should be configured in network settings.

If your internal network is using DHCP to provide IP addresses to your workstations, then "option domain-name-servers 192.168.1.1;" should be set in your "/etc/dhcpd.conf" configuration file.

Configuring Dynamic DNS

As you would have noticed, configuring the forward and reverse zones for a single domain name can take some time to set up correctly and the information these zone files contain are pretty much static, ie they shouldn't change much. However when an IP address or name does change the information in the zone files also need to be changed otherwise the incorrect details will be returned from our DNS server when queried.

To automate this, we use Dynamic DNS. The Internet Systems Consortium corporation (ISC) write both of the BIND and DHCP server suites that are utilised within Fedora Core, when both of these server applications are utilised together, they are able to update themselves whenever details change between DHCP and DNS. This allows an easy method for the forward and reverse DNS zone files to be updated when a dynamic host is allocated an IP address from the DHCP server.

Caution !! The following configuration adjustments assume you have already configured your ISC DHCP daemon in accordance with Chapter 10; please do this first.

To configure Dynamic DNS, we can generate a basic set of configuration files by running the rndc-confgen application. The first half of the output goes into the "/etc/rndc.conf" file, while the remaining half of the output goes into the "/etc/named.conf" file.

[bash]# rndc-confgen
key "rndckey" {                    <-- Insert first section into /etc/rndc.conf file
        algorithm hmac-md5;
        secret "rZvmZb1cOtvkUfacVZ6oKA==";
};

options {
        default-key "rndckey";
        default-server 127.0.0.1;
        default-port 953;
};                                 <-- End of first section

key "rndckey" {                    <-- Insert second section into /etc/named.conf file
      algorithm hmac-md5;
      secret "rZvmZb1cOtvkUfacVZ6oKA==";
};

controls {
      inet 127.0.0.1 port 953
              allow { 127.0.0.1; } keys { "rndckey"; };
};                                 <-- End of second section

Warning !! Ensure the "include /etc/rndc.key" directive is removed (or commented out) from both the /etc/rndc.conf and /etc/named.conf files, as you have now created a new configuration. Only ensure there is only ONE "controls" directive in /etc/named.conf.

To ensure that all zone updates are secure, the update requests and transfers are covered using a secure key (MD5 message hash algorithm) which can be generated easily with the dnssec-keygen application. This key then needs to be replicated and shared with the DNS and DHCP server configuration files.

[bash]# dnssec-keygen -a HMAC-MD5 -b 128 -n USER DYNAMIC_DNS_KEY
[bash]# cat Kdynamic_dns_key*.private
Private-key-format: v1.2
Algorithm: 157 (HMAC_MD5)
Key: LBxD9REd0XAEwPYOTZMS0w==                      <-- Shared MD5 Algorithm
Note !! The "Kdynamic_dns_key*" file generated in the above step is safe to delete after the DNS and DHCP configuration files have been updated.

The DNS server configuration file needs to be updated with the secure key declaration, and the zone file settings will also need to be allowed to update if they are done so with the secure key.

[bash]# vi /etc/named.conf
key DYNAMIC_DNS_KEY {
        algorithm hmac-md5;
        secret LBxD9REd0XAEwPYOTZMS0w==;           <-- Shared MD5 Algorithm
};

zone "example.com" IN {
        type master;
        file "data/master-example.com";
        allow-update { key DYNAMIC_DNS_KEY; };     <-- Allow "key" update
};

zone "1.168.192.in-addr.arpa" IN {
        type master;
        file "data/reverse-192.168.1";
        allow-update { key DYNAMIC_DNS_KEY; };     <-- Allow "key" update
};

Now the DHCP server configuration file needs to updated with the same secure key declarations. The server is also told where the primary zone files are stored (on 127.0.0.1) so they can update the DNS server.

[bash]# vi /etc/dhcpd.conf
key DYNAMIC_DNS_KEY {
        algorithm hmac-md5;
        secret LBxD9REd0XAEwPYOTZMS0w==;           <-- Shared MD5 Algorithm
}

zone example.org. {
        primary 127.0.0.1;
        key DYNAMIC_DNS_KEY;                       <-- Allow "key" update
}

zone 1.168.192.in-addr.arpa. {
        primary 127.0.0.1;
        key DYNAMIC_DNS_KEY;                       <-- Allow "key" update
}

Caution !! The secure key must match in both the "/etc/named.conf" and "/etc/dhcpd.conf" files otherwise Dynamic DNS will not work effectively.

The DHCP server must now be configured to allow client updates, make the following two changes to your "/etc/dhcpd.conf" file.

[bash]# vi /etc/dhcpd.conf
#
#   DHCP Server Config File
#
ddns-update-style interim;
               <--- Change these in /etc/dhcpd.conf
allow client-updates;                     <--- Change these in /etc/dhcpd.conf

The DHCP daemon now needs to be configured for Dynamic DNS updates.

[bash]# vi /etc/sysconfig/named
OPTIONS=-4
ENABLE_ZONE_WRITE=yes
ROOTDIR=/var/named/chroot

Note !! For detailed information about named daemon, type "man named" at the command prompt.

Now that the Dynamic DNS configurations are complete, the services need to be restarted.

[bash]# /etc/init.d/dhcpd restart
[bash]# /etc/init.d/named restart

Allow your Dynamic DNS configuration a little time to run (enough for some DHCP clients to renew IP Addresses) and then check the syslog to see if your server is successfully updating the forward and reverse zone files with the new client information.

[bash]# grep dhcpd /var/log/messages
dhcpd: if wkstn3.example.com IN TXT "3168f50e8140ac8a1c8b84d809c6adbefe" rrset exists and wkstn3.example.com IN A 192.168.1.200 rrset exists delete wkstn3.example.com IN A 192.168.1.200: success.
dhcpd: if wkstn3.example.com IN A rrset doesn't exist delete wkstn3.example.com IN TXT "3168f50e8140ac8a1c8b84d809c6adbefe": success.
dhcpd: removed reverse map on 200.1.168.192.in-addr.arpa.
dhcpd: DHCPRELEASE of 192.168.1.200 from 00:13:d4:2e:3b:d6 (wkstn3) via eth1 (found)
dhcpd: DHCPDISCOVER from 00:13:d4:2e:3b:d6 via eth1
dhcpd: DHCPOFFER on 192.168.1.200 to 00:13:d4:2e:3b:d6 (wkstn3) via eth1
dhcpd: Added new forward map from wkstn3.example.com to 192.168.1.200
dhcpd: added reverse map from 200.1.168.192.in-addr.arpa. to wkstn3.example.com

The named daemon will also add entries to the syslog to identify correct/successful operation.

[bash]# grep named /var/log/messages
named: client 127.0.0.1#32769: updating zone 'example.com/IN': adding an RR at 'wkstn3.example.com' A
named: client 127.0.0.1#32769: updating zone 'example.com/IN': adding an RR at 'wkstn3.example.com' TXT
named: client 127.0.0.1#32769: updating zone '1.168.192.in-addr.arpa/IN': deleting rrset at '200.1.168.192.in-addr.arpa' PTR
named: client 127.0.0.1#32769: updating zone '1.168.192.in-addr.arpa/IN': adding an RR at '200.1.168.192.in-addr.arpa' PTR

A forward lookup can be checked against a known DHCP client to ensure a successful lookup.

[bash]# host wkstn3.example.com
wkstn3.example.com has address 192.168.1.200

A reverse lookup can also be done to ensure reverse delegation can also be confirmed.

[bash]# host 192.168.1.200
200.1.168.192.in-addr.arpa domain name pointer wkstn3.example.com

If you have got this far, you have done well - enjoy a fully automated Dynamic DNS solution.



Previous
Home Next