A DNS database source file is a human-editable form of the DNS database. It is compiled into the machine readable form by the DNS database compiler.
DNS database source files are simple text files. Conceptually they are a stream of lexical tokens forming a grammar. The tokenization process treats whitespace characters, including the newlines at the ends of lines, as token delimiters, and removes any part of a line following an unescaped hash ('#') character, which is a comment character. Tokens are either quoted strings (delimited by quotation marks, and capable of using C++-style escape sequences for embedding non-ASCII characters, quotation marks, and newlines in the strings), or unquoted strings, which comprise a sequence of non-whitespace characters.
The grammar describes a simple sequence of records. Each record begins with an unquoted token, which is taken to be a keyword. An unrecognized keyword is a syntax error. The keyword denotes the syntax of following tokens that comprise the whole record. Records can span multiple lines, for clarity and legibility. The end of a record is defined by the grammar, not by newlines in the file.
There are fifteen record types, introduced by the following keywords:
names or nameservermail or mailhubhostaliaschainservicehosthostfwdhostrevemptynegativeddnsuppersonznxfrdataEvery record type, except for server-side aliases, incorporates a Time To Live. This is the TTL that is to be employed by caching proxy DNS servers. Additionally, this TTL can be augmented by an inception date and an expiry date. Content DNS servers won't publish data until their inception dates have passed, and won't publish data whose expiry dates have passed. (The content DNS servers will also automatically adjust TTL values to ensure that cached copies of data on proxy DNS servers expire at the same time.)
This information is expressed as a single token, a ttl:inception:expiry token. This token contains just one numeric sub-field for a record with no inception or expiry dates. Otherwise it contains three numeric sub-fields, separated by colons. The inception and expiry date sub-fields can be blank (in which case they represent records whose inception has already occurred, or that do not expire, respectively) or can contain numbers that represent each date as the count of SI seconds since 1970-01-01 00:00:10 TAI.
Every record type, except for server-side aliases, incorporates a location. If the location field is not blank, the content DNS servers will only publish the data in the record to clients whose locations match the value in the location field. Locations allow for clients in different IP address ranges to have different views of the DNS database. (One common use of locations is to give servers in service records different server priorities or weightings for different client views.)
Alias records come in two forms: client-side and server-side. Server-side aliases, the preferred form, are handled internally within the database compiler and the content DNS servers. Client-side aliases, are handled, as the name suggests, by DNS clients. (There are various widely-documented difficulties with client-side aliases, from restrictions on their uses for locating SMTP Relay and content DNS servers to problems when they aren't properly maintained. They are not the preferred form.)
Alias records have the following syntax:
aliasdomain targetchaindomain ttl:inception:expiry location target
Service mapping records conceptually map a domain name, and a type of service, onto zero or more tuples comprising an IP address, a port number, a priority, and a weight.
This simple schema is complicated by two factors:
Although this is the underlying database schema of the Domain Name System (and hence is the schema used by the Internet Utilities), it is not the schema that is used by the DNS protocol.
The DNS protocol requires all service mappings to go through an intermediate domain name, for no really good reason. The way that DNS data are transferred in DNS protocol queries and responses divides up mappings such that domain names are mapped to an intermediate domain name, along with the port+priority+weight information, but to get the IP address one has to then map from that intermediate domain name to an IP address. Content DNS servers have to divide the mappings up in order to transmit them over the DNS protocol, and DNS clients have to re-assemble them to get the serving mapping proper.
For historical reasons, two particular service mappings are represented by
their own types of resource records in the DNS protocol, which lack
certain pieces of information. SMTP Relay server mappings and Content DNS
server mappings are represented by NS and MX
resource record sets. Other service mappings are represented by
SRV resource record sets.
Service mapping records have the following syntax:
nameserverdomain ttl:inception:expiry location priority weight port""address(es)…,priority weight port""address(es)…,… priority weight port intermediate-name address(es) …;mailhubdomain ttl:inception:expiry location priority weight port""address(es)…,priority weight port""address(es)…,… priority weight port intermediate-name address(es) …;servicedomain ttl:inception:expiry location priority weight port""address(es)…,priority weight port""address(es)…,… priority weight port intermediate-name address(es)…;
Notice that the syntax allows for blank intermediate names (expressed as
zero-length quoted string tokens). In this case, the database compiler
will invent intermediate names, by taking the domain name and prefixing
single-letter labels to it (adding an ns. or mx.
label for the case of nameserver and mailhub records),
picking the letters to ensure that intermediate names are unique. (This
naming scheme is designed to compress well in the DNS protocol, as well as
to not overlap first level subdomains. It also results in "glue" resource
records that are always in-bailiwick.)
Note: Do not use "rôle hostnames" as intermediate domain names, unless you make sure that the IP addresses published are the same in the service record as they are in any host record. If these IP address lists differ, then people performing DNS lookups will see odd results.
For examples, see best practice.
Host records conceptually map a host name to and from an IP address. Host records are less useful than service records, since host records either rely upon the notion of "well known port numbers", which is far from satisfactory for the number of services that a domain can provide, or rely upon the notion of "rôle hostnames" such as "www" and "ftp", which is both inefficient (requiring lots of duplication) and ambiguous (Does an "ftp" rôle name support HTTP service?).
Host mappings are either forward mappings, from host name to IP address, reverse, from IP address to host name, or bidirectional.
Host mapping records have the following syntax:
hostdomain ttl:inception:expiry location address(es) …;hostfwddomain ttl:inception:expiry location address(es) …;hostrevdomain ttl:inception:expiry location address(es) …;
Notice that the syntax allows multiple IP addresses in records. This creates a 1-to-many forward mapping or a many-to-1 reverse mapping, or both.
Some examples:
host hobbes.nmsu.edu. 40 "" 128.123.34.6 ; hostfwd in.parliament.uk. 172800 "" 194.60.38.10 ;
Here are various tips for best practice.
Prefer service records over host records. Don't use "rôle hostnames" unless existing naming schemes require you to. Instead leave host records for things that don't provide services, such as machines on a LAN.
Note:
It is not necessary to treat "glue names" as if they were
"rôle hostnames". Your content DNS server may have been known as
ns1.example.org. and your SMTP Relay server may have been
known as mx1.example.org., but the world properly only ever
looked up those names as "glue" names — the second halves of two-stage
NS and MX lookups. It is not necessary
to think of such "glue names" as if they should be preserved like
rôle hostnames. The world may have known about the rôle
hostname www.example.org., but it never knew to explicitly
ask for mx1.example.org. except as a result of
your telling it to via what you published in other DNS data.
Such names are intermediate domain names, not rôle hostnames.
Some examples:
# This is a nameserver record in the preferred style. nameserver british-library.uk. 172800 "" 0 0 53 "" 194.66.226.9 194.66.233.106 ; # See below. # These are intermediate names, not rôle hostnames, and so # need not be preserved. #host dns1.bl.uk. 172800 "" 194.66.226.9 ; #host dns2.bl.uk. 172800 "" 194.66.233.106 ;
Do not supply an explicit intermediate name in a service record, and list all IP addresses that have the same priorites, weights, and port numbers in a single sub-record. For examples:
service _http._tcp.pantz.org. 40 "" 40 0 80 "" 68.49.78.36 ; service _smtp._tcp.calomel.org. 60 "" 0 0 25 "" 71.179.97.249 ; service _pop3._tcp.fudo.org. 60 "" 0 0 119 "" 204.16.144.199 2002:CC10:90C7::0001 ; nameserver mod.uk. 172800 "" 0 0 53 "" 195.66.240.130 2a01:0040:1001:0035:0000:0000:0000:0002 192.5.29.50 ;
Sometimes one might find that the intermediate domain names are required, because they map to other people's machines whose IP addresses may change arbitrarily, without one being informed. For examples:
mailhub os2bbs.com. 3600 "" 10 0 25 m2.spamarrest.com. , 20 0 25 r1.spamarrest.com. ;
Note that you are giving other people control over where your domain's published services are when you do this. This is not a thing to do lightly. It is strongly recommended that you list services by their IP addresses, with blank intermediate names, and only use this form as a rare exception.
As Jim Nelson notes,
in an ideal world, everyone would be using service DNS lookups for all
server protocols, and both rôle hostnames and the NS
and MX resource record types would be obsolete. In such an
ideal world, one's database source file would look like this:
# In this example, services are normally provided on IP addresses # e.f.g.h and i.j.k.l with a 60/40 load balancing split. # In the event of network outage, fallback is to address m.n.o.p # which shouldn't be used in normal operation (because it serves up # placeholder WWW pages announcing a server outage, for starters). # Record for HTTP clients: service _http._tcp.some.corp. 604800 "" 10 60 80 "" e.f.g.h , 10 40 80 "" i.j.k.l , 20 0 80 "" m.n.o.p ; # Record for SMTP Relay clients: service _smtp._tcp.some.corp. 604800 "" 10 60 25 "" e.f.g.h , 10 40 25 "" i.j.k.l , 20 0 25 "" m.n.o.p ; # Record for POP3 clients: service _pop3._tcp.some.corp. 604800 "" 10 60 110 "" e.f.g.h , 10 40 110 "" i.j.k.l , 20 0 110 "" m.n.o.p ; # Record for NNTP clients: service _nntp._tcp.some.corp. 604800 "" 10 60 119 "" e.f.g.h , 10 40 119 "" i.j.k.l , 20 0 119 "" m.n.o.p ; # Record for DNS clients: service _domain._udp.some.corp. 604800 "" 10 60 53 "" e.f.g.h , 10 40 53 "" i.j.k.l , 20 0 53 "" m.n.o.p ;
The world at large has not reached this ideal. Whilst many protocols do employ service DNS record lookups — and there are a lot more of those than people think —, some HTTP clients, some SMTP Relay clients, and some DNS clients still do not use service lookups. (The clients in the Internet Utilities are all service-record aware, and can all be configured to use service lookups. So, too, is the proxy HTTP server, although the resolving proxy DNS server does not use service lookups to find content DNS servers.) Coping with such clients currently requires a few more records in a DNS database source file:
# Old SMTP Relay clients are almost there, but won't do load balancing: mailhub some.corp. 604800 "" 10 60 25 "" e.f.g.h , 10 40 25 "" i.j.k.l , 20 0 25 "" m.n.o.p ; # Notice the omission of m.n.o.p in the following. Old-style clients # do not know, and cannot be told via the DNS, not to use it in normal # operation. (This lack is one of the disadvantages of old-style data # compared to service records.) # Old HTTP clients need a rôle hostname: hostfwd www.some.corp. 604800 "" e.f.g.h i.j.k.l ; # Old Content DNS clients at least don't need rôle hostnames, # but won't do load balancing or fallback: nameserver some.corp. 604800 "" 10 60 53 "" e.f.g.h , 10 40 53 "" i.j.k.l ;
The mailhub and nameserver records are
intentionally designed to be easily convertable to service
records (and vice versa, of course), to aid in the progress towards the
ideal. Hence the inclusion in their syntax of information that is not
actually, because of the way that the DNS protocol works, publishable to
the world.