Navigation:

Search



Our Friends

Articles DNS and BIND
 

DNS and BIND

An explanation of the domain name system (DNS) and setting up a domain using ISC BIND 9.

This was written by Moshe Jacobson and given on Sun Feb 23 2003.

Table of Contents


1. Introduction

Setting up and hosting your own domain name is easy! This document will hopefully give you all the information you need to set one up using BIND 9.

2. The Domain Name System

If you already know how DNS works, you can skip this section. It is intended as a brief introduction to the complex behavior of the DNS system in general.

When you perform a DNS query, you are attempting to find the/an IP address associated with a particular domain name. You as an end user generally have two DNS servers that you always use to perform lookups. These are generally run by either you or your Internet access provider, and in most Unix-like platforms, are listed in /etc/resolv.conf .

When you send a query to your local nameserver, it first looks to see if it is hosting the domain about which you're requesting information. If it is, it simply looks up the information locally and sends the response to you.

If it doesn't host that domain, it looks to see if it has recently answered a query for the same record as you are requesting. If it has, and the Time-To-Live on the cached record data has not yet expired (meaning the record is still current enough to be accurate), it then just returns the answer from its cached data.

If it doesn't have the data cached, and it is set up as a recursive nameserver (one that will perform the subsequent requests on your behalf instead of making you do it), it must fetch an authoritative answer. Since it is impossible to know what the authoritative server is for a particular zone, that information must be maintained centrally. The servers that store this information are known as the "root" nameservers. There are currently 13 of them, with DNS names of A.ROOT-SERVERS.NET through M.ROOT-SERVERS.NET. If these servers were all to go down, the Internet would become practically unusable.

Once your local DNS server has queried a root nameserver for the requested domain's authority information, it is given a (short) list of servers that will be able to return authoritative data for the domain under which your requested record resides.

It then sends a query to the authoritative servers in turn until it receives an answer. It then relays the answer to you.

The highly distributed nature of DNS can cause many headaches when you need to make any changes to a domain's authoritative servers or any of its records. Changes can take days to propagate, and knowing how to minimize your downtime is very important.

3. DNS Hosting Requirements

If you wish to host your own domain name, there are some prerequisites that must be satisfied.

First, your DNS servers must have completely static IP addresses. Any change to your IP address will make your domain name completely useless.

Second, you must have one server to function as the primary nameserver, and at least one separate machine to host the secondary nameserver(s). These are the servers that will answer DNS queries for your domain in the event that your primary DNS server is unavailable.

Usually, one of your friends will be willing to be the secondary nameserver for your domain in return for the same from you. If you don't have any friends, you can use www.secondary.com which will be your backup name server for free.

4. Setting it all up

The steps involved in setting up your own domain name are as follows:

4.1. Register your domain name with a domain name registrar.

You can use any registrar such as http://netsol.com/ , http://godaddy.com/ , http://gandi.net/ , or http://joker.com/ . The domain name will cost you between $8 and $20 per year depending on where you register it.

Some features to look for with a registrar are the ability to make ALL changes online, especially your administrative and technical contact information and the name servers registered as authoritative for your domain.

4.2. Register your DNS servers with your registrar, if necessary.

Many registrars require that you register your name servers' IP addresses with them before they allow you to use them for your domain. Follow the instructions on their website to set these up.

You may need to have the DNS server already running on the IP address before registering it with them, but in most cases, you can just do it right now. If they request a name for the DNS server, you should use something like ns1.yourdomain.com and ns2.yourdomain.com .

4.3. Register your DNS servers as authoritative for your domain.

Once you've registered the DNS servers, you will need to edit your domain information and change the name servers listed on there to ns1.yourdomain.com and ns2.yourdomain.com (assuming that's what you named them).

It will now take between 24 and 48 hours for this new domain to be propagated to the root nameservers, so you will only be able to use it from your own machine for a while, provided you have set your own machine's primary DNS server to 127.0.0.1 in /etc/resolv.conf .

4.4. Install BIND on your host(s) and perform the basic configuration.

I won't go into the specifics of how to perform the basic installation (It's pretty much a straight ./configure && make && make install ) You can download the BIND 9 tarball here:

http://isc.org/products/BIND/bind9.html

If you don't like building from a tarball, you can probably find a package of BIND made just for your Linux distribution.

4.5. Perform basic configuration

Once you have BIND installed, you will need to create /etc/named.conf . There are some example configurations in the ARM (see Resources section). I will go over the basic options that you'll need to get a more-or-less typical setup working.

