- Domain Name System Essentials
Another book in progress about DNS ... We have over 200 pages of an unreleased DNSSEC book to integrate, plus courseware used 20 to 10 years ago to rewrite into this book ...
DNS is one of the key building blocks of the Internet and is used by nearly every device and human on the Internet, internal network including ATMs, cameras, printers, car navigation system, and more. DNS is the Domain Name System. Its primary and common use is looking up Internet (IPv4) addresses using a name, such as a website domain name. But it is so much more than that.
DNS is a database system. The database looked at is massive. It contains over 365 million domain names and many times more sub-domain names. A standard domain name requires at least a couple record values, and commonly has around eight different values. Some domain names contain or reference thousands to even millions of sub-domain records within it. The Domain Name System represents billions of unique records which are managed by tens of millions of individuals and organizations. The changes are done using different tools and techniques - some changed infrequently (like less than once a year) and others many times per second. Some of the records are queried rarely while others are queried hundreds of thousands of times per second. Accordingly, no single database system scales like DNS.
DNS is a distributed database - the largest distributed database in the world. It allows owners or administrators to define their record values which are shared to others when queried. It also allows load balancing by distributing even identical queries to multiple systems.
This database, the DNS system, is structured in a tree format. It begins with a root DNS server where an initial lookup is done. A root server does not have (and cannot have) all the answers for the entire DNS. It simply knows about and tells you about the next servers to ask. These next servers, known as the Top Level Domain (or TLD) servers, are like .COM, .NET, .UK, .EDU, and others domain names for example. They also don't know about all the possible data, but do have information for finding all the "second-level" domains (SLD) under them. Generally a third server is asked to get answers for most of the Internet use. When a server refers to another server, this is called a delegation.
. root (the dot) / \ com. gov. TLD (top level domain) | | disney.com. whitehouse.gov. SLD (second level or final domain)
The database contains resource records. The resources are domain names, a class, and a record type. (In database terms, this is the "key".) The domain name is read from left to right, but used from right to left with period-delimited words known as labels. The class basically defines the schema for the record data associated with the resource. For the common use, this is the Internet (IN) class. The resource record type identifies the format for different types of data. Together these define the query format. The most common query is for an IPv4 address type (A).
The resource record data (RDATA) is the data or value associated with that query label/class/type tuple. There may be multiple data entries or values for a single resource record. This is called a resource record set (RRSET). The database can also contain multiple data entries for the same domain name but for different types. The resource record also contains a time-to-live counter, TTL, which tells a client how long it can store or reuse the values. All the records contained in a single database, usually under a single domain name, is commonly known as a zone.
DNS is a network client/server protocol commonly used over both UDP and TCP.
The clients may be identified in different ways. An end-user client or application layer asks a network server directly or utilizes a local system DNS API or service which can forward the query on or intelligently attempt to find the answer itself. Simple forwarding of a query is called a stub client. Finding the answer from the "root" server and its descendents is called iteration and the service is called a recursive resolver.
A DNS resolver server is effectively a client itself. It accepts incoming queries and returns an answer, It may contain the data locally to return, or on behalf of its questioner, it can iteratively ask other servers the same question. Normally, a resolver server is also a caching server. It stores, reuses, and shares previously looked up answers (resource records) to save time and network resources. These resource records have a TTL provided to them that tell the cache how long they can keep and share that data. These servers handling DNS, whether they are serving original data or sharing cached data, are known as nameservers.
As an example, a lookup for www.stanford.edu (for its address record) against an empty caching resolver will do these steps:
1) Ask a single root server for the www.stanford.edu address record. (It has the IP address for the root servers hard-coded or locally configured.)
The root server will return the server names for the nameservers to ask instead, such as f.edu-servers.net, and their IP addresses. (It will tell the resolver it can cache this information for 2 days.)
2) The resolver will then ask one of these next nameservers for the www.stanford.edu address.
The responsible name server for "edu" doesn't have the answer, but will return the server names for the nameservers that know about stanford.edu, such as argus.stanford.edu (and possibly an IP address). (It also tells the resolver it can cache this information for 2 days.)
3) The resolver then asks one of these next nameservers the same question.
This server has an answer which the resolver also can cache and returns to the client.
Note if it doesn't have the IP address for the intermediate nameservers, the resolver will need to follow the same steps to get the address for the nameservers. When addresses are provided by default when a nameserver tells you what other nameserver to use, this is called "glue".
On a next query for some other domain name under "edu" the resolver doesn't need to ask the root server again (as long as the TTL timer hasn't expired), but can use the cached nameserver(s) instead.
Nearly all use of DNS is to lookup a name to get an address. The DNS lookup support is included with an operating system and some applications also provide their own client implementation. Client tools are available to do lookups, such as the command-line tools: host, getent, ping, nslookup, dig, and many others. The following are a few examples.
The host command looks up IPv4 and IPv6 addresses (known as DNS A and AAAA records, respectively) and the mail servers and priorities (known as the DNS MX record) for the name:
$ host wikipedia.org wikipedia.org has address 18.104.22.168 wikipedia.org has IPv6 address 2620:0:861:ed1a::1 wikipedia.org mail is handled by 10 mx1001.wikimedia.org. wikipedia.org mail is handled by 50 mx2001.wikimedia.org.
The getent tool uses the local hostname address lookup database to lookup an address:
$ getent hosts wikipedia.org 2620:0:861:ed1a::1 wikipedia.org
The ping command is example of a tool that will lookup a single address before it does other work:
$ ping -c 1 wikipedia.org PING wikipedia.org (22.214.171.124) 56(84) bytes of data. 64 bytes from text-lb.eqiad.wikimedia.org (126.96.36.199): icmp_seq=1 ttl=60 time=0.714 ms --- wikipedia.org ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.714/0.714/0.714/0.000 ms
The nslookup command-line tool is an interactive client for looking up details via DNS, but can also be used one at a time:
$ nslookup wikipedia.org Server: 127.0.0.1 Address: 127.0.0.1#53 Non-authoritative answer: Name: wikipedia.org Address: 188.8.131.52
A well-known DNS client tool is DiG which can provide full details from DNS. Here is an example of an abbreviated response with a single answer only:
$ dig +short wikipedia.org 184.108.40.206
These tools can also do lookups of IP addresses to find hostnames, if available, such as in the previous ping example and in the following:
$ host 220.127.116.11 18.104.22.168.in-addr.arpa domain name pointer text-lb.eqiad.wikimedia.org.
Some of the examples above query DNS directly while some of them use local name lookup routines to get results before trying DNS. This book will cover these types of lookups and much more. It will teach how the queries work behind the scenes, including what data is sent and received and from where.
As a simplified explanation, when a normal query is done, first a cache is looked at to see if the name and answer for the query type was previously and still stored. If so, that answer is provided. If not, it falls back to use DNS to iterate asking questions of possibly multiple servers leading to the best source to retrieve the answer. Before we get into detail, let's cover more about the data that is stored.
When providing addresses for a name or looking up addresses for a name, the key record types are the A record for IPv6 addresses, AAAA for IPv6 addresses, and the NS record to define the nameserver names that are responsible - or authoritative - for the name to lookup.
The common or standard way these are represented or stored in human-readable formats is: name, time-to-live, class, type, and value (or answer) separated by spaces and defined on a single line. Notice the following two related examples.
wikipedia.org. 86154 IN NS ns0.wikimedia.org. wikipedia.org. 402 IN A 22.214.171.124 ns0.wikimedia.org. 86346 IN A 126.96.36.199 wikimedia.org. 86128 IN NS ns0.wikimedia.org.
In the first example, a NS record for the name on the left is defined by the name on the right. The address for that name on the right is defined in the second example's A record entry. The first column is the domain name. Notice it ends with a period which indicates it is the end of the name. (If it does not end with a period in a DNS storage file, it is likely to get a name appended to it. This is covered later.)
The second column is the time-to-live or TTL. This is the time in seconds that this entry may be stored and reused locally or may be shared with others, before having to lookup this answer again (for the specific name and type). These examples show real world TTLs that have already started to decrement as counters.
The third column is the DNS class. These examples and basically all DNS usages uses the Internet class, abbreviated as IN. (As mentioned before, this defines a database schema for the available types.)
The type in the fourth column is also called a resource record type or record type and commonly abbreviated as RRTYPE. There are 14 common record types which this book will cover in detail, plus many others which will be introduced.
The final columns provide the values for the name/class/type tuplets. Two of the most common types are the A address record and the NS record which only have a single value for a single record. The address record is simply a human-readable dotted quad IPv4 address. The nameserver field is a hostname of DNS server which is responsible for the domain name. This is used for delegation or for identification.
A name with a record type may have multiple values. This is called a set or resource record set, abbreviated as an RRSET. The following is an RRSET which is a set of three records in this example:
wikimedia.org. 85980 IN NS ns1.wikimedia.org. wikimedia.org. 85980 IN NS ns2.wikimedia.org. wikimedia.org. 85980 IN NS ns0.wikimedia.org.
A single query asking for that name within that class for that type may get a multiple-part answer. Often, the same value may be repeated (duplicated) in an RRSET. The order they are delivered and used varies, but the point is a single question can result in multiple answers and one (or more) can be used. The TTL is not part of the query but is returned in the answers. For brevity in this book, the IN (Internet) class will be assumed in all queries and examples unless specifically teaching about alternate classes.
A DNS query or question has multiple options and flags which are covered through out this book. A DNS response has multiple flags and parts also covered in this book. The most common part of a response is the ANSWER section, but there are also response sections known as the AUTHORITY section which tells where to query instead via a list of NS records; and the ADDITIONAL section which provides supplement information such as corresponding A addresses (the "glue") for the AUTHORITY NS records. Examples are shown in the following.
Using this same name as an example, looking up its address the first time would commonly involve the following iterative steps by a recursive resolver.
First, ask a root server to learn who is responsible for wikipedia.org. The root servers are the starting point. Twelve organizations run hundreds to thousands of servers for 13 IPv4 and and IPv6 addresses using distributed routing technologies (such as Anycast). Their alphabet-labeled names are a.root-servers.net. through m.root-servers.net. The IP addresses for the root servers are builtin or already configured and primed into the DNS resolver. You don't have to do this priming step as this is done automatically (and this will be covered in detail later). Nor do you have to do the initial query, but if you did it would look like the following:
$ dig @j.root-servers.net wikipedia.org ; <<>> DiG 9.10.5-P1 <<>> @j.root-servers.net wikipedia.org ; (2 servers found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60180 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 6, ADDITIONAL: 13 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1472 ;; QUESTION SECTION: ;wikipedia.org. IN A ;; AUTHORITY SECTION: org. 172800 IN NS a0.org.afilias-nst.info. org. 172800 IN NS a2.org.afilias-nst.info. org. 172800 IN NS b0.org.afilias-nst.org. org. 172800 IN NS b2.org.afilias-nst.org. org. 172800 IN NS c0.org.afilias-nst.info. org. 172800 IN NS d0.org.afilias-nst.org. ;; ADDITIONAL SECTION: a0.org.afilias-nst.info. 172800 IN A 188.8.131.52 a2.org.afilias-nst.info. 172800 IN A 184.108.40.206 b0.org.afilias-nst.org. 172800 IN A 220.127.116.11 b2.org.afilias-nst.org. 172800 IN A 18.104.22.168 c0.org.afilias-nst.info. 172800 IN A 22.214.171.124 d0.org.afilias-nst.org. 172800 IN A 126.96.36.199 a0.org.afilias-nst.info. 172800 IN AAAA 2001:500:e::1 a2.org.afilias-nst.info. 172800 IN AAAA 2001:500:40::1 b0.org.afilias-nst.org. 172800 IN AAAA 2001:500:c::1 b2.org.afilias-nst.org. 172800 IN AAAA 2001:500:48::1 c0.org.afilias-nst.info. 172800 IN AAAA 2001:500:b::1 d0.org.afilias-nst.org. 172800 IN AAAA 2001:500:f::1 ;; Query time: 40 msec ;; SERVER: 188.8.131.52#53(184.108.40.206) ;; WHEN: Wed Jan 06 21:08:24 CST 2021 ;; MSG SIZE rcvd: 444
In the above DiG example, a single root server was asked for an A address record. This remote server did not know about the name queried and did not provide any answers. But it did know about the org. Top Level Domain so it provided an AUTHORITY section with six NS records. One or more of these NS targets can be used to ask about the initial query name. (By default, DiG asks for the A address record type. Further details about the DiG command and its outputs will be explained in this book.)
This root server knows about the addresses for those NS hostnames, so it provided 13 records for them in the ADDITIONAL section.
The root servers know about all 1500-plus Top Level Domains - the right-hand side, last label of domain names. This includes the original com, org, net, edu, gov, mil, and arpa domain names; 255 country-code top level domains (also known as ccTLD) such as uk, us, and jp; and many generic top level domains (gTLD) like actor, news, and wedding.
The root servers can provide the nameservers names (NS) and their addresses for the many TLDs, such as in the previous org example. These second level of servers can provide answers closer to the names to lookup.
The second step in this simple recursing example is to query against one of those IP addresses above. For example, one of the AUTHORITY section records has a NS of c0.org.afilias-nst.info and the ADDITIONAL section has 220.127.116.11 as its IP address - which can be used for next query:
$ dig @18.104.22.168 wikipedia.org ; <<>> DiG 9.10.5-P1 <<>> @22.214.171.124 wikipedia.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10355 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 3, ADDITIONAL: 4 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;wikipedia.org. IN A ;; AUTHORITY SECTION: wikipedia.org. 86400 IN NS ns0.wikimedia.org. wikipedia.org. 86400 IN NS ns1.wikimedia.org. wikipedia.org. 86400 IN NS ns2.wikimedia.org. ;; ADDITIONAL SECTION: ns0.wikimedia.org. 86400 IN A 126.96.36.199 ns1.wikimedia.org. 86400 IN A 188.8.131.52 ns2.wikimedia.org. 86400 IN A 184.108.40.206 ;; Query time: 36 msec ;; SERVER: 220.127.116.11#53(18.104.22.168) ;; WHEN: Thu Jan 07 19:18:36 CST 2021 ;; MSG SIZE rcvd: 154
The above example again has no answers but does point to more NS nameservers (with corresponding glue addresses) to try, in this case specific for the queried name.
So continuing with this example, we will do a DNS query using one of these newly found nameservers:
$ dig @22.214.171.124 wikipedia.org ; <<>> DiG 9.10.5-P1 <<>> @126.96.36.199 wikipedia.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20540 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1024 ;; QUESTION SECTION: ;wikipedia.org. IN A ;; ANSWER SECTION: wikipedia.org. 600 IN A 188.8.131.52 ;; Query time: 7 msec ;; SERVER: 184.108.40.206#53(220.127.116.11) ;; WHEN: Thu Jan 07 19:21:24 CST 2021 ;; MSG SIZE rcvd: 58
Notice here that it has one answer which may be cached and reused for 600 seconds. It also doesn't have any AUTHORITATIVE nor ADDITIONAL section records in the response. This simple iterative resolution is done. To summarize as if this was done automatically with a resolver: it started with one of the root nameservers hardcoded or primed in the resolver; then iteratively asked the same question to one new nameserver for each depth until it finally gets an answer.
There are other variations in this resolution, such as using intermediate nameservers already known from a cache (and not expired from their TTL), asking for and utilizing security features, trying multiple nameservers simultaneously (including via IPv6), and others.
Some of the previous examples show header "flags" as reported back from a remote nameserver. The final simple example above showed an "aa" flag which indicates that sending nameserver is authoritative for the name asked about - in other words, it is a nameserver where that domain name is officially configured to serve its official record answers. (We will talk about EDNS Flags later.)
The DNS message flags are sent in original queries and also sent back in responses. They are also called "bits".
As seen earlier, two other common flags are "qr" meaning it is a response to the query and "rd" (recursion desired) which means you asked for the remote nameserver to do the entire recursion for you (versus you doing each iteration). In those previous DiG examples, there were DiG comments saying that this recursion was requested but not provided. If a nameserver can do recursion for others, then it will return back an "ra" flag indicating it is available.
Another response flag is the "tc" flag which indicates that the remote server truncated the response over a UDP connection. This tells the client to try again using TCP instead. This will be covered in detail later in this book.
DNS queries are sent with a transaction identification number (also known as a TXID), such as seen in the previous ``id: 20540'' example. A response is sent back with the corresponding ID number which the resolver or client uses to match answers with the question. It also matches on the UDP or TCP source port and the query tuple too. The ID number ranges from 0 to 65535.
This question/answer matching is insecure and can be abused by malicious senders by racing to send back an alternative spoofed answer instead with both a predicted or guessed source port number and TXID. This will be covered further in the cache poisoning section. Additional values for comparisons include 0x20 and DNS Cookies. DNS Security (DNSSEC) data may also be used to confirm that responses are not modified in transit.
DNS servers also return a status code, also known as a RCODE, when responding. (Such as seen in the previous DiG examples showing ``status: NOERROR'' comments.) The common RCODEs are:
If a nameserver knows about the query and sends back an answer or AUTHORITY section records, it will provide a NOERROR response code meaning there wasn't a problem.
If a query for a name exists but for a different resource record type, no ANSWER section will be returned (and the answers count will be zero) and, instead, a SOA record will be returned in the AUTHORITY section. This is not an error so a NOERROR status will be provided. An example of known name with an unknown type follows:
$ dig wikipedia.org -t TYPE2021 ; <<>> DiG 9.10.5-P1 <<>> wikipedia.org -t TYPE2021 ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37545 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;wikipedia.org. IN TYPE2021 ;; AUTHORITY SECTION: wikipedia.org. 3397 IN SOA ns0.wikimedia.org. hostmaster.wikimedia.org. 2020120918 43200 7200 1209600 3600 ;; Query time: 0 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Jan 23 15:00:23 CST 2021 ;; MSG SIZE rcvd: 103
The SOA, or Start of Authority, record type is a special type with multiple purposes. It will be explained in this book.
If no record exists for the queried name and type (and class), the NXDOMAIN status is returned (for no such domain). The responding nameserver won't provide any answer, but will return a SOA record in the AUTHORITY section. See the following status and AUTHORITY section example from querying for a domain that does not exist:
$ dig doesnotexist.wikipedia.org ; <<>> DiG 9.10.5-P1 <<>> doesnotexist.wikipedia.org ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 5945 ;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;doesnotexist.wikipedia.org. IN A ;; AUTHORITY SECTION: wikipedia.org. 3114 IN SOA ns0.wikimedia.org. hostmaster.wikimedia.org. 2020120918 43200 7200 1209600 3600 ;; Query time: 6 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Sat Jan 23 15:05:06 CST 2021 ;; MSG SIZE rcvd: 116
If the nameserver is not configured to provide an answer for the client - or is specifically configured to not provide answers for a client, a REFUSED status code is returned. When the client's query is refused, no records are returned. The following example shows that a nameserver refuses to provide an answer for an unrelated domain:
$ dig @ns0.wikimedia.org. army.mil ; <<>> DiG 9.10.5-P1 <<>> @ns0.wikimedia.org. army.mil ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 49185 ;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1024 ;; QUESTION SECTION: ;army.mil. IN A ;; Query time: 39 msec ;; SERVER: 18.104.22.168#53(22.214.171.124) ;; WHEN: Sat Jan 23 15:11:51 CST 2021 ;; MSG SIZE rcvd: 37
Note that the client may be able to get answers for other queries from the same target nameserver, so a REFUSED doesn't indicate that all possible queries from the client are rejected.
If the nameserver has a problem, it may return a SERVFAIL status. This is an overloaded return code as it may have many different reasons which in standard DNS are not easily explained for the client. When this server failure is returned, the DNS response will not include any answers or records.
Server failure examples may include: the nameserver is configured to know about the domain, but couldn't load its domain data (so had nothing to share); all nameservers delegated to provide answers are unvailable; a nameserver name didn't have any corresponding address; or a security validation failed. These and other SERVFAIL statuses with examples will be covered further in this book.