DNS History

The Domain Name System was proposed in the early 80's

Solving the problem of scale

Original intent was to replace the HOSTS file

Newest implementations offer additional features like:


Domain Name Space

The DNS distributed database framework

NODES in the tree have labels called Domain Names

Fully-Qualified Domain Names (FQDNs)

A Domain is just a sub-tree of the Name Space

The in-addr.arpa. domain


Zones, Delegation and Authority

Authority for a zone is Delegated by the parent zone

A zone can include its sub-domains

A zone is that portion of a Domain Name Space sub-tree that is managed by a single entity. Note that this definition might include sub-domains of the parent if those domains have not been delegated.

Zone authority usually includes at least two zones


DNS Queries

In a nutshell:

Queries come in two flavors

Here is how a query might get resolved:


Resource Records

All data in the DNS is kept in Resource Records

The 'nslookup' command is used to retrieve Resource Records (RRs)


Name Servers

A name server is a daemon process that answers DNS queries

Usually there is one Primary name server for a zone

Most sites have one or more Secondary name servers

A third type of name server is the Caching server

One name server can play all three roles

A final category of name server is the Stealth Server

Every zone must be served by an Authoritative server

Parent zone must delegate to all authoritative servers

Name servers can be configured to Forward queries


DNS Networking Information

DNS Servers listen on TCP and UDP port 53

Note that this is a configurable value, but that is also the well-known port number on which resolver libraries (i.e. client applications) expect to find DNS servers listening. Zone transfers (when a secondary server gets an entire set of zone data from a primary server) sometimes utilize a different port (1053 seems to be common) to allow for more specific firewall rules.

The header is described below. Not all of the remaining sections must have any data. For queries, only the 'question' section will have anything in it. Answers to standard (A,PTR,CNAME) queries will be found in the 'answers' section. Answers that are NS records are in the 'authority' section. Answers to other queries will be in the 'additional' section.

The ID value is arbitrarily chosen by the machine that generates the query, it is propogated into server responses. The QR bit is set to one for queries, and zero for answers. The opcode has only three possible values (at this time):

   0    A standard query
   1    An inverse query
   2    A server status request
        Other values are reserved for future use

The AA bit specifies that the name server's answer is authoritative. The TC bit indicates that the message has been truncated (due to MTU length being exceeded, usually). The RD bit specifies that the query is a recursive one, that the name server should recursively query other name servers for the answer. The RA bit is set by a name server to indicate that it is willing to answer recursive queries. The Z field is reserved and currently MUST be zero. The Rcode value indicates an error condition from the responding server.

The remaining 'count' fields indicate the number of queries or answers present in the respective message fields.


Zone Files

Primary name servers load their data from 'zone files'

Most entries in a zone file are Resource Records

The first entry in a zone file MUST be the $TTL directive

Most Resource Records have a common 5-field format:

  [name]  [ttl]  [class]  type  data

The order of resource records mostly doesn't matter

The second entry in a zone file is always the SOA RR

NS records

The remaining records depend on the type of zone

Now have a look at some zone files

This is the master zone file for my own domain, xbalanque.net:

  ; start of authority record for xbalanque.net
  $TTL 7200
  @  IN  SOA  cs.colorado.edu.  admin.cs.colorado.edu. (
              20010421      ; Serial Number
                 86400      ; Refresh - every 24 hours
                  1800      ; Retry   - 30 minutes
               1209600      ; Expire  - 2 weeks
                  7200 )    ; Negative answers - 2 hours

       IN      A     198.11.19.5
       IN      MX    10 @
       IN      NS    cs.colorado.edu.
       IN      NS    ns.village.org.
       IN      TXT    "432 Gateway"

  localhost   IN    A     127.0.0.1

  coatlicue   IN    A     198.11.19.5
               IN    MX    10 @
               IN    HINFO    "SPARCstation Classic" "OpenBSD 2.8"

  ftp         IN    CNAME    coatlicue
  www         IN    CNAME    coatlicue
  mail        IN    CNAME    coatlicue
  xibalba     IN    MX       10 @
  xbalanque   IN    MX       10 @
  feanor      IN    MX       10 @

Note that the ORIGIN (@) is 'xbalanque.net'. Note also that I have an NS record that points to an off-site name server (ns.village.org). You have to make sure that all of the FQDNs specified in the zone file are terminated with dots.

There are a bunch of hostnames (e.g. 'xibalba' and 'feanor') that don't have IP addresses (no A records) but are simple MX records that have the ORIGIN as there only preference. I do this so that, if by chance I send mail from one of those hosts and the reply goes back to it directly, then the mail will just get sent to my gateway host.