The named.conf syntax is very rigid, but pretty straightforward. Mostly everything is either just a statement followed by a semicolon, e.g.:

file "example.com.db";

or a block-style option, which requires a semicolon after the closing brace, as well as after each sub-block's closing brace, and after each simple statement it contains:

allow-transfer {
    192.168.4.14;
    192.168.5.53;
};

The most basic configuration, which will probably suit most needs just fine, starts out with an options block like this:

options {
    /* Base dir; where to look when we see a relative pathname */
    directory "/var/named";

    /* Write a pidfile on startup so we know the pid of named */
    pid-file "/var/run/named.pid";

    /* Allow anyone to perform DNS queries to this server */
    allow-query { any; };

    /* Perform recursive queries for clients. This helps build a cache
     * of DNS data, so that fewer external requests are generated in
     * the future. */
    recursion yes;

    /* What interfaces for BIND to listen on */
    listen-on { 66.23.194.234; 127.0.0.1; };

    /* When a change is made to any of the zones for which we are the
     * master server, notify the slaves of the update immediately */
    notify yes;
};

Now we need to specify the base zone "." which is used when we need to make external requests.

zone "." in {
  type hint;
  file "root.hint";
};

The file root.hint is found in /var/named/root.hint since we specified /var/named in the directory directive above. The "type hint;" directive indicates that this zone file is a listing of the root nameservers, which provide a "hint" to point you to the authoritative server for a domain. The root.hint file looks like this. You never need to modify it:

.                        3600000  IN  NS    A.ROOT-SERVERS.NET.
A.ROOT-SERVERS.NET.      3600000      A     198.41.0.4

.                        3600000      NS    B.ROOT-SERVERS.NET.
B.ROOT-SERVERS.NET.      3600000      A     128.9.0.107

; continue in this fashion...

.                        3600000      NS    L.ROOT-SERVERS.NET.
L.ROOT-SERVERS.NET.      3600000      A     198.32.64.12

.                        3600000      NS    M.ROOT-SERVERS.NET.
M.ROOT-SERVERS.NET.      3600000      A     202.12.27.33

Now we need reverse resolution for the 127.* range of IP addresses. The following zone will do it:

zone "0.0.127.in-addr.arpa" in {
  type master;
  file "0.0.127.in-addr.arpa";
  allow-update { none; };
};

The backwards "in-addr.arpa" system is used to reverse resolve IP addresses to domain names. It's a long story why this is the case, but in a nutshell, it is so that forward resolvers don't have to be entirely rewritten to perform reverse resolution as well.

The 0.0.127.in-addr.arpa zone file is very simple, only listing a record for 1.0.0.127.in-addr.arpa, or 127.0.0.1 to resolve to "localhost":

$TTL    86400
@       IN      SOA     localhost. root.localhost.  (
                                      1997022700 ; Serial
                                      28800      ; Refresh
                                      14400      ; Retry
                                      3600000    ; Expire
                                      86400 )    ; Minimum
        IN      NS      localhost.
1       IN      PTR     localhost.

I will go over the meaning of these records in more detail when we get to the section on configuring our zone files.

Finally, let's set up forward resolution for the "localhost" hostname:

zone "localhost" in {
  type master;
  file "local";
  allow-update { none; };
};

The "local" file is also very simple; it maps "localhost" to 127.0.0.1:

$TTL 21600
@ IN SOA @ root.localhost. (
     45
     28800
     14400
     3600000
     86400 )
@ IN NS localhost.
@ IN A 127.0.0.1

Finally, we must set up a shared key to allow the use of the "rndc" tool to control the server. The reason it must use a key is that rndc can be used from any host on the Internet, so we must be able to verify that it is authorized, as well as be able to encrypt its data.

Before we can add the shared key section to the named.conf, however, we must, run the rndc-confgen program that comes with bind. This program generates the content for /etc/rndc.conf for you automatically, with a randomly generated key. Its output will look something like this:

# Start of rndc.conf
key "rndc-key" {
            algorithm hmac-md5;
                    secret "OpxZPKpwc5vNOCsD/rz9sw==";
};
        
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 "OpxZPKpwc5vNOCsD/rz9sw==";
# };
#
# controls {
#       inet 127.0.0.1 port 953
#               allow { 127.0.0.1; } keys { "rndc-key"; };
# };
# End of named.conf

In the commented section of this file, it provides you with the exact blocks you need to place in named.conf to allow rndc to connect to it using this rndc.conf . Simply copy these lines onto the end of the named.conf and save it and exit.

You can now verify the syntax and validity of your config file using the named-checkconf program that comes with BIND. Make sure everything is kosher, and you should be ready to progress to the next section! But first, take a caffeine break :)

4.6. Add the new zone to your primary server's BIND config file (named.conf).

You now need to tell BIND that you want to host the primary DNS for mydomain.com. This is done by adding a new "zone" block to the named.conf , as follows:

/* New zone called mydomain.com, of type "in" (Internet) */
zone "mydomain.com" in {

    /* We're the master server for this domain */
    type "master";

    /* Store the data in /var/named/mydomain.com.db */
    file "mydomain.com.db";

    /* Who will we allow to transfer the entire domain? Normally, the
     * only IP addresses listed here should be those of the secondary
     * DNS servers for the domain */
    allow-transfer {
        128.61.15.251; // ns.resnet.gatech.edu
        128.177.209.27; // secondary.com
    }
}

At this point, you should be done with the named.conf on the primary DNS server. You don't need to do anything else to it. Run named-checkconf to make sure the file checks out, and you should then be good to go.

4.7. Create and populate the new zone file.

Now's the fun part. This is where you get to specify all the information about your domain. Assuming you pointed your named.conf at /var/named/mydomain.com.db for the information pertatining to mydomain.com (for which you are listed as the primary DNS server), you should now create this file with your favorite editor, and proceed with me.

All BIND 9 compatible zone files must start out with a default time-to-live that will be applied to all the resource records in your domain. The global TTL specification looks like this:

$TTL 86400

This TTL specification says that for every record in your zone that does not have a specific TTL set for it, that the TTL should be set to 86400 seconds, or 1 day. BIND 8 did not require this statment, but BIND 9 does.

Now we begin with the resource records. Each record specifies something about the zone, and follows this general format:

RESOURCE_NAME   PROTO   TYPE    VALUE(S)

The resource name is usually a hostname in your domain, or the domain name itself. The protocol is usually IN. This is short for Internet, and pretty much all records are of type IN. In fact, if you don't specify a protocol, BIND will usually assume type IN. The TYPE is usually one of the following (there are others, but they are rarely used):

Type Description
SOA Start of Authority, some global settings for the zone
NS Specifies a Name Server for the domain
MX Specifies a Mail eXchanger for the domain
A Specifies an IP Address for a particular host/domain
CNAME Specifies the canonical name for this "nickname" entry

The VALUE varies depending on the TYPE. You will begin to see how this all works as we go over examples.

The first resource record (RR) that comes in every zone file is the SOA record. It looks something like this:

mydomain.com. IN SOA ns.mydomain.com. hostmaster.mydomain.com. (
                        200209272 ;serial
                        28800     ;refresh
                        14400     ;retry delay
                        86400     ;expire
                        21600     ;default_ttl
                    )

The resource name is "mydomain.com." since we are specifying the SOA record for this domain, not one of its subdomains. Please note that we must place a period after the domain name so that BIND doesn't automatically append "mydomain.com" to the end of it, resulting in a record for "mydomain.com.mydomain.com". This is a common beginner's mistake. Any fully qualified domain name (FQDN) that is specified _anywhere_ in a zone file must be followed by a "." or BIND will append the "origin" domain name to it.

Note that you can also replace any instance of the zone's base domain ("mydomain.com.") with an @ sign, so that a single zonefile could be used for multiple zones that are copies of each other, and the @ will be replaced with the proper domain name for each. So then the SOA record ends up looking like this:

@  IN SOA ns.mydomain.com. hostmaster.mydomain.com. (
              200209272 ;serial
              28800     ;refresh
              14400     ;retry delay
              86400     ;expire
              21600     ;default_ttl
          )

The two values after SOA, are, respectively, the primary DNS server name for this domain (note the period after it), and the email address of the domain administrator (with a "." instead of the "@").

The serial number is what keeps track of the file's version. DNS servers around the world attempt to cache your domain's information, and will retrieve updated information from your server only if the serial number has incremented since last time it checked. Therefore, if you make changes to your DNS zone, you *must* increment the serial number or it will not take effect until the number of seconds in the "expire" field has passed, or until $TTL seconds have passed, whichever comes later.

It is conventional to use some form of the date (e.g. YYYYMMDDNN, where NN is the number of the revision for that day, so you could revise it up to 100 times in that day). Other people simply like to start their serial number at 1, and just increment by 1 each time. It's all a matter of personal preference.

The refresh, retry delay, and expire are almost always good at their defaults. The default_ttl is the amount of time that negative responses for data from your zone should be cached. That is, if someone requests an IP address for nonexistent.mydomain.com and it doesn't exist, their DNS server will cache that negative response for 21600 seconds. This means that even if you add nonexistent.mydomain.com to your zone within 21600 seconds, they will not notice until that amount of time has passed on their end.

Now that you've specified your SOA record, you need to list the authoritative name servers for your domain. This will use the NS record type, and it will look something like this:

@  IN NS ns.mydomain.com.
   IN NS ns1.secondary.com.
   IN NS ns2.secondary.com.

As you can see, we didn't need to specify the @ for each record, because if the resource name is omitted, BIND assumes you are still referring to the last one mentioned.

If you want to receive email at your domain, you must now specify a mail exchanger. This is the host to which an MTA (e.g. sendmail, qmail) will send mail when there is mail for someone@mydomain.com. The MX record specification looks something like this:

@  IN MX  10  mail.mydomain.com.
   IN MX  20  mail.backupmx.com.

The number between the MX and the mail server hostnames is the preference number. The lower numbered servers are tried first, and if they fail, mail is sent to a backup MX -- one with a higher preference number. This is so that if the main mail server is down, mail can be sent to another mail server that will hold the mail until the primary server comes back up.

Now you should specify an A record for the main domain name so when people go to http://mydomain.com or ping mydomain.com, they get a valid IP address:

@  IN A  128.61.48.46

At this point, you've taken care of the basic settings for the base domain. Notice that we have used several hostnames we haven't yet defined, such as ns.mydomain.com and mailmydomain.com. We'll need to add those domains below.

First, however, let's set our origin to mydomain.com. so we can be lazy and specify only hostnames instead of full domain names:

$ORIGIN mydomain.com.

Again, notice the "." after the domain name, as always.

Now we can proceed to specify our hostnames. One rule is that all nameserver hostnames and mail exchanger hostnames must be defined by A records, not with CNAME records. It just creates another level of indirection for lookups, and is against standards.

mail    IN A    128.61.48.46
ns      IN A    128.61.48.46
mybox   IN A    128.61.48.46
lappy   IN A    192.168.0.2

"mybox" is a name we're giving to the host at 128.61.48.46. We want 128.61.48.46 to show up when you look up the name mybox.mydomain.com. lappy.mydomain.com will resolve to 192.168.0.2, so it is really only useful inside my network.

Most domains have www and ftp names with it. Assuming we are hosting our web and ftp service on box1, we can just make these records CNAMEs, so there will be less switching around of records if we ever change IP addresses:

www     CNAME   mybox
ftp     CNAME   mybox

Okay, now say your friend Joe wants to have joe.mydomain.com point to the same IP address as his website so he can set up some virtual hosting. Let's say that www.eatatjoes.com is his normal website, and he wants us to point joe.mydomain.com there. What we can do to avoid having to change our record every time he changes his IP address is simply create a CNAME to point to his domain:

joe     CNAME   www.eatatjoes.com.

Again, we put a period at the end this time, since it is not a cname for www.eatatjoes.com.mydomain.com.

Now assume that jill decides she wants to have control of jill.mydomain.com and all its subdomains; she's going to run her own name server for jill.mydomain.com. What we do, then, is delegate the zone to her with an NS record:

jill    IN NS   ns.jillsdomain.com.

That way, requests to jill.mydomain.com and *.jill.mydomain.com will all be redirected to her name server.

All right! It looks like everything is set up and ready to go! You can use the named-checkzone program distributed with BIND to check the syntax of your zone, and make any corrections necessary, and then you'll be ready to progress to the next step.

4.8. Start named!

Assuming you (or the named installation) created a nonprivileged user "named" under which to run named, you're ready to start named as follows:

named -u named

Then we set up our secondary server...

4.9. Add the new zone to your backup server's named.conf

Now all you've gotta do is tell the secondary server that it's authoritative as a slave server for mydomain.com. Assuming they're running BIND 9, you can accomplish this by adding a block similar to the following to their named.conf :

zone "mydomain.com" in {
    type slave;
    file "com/mydomain";
    masters {
        128.61.48.46; // ns.mydomain.com
    };
};

On this server, the administrator likes to arrange the domain files in a different structure, placing them in a hierarchy where each component of the domain name gets its own subdirectory. So if their "directory" was specified as /etc/named , then when their named is restarted, it will transfer the zone from us and place it in /etc/named/com/mydomain .

Now reload the zones on the slave server (You can use " rndc reload ") and it should pull down the domain name from your main server.

Congratulations, you're now hosting your own domain name! Now it's time to set up your mail and web servers... But I'm not going to tell you how to do that here :) That's for another presentation!

5. Resources