The primary name server for xbalanque.net is 'cs.colorado.edu' (I don't manage the zone from my home machine, I manage it from work :). This a case where none of the authoritative name servers for the zone actually resides in the zone!

Another thing to point out is that I do not have a reverse zone. The University's ITS department controls the reverse zone for the entire 198.11.19.0/24 subnet. It would be a major pain for them to delegate out single IP address reverse zones to each person who wanted a static IP address. As a result they maintain the PTR record for my IP address.

   coatl % nslookup 198.11.19.5
   Server:  mroe-fs.cs.colorado.edu
   Address:  128.138.242.197

   Name:    coatlicue.Colorado.EDU
   Address:  198.11.19.5

I also run a stealth server inside my NAT'd home network. This server is not accessible from the outside world (which would be useless anyhow, because it resolves names for an RFC 1918 subnet!). Here is the Forward zone for my stealth server:

   ; start of authority record for xbalanque.net
   $TTL 3600
   $ORIGIN xbalanque.net.  ; added for clarity
   @  IN  SOA    xbalanque.net. tor.cs.colorado.edu. (
             2001031300         ; Serial Number
                   7200         ; Refresh - check every 2 hours for now
                   1800         ; Retry   - 30 minutes
                 604800         ; Expire  - 1 week (was 2 weeks)
                   7200 )       ; Minimum - 2 hours for now

                   IN      A       10.0.0.1
                   IN      NS      @
                   IN      TXT     "stealth DNS server for xbalanque.net"

   localhost               IN      A       127.0.0.1

   coatlicue               IN      A       10.0.0.1
   coalticue               IN      CNAME   coatlicue
   xibalba                 IN      CNAME   coatlicue
   www                     IN      CNAME   coatlicue
   quetzel                 IN      A       10.0.0.3
   xoxitl                  IN      A       10.0.0.4
   xbalanque               IN      CNAME   coatlicue
   bunky                   IN      CNAME   coatlicue
   hunapu                  IN      A       10.0.0.6
   boonie                  IN      CNAME   hunapu
   home-eye                IN      A       10.0.0.7
   judith                  IN      A       10.0.0.32
   mydhcp-33               IN      A       10.0.0.33
   feanor                  IN      A       10.0.0.34
   tala                    IN      A       10.0.0.35
   db-wired                IN      A       10.0.0.36
   mydhcp-37               IN      A       10.0.0.37
   mydhcp-38               IN      A       10.0.0.38
   dbw                             IN      A       10.0.0.39
   db-wireless             IN      CNAME   dbw
   mp3                             IN      A       10.0.0.40

   $GENERATE       41-128  mydhcp-$        A       10.0.0.$        ; dhcp address

The only really interesting thing to point out is the $GENERATE directive. This is a like a FOREACH loop to generate similar resource records. The second field specifies the range of values. the 'name' 'type' and 'data' portions of the record are given. A single '$' dollar-sign get's replaced with each value in the range. (Use a backslash to escape the dollar-sign if you actually want one in your names. This particular loop generates Address Records that look like:

   mydhcp-50   IN  A  10.0.0.50
   feanor % nslookup 10.0.0.50
   Server:  coatlicue.xbalanque.net
   Address:  10.0.0.1

   Name:    mydhcp-50.xbalanque.net
   Address:  10.0.0.50

The Internet class (IN) is implicit. Only a few records can be generated this way. Notably, NS, A, CNAME and PTR records can be.

Here is the Reverse zone file for my stealth server:

   ; start of authority record for xbalanque.net reverse zone
   $TTL 3600
   $ORIGIN 0.0.10.in-addr.arpa.  ; added for clarity
   @  IN  SOA    xbalanque.net. tor.cs.colorado.edu. (
           2001031300      ; Serial Number
           7200            ; Refresh - check every 2 hours for now
           1800            ; Retry   - 30 minutes
           604800          ; Expire  - 1 week (was 2 weeks)
           7200 )          ; Minimum - 2 hours for now

                   IN              NS              xbalanque.net.

   1               IN              PTR             coatlicue.xbalanque.net.
   3               IN              PTR             quetzel.xbalanque.net.
   4               IN              PTR             xoxitl-old.xbalanque.net.
   6               IN              PTR             hunapu.xbalanque.net.
   7               IN              PTR             home-eye.xbalanque.net.
   32              IN              PTR             judith.xbalanque.net.
   33              IN              PTR             mydhcp-33.xbalanque.net.
   34              IN              PTR             feanor.xbalanque.net.
   35              IN              PTR             tala.xbalanque.net.
   36              IN              PTR             db-wired.xbalanque.net.
   37              IN              PTR             mydhcp-37.xbalanque.net.
   38              IN              PTR             mydhcp-38.xbalanque.net.
   39              IN              PTR             dbw.xbalanque.net.
   40              IN              PTR             mp3.xbalanque.net.
   $GENERATE 41-128  $  PTR  mydhcp-$.xbalanque.net.

The 'dig' command also retrieves resource records


BIND - the Berkeley Internet Name Domain

BIND is the reference implementation of DNS

Running named

Controlling Bind


BIND - named Configuration

The Config file is a simple ascii text file

Address Match Lists specify a set of IP addresses

Before looking at the various configuration file statements it is important to understant the meaning and syntax of an Address Match List. This list just specifies a set of IP addresses or networks. Access Control Lists (acl) are just labeled versions of these lists.

The 'acl' statement gives a label to an address list

  acl  <acl-id>  {
   ! 1.2.3.4;  1.2.3/24; localhost;
  };

Remember that address match lists are successful on a first-match basis, so order matters. In the above example, the negated host must occur before the allowed subnet.

Also, an ACL must be defined with an acl statement before it is used in the config file. The acl statement must be top-level (that is, not embedded within some other statement. For that reason, acl statements are usually made first at the top of the configuration file.

The 'include' statement

  include  "/path/to/file";

The 'options' statement

The 'key' statement

  key  key_id  {
     algorithm hmac-md5;  // the only alg
     secret "XYZZY";
  };

The 'trusted-keys' statement is used with DNSSEC

The 'server' statement

  server  IP_ADDR  {
     option1 .. ;
     option2 .. ;
  };

The 'controls' statement configures access for 'rndc'

Or it configures access for 'ndc' if you are using Bind 8.

  controls  {
     inet IP_ADDR [port N] allow { acl_id8 }
            keys { key_id1; key_id2; };
  };

We can now look at the '/etc/rndc.conf' file

The 'zone' statement

  zone "domain_name" {
     type  master;  // or slave
     file  "path/to/zone/file";
  };

Other possible types are: 'stub', 'forward', and 'hint'

The 'view' statement is used to present different information based on the source of the DNS query

  view  "view_name"  {
     . . .
  };

For example, a site may want to present one set of data to its internal clients and a different (sanitized) set of data to external clients. Small private networks can make use of views in a big way by presenting full DNS information inside the network pertaining to the private addresses used on the network (one view). The server, for the same zone, can present different data records to the outside world (an external view), which is important when most internal hosts are not reachable on the net anyway.

The 'logging' statement is quite flexible

Now let's look at some configuration files

Here is the configuration for my current home network stealth server. This server is version 8.2.3. I am in *slightly* less haste to upgrade the server because it doesn't listen to queries from the Internet.

  /*
   * named master conf file for xbalanque.net
   *
   *  stealth server for a private network
   *
   * RCS: $Id: dns.pmp,v 1.4 2003/03/26 19:19:20 tor Exp tor $
   */

  options {
          directory "/";
          pid-file "/named.pid";
          listen-on { 10.0.0.1; 127.0.0.1; };
          forward first;
          forwarders { 128.138.129.76; 128.138.243.151; };
          query-source port 1053;
  };

  zone "xbalanque.net" {
          type master;
          file "xbalanque.forward";
      allow-transfer { 10.0.0.5; };
  };

  zone "0.0.10.in-addr.arpa" {
          type master;
          file "xbalanque.reverse";
  };

  zone "." {
          type hint;
          file "cache.db";
  };

  zone "0.0.127.in-addr.arpa" {
          type master;
          file "localhost";
          notify no;
  };

  logging {
      channel syslog_info {
                  syslog local3;
                  severity info;
          };
          channel syslog_tor {
                  syslog local1;
                  severity info;
          };
          channel no_info_messages {
                  syslog local2;
                  severity notice;
          };
          category parser       { syslog_tor; };
          category security     { syslog_tor; };
          category load         { no_info_messages; };
          category lame-servers { no_info_messages; };
          category default      { syslog_info; };
  };

I plan to upgrade to Bind 9 soon, and use 'view' statements to present 10.0-net data inside and real xbalanque.net data outside. The internal view will be a primary server for the zone, while the external view will be a secondary server (the real primary is cs.colorado.edu).

The CS department currently runs to separate nameserver processes to facilitate the 'views' concept (they are Bind 8 servers, so no 'view' statement). Yes, we plan to upgrade soon... Here is the current config file for the external server:

  //
  // ACL's
  acl CUnets {
          128.138/16; 198.11.16/24; 204.228.69/24; 127.0.0.1;
  };
  acl rfc1597 {
          10/8; 172.16/12; 192.168/16;
  };

  //
  // Global options
  options {
          version "wouldn't you like to know...";
          directory "/";
          pid-file "/named-external.pid";
          named-xfer "/named-xfer";
          notify yes;
          /*
           * Since this daemon serves external hosts we bind to the
           * external address, 128.138.243.151.
           */
          listen-on { 128.138.243.151; };
          transfer-source 128.138.243.151;
          /*
           * 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 128.138.243.151 port 53;
          /*
           * Choose local name servers over off-site ones.
           */
          topology {
                  localhost;
                  localnets;
                  CUnets;
          };
          /* 
           * Don't listen to known broken nameservers
           */
          blackhole {
                  209.234.73.115;
                  209.234.73.116;
                  209.234.73.117;
                  209.234.73.118;   
          };
  };

  //
  // Logging
  logging {
          // We want syslog stuff to go to local3
          channel syslog_info {
                  syslog local3;
                  severity info;
          };

          // We don't care about people's broken name servers
          category lame-servers { null; };

          // Use syslog_info channel unless we get a more specific match
          category default { syslog_info; };
  };

  //
  // Root servers cache
  zone "." in {
          type hint;
          file "named.cache";
  };

  //
  // Primaries
  //

  //
  // localhost
  zone "0.0.127.in-addr.arpa" in {
          type master;
          notify no;
          file "localhost";
  };

  //
  // CS
  zone "cs.colorado.edu" in {
          type master;
          file "forward-external/cs.colorado.edu";
  };

  //
  // CS reverse records (128.138.X.X)
  zone "245.138.128.in-addr.arpa" in {
          type master;
          file "reverse/245.138.128";
  };
  zone "244.138.128.in-addr.arpa" in {
          type master;
          file "reverse/244.138.128";
  };

  // ...  many other reverse zones edited out ...

  //
  // catbelly.com for garnett (garnett@catbelly.com)
  zone "catbelly.com" in {
          type master;
          file "catbelly/catbelly.com";
  };

  //
  // xbalanque.net for tor (tor@xbalanque.net)
  zone "xbalanque.net" in {
          type master;
          file "xbalanque/xbalanque.net";
  };

  // ... other zones for which we are primary deleted ...

  //
  // Secondaries
  //

  //
  // colorado.edu top level
  zone "colorado.edu" in {
          type slave;
          file "secondary/colorado.edu";
          allow-transfer { none; };
          masters {
                  128.138.240.1;
                  128.138.238.18;
          };
  };

  // ... other zones for which we are secondary deleted (about 50) ...

You can see that the CS department primary nameserver has a lot of duties! We are primary for a dozen or more different domains (like mine) and secondary for many dozens more.


TSIG - Transaction Signatures

TSIG uses shared-secrets and one-way hash functions

Generate a secret key with 'dnssec-keygen'

 % dnssec-keygen -a hmac-md5 -b 128 -n HOST  hostA-hostB


Dynamically Updated Zones

Dynamic Updates provides for automatic updating of zone data


Views

Views facilitate a concept known as 'Split DNS'


DNSSEC - Security Extensions

DNSSEC comprises a set of extensions using public keys

Generate a key-pair for a specific zone

  % dnssec-keygen -a RSA -b 512 -n ZONE xbalanque.net.
  Kxbalanque.net.+001+53599

Recall that the algorithm is the middle (001) number, while the last number is fingerprint of the key. Also recall that two files are generated, and this time it makes more sense.

  coatlicue% ls Kxbalanque.net.*
  Kxbalanque.net.+001+53599.key
  Kxbalanque.net.+001+53599.private

The public '.key' file, as mentioned above, is a DNS KEY Resource Record. Here is what it looks like (the file has ONE line in it, it is split apart for readability).

  coatlicue% cat Kxbalanque.net.+001+53599.key 
  xbalanque.net. IN KEY 256 3 1 AQPjRG1hINd3E7sw/F
          /cM4B2ZDOM+GWQoxeRLucwjLhin8TLdo552YjB
          wAXTllDUbbpfljIS7JeY5TGcyMUK0V/F

The name of the key is the 'domain name' for the KEY record. The class as usual is IN for Internet. The type, of course, is KEY. The remaining four values in the record are 'flags', 'protocol', 'algorithm' and 'key'. The flags field is a 16-bit value that designates the type of key and the uses for which the key is suitable (e.g. authentication, confidentiality). The 'protocol' field, 8 bits, designates the key use. A protocol value of '3' indicates DNSSEC. Other key uses might be IPsec or TLS. The 'algorithm' field value of '1' indicates that RSA is the algorithm. (You'll see a '3' for DSA). The 'key' field is public key.

Use the 'trusted-keys' statement to authenticate servers

Signing zone data with a zone's public key


References

DNS and Bind; Paul Albitz and Cricket Liu

The Purple Book (The Unix Sysadmin Handboook)

The ISC website: http://www.isc.org/