DNS might not be the oldest, but is for sure one of the oldest and still very important services building the core of the Internet. The domain name service, or DNS for short, is one of the core services of the internet used every day. It is a highly distributed and hierarchical system. Without the DNS service, name resolution would not be possible. It is essential in translating domain names into IP addresses.
DNS in a nutshell
From the early stages of “the Internet” a translation between host names and IP addresses was necessary as IP addresses were hard to remember and could change over time. Whether it was for the name of a website or the hostname of a mail server, a host-name to address-mapping was required to translate all of those names into IP addresses for all the Internet connected devices to connect to those and many other servers and services.
RFC1034 summarises the state of name resolution before the adoption of DNS like this: “Host name to address mappings were maintained by the Network Information Center (NIC) in a single file (HOSTS.TXT) which was FTPed by all hosts”. With the size of the Internet nowadays this concept of managing name resolution in this way is absolutely unthinkable. Even back then, a better solution was needed. This is where the Domain Name System (DNS) was invented.
(Jon Postel in 1994, with map of Internet top-level domains. Photo by Irene Fertik, USC News Service. Copyright 1994, USC. Permission granted for free use and distribution, conditioned upon inclusion of the above attribution and copyright notice.)
The DNS system is decentralised, allowing each owner of a so-called zone to manage his DNS entries autonomously. To be able to find information in such a massive decentralised system, a hierarchical structure was introduced. The so called “root zone” often shown as “.” is the top of the hierarchy and the known starting point for lookups.
The root DNS servers are well known and all DNS resolvers include the list of root DNS servers. From the root zone, all top-level-domains (TLD’s) are delegated. Delegation means, the root zone contains DNS records (NS records) delegating the control of sub zones to other name servers. As an example, the “net” zone is delegated from the root zone to the name servers of the “net” TLD using NS records.
The name server of the “net” TLD then delegates further sub zones to other name servers. As an example, the “tinned-software.net” domain is delegated from the “net” TLD name servers to the name servers responsible for this domain. The example shows the TLD “net” and the name “tinned-software” separated by the use of a “.” character. The “.” character is used in DNS to separate the hierarchy levels (nodes).
To continue the example, the well known “www” of “www.tinned-software.net”, is represented as a leaf node in the DNS hierarchy. This “www” leaf node is usually represented by an address resource record (A or AAAA record). Even with the example being one of the most common structures in DNS, the hierarchy does not need to stop there, subdomains are common, as well as names not starting with the well known “www”. For example, “blog.tinned-software.net” uses the “blog” leaf node name.
(Example hierarchy of the DNS system.)
Relation between zones
Navigating the DNS hierarchy requires a relation between the zones.
The relation is often referred in relative terms like “parent zone” which represents the Zone delegating to the zone in question. For example, from the perspective of the “tinned-software.net” zone, the parent zone is the “net” zone.
That does not imply a relation between zones and the hierarchical levels represented by the “.” separator. Not every level represents its own zone. Records like “www.tinned-software.net” as well as “non.existing.name.tinned-software.net” could be in the same zone.
In DNS, a Zone represents a portion of the DNS system managed as one entity. In other words, a zone represents a defined part of the domain name system like “tinned-software.net” in which the owner of the zone can create any records they like. Within the zone, the owner can create any record ending in the delegated name. In the example, “tinned-software.net” being delegated to me, I am able to create any record I want within that zone as long as they are under the “tinned-software.net” portion. Within a zone, other delegations to other zones are possible too. Those delegations allow to delegate a sub-portion of the zone to other zones.
The authoritative name server
An authoritative DNS server is the server authorised to answer requests for a certain zone. In other words, the authoritative DNS server is able to answer DNS queries for a defined portion of the DNS space without consulting any other DNS server. Those portions, called zones, are configured on the authoritative DNS server. Each of the zones contain so called resource records (RR) that can be queried. There are many different types of RR. “NS” records are the ones used to delegate responsibility between zones.
Lets take the “tinned-software.net” example again. The root zone servers authority is to answer the question which DNS servers are authoritative for the “net” zone using the NS records for the “net” name servers. The “net” DNS servers will respond with their “known” part of the queried name and respond with the details for the responsible DNS servers for the “tinned-software.net” zone.
The glue records
In many cases, the NS records point to a DNS server name inside the delegated zone. With that said, this name can not be resolved as the DNS server name is inside the zone the server is responsible. To overcome this issue, so called “clue records” are added to the parent zone. Those are normal address records (A or AAAA) pointing to the IP address of the DNS servers referenced in the NS records.
As example, one of the authoritative DNS server for the “net” zone, “a.gtld-servers.net.” is delegated from the root zone. As the NS record is an address inside the “net” zone, an additional glue-record needs to be added to the “root” zone to resolve the name “a.gtld-servers.net.” before a resolver can access the DNS server to resolve any domain like “blog.tinned-software.net”.
When a domain name is resolved, the so called “resolver” will walk through this hierarchy to find the requested record. A resolver asked for the address record of “blog.tinned-software.net” would start by sending a request for “blog.tinned-software.net” to the only known authoritative servers, the root servers. The set of root servers are known by the resolver. The root DNS servers will respond with the delegation information (the NS records) for the “net” zone. The resolver will in turn send the same request to the DNS server for the “net” zone. The DNS servers for the “net” zone might also return delegation information pointing to the DNS server of the domain. As before, the resolver will send the same request now to the domain’s DNS server. In this example the DNS server authoritative for the “tinned-software.net” domain has the address records (A or AAAA records) and will return it to the resolver. But the delegations could go on with every level of sub-domain. Once it has the address records from the “tinned-software.net” name servers, the resolver will return those to the client.
While walking through the hierarchy of the DNS structure, the resolver will cache information to speed up the process of resolving of future requests. With the example above in mind, the resolver will cache the response from the root DNS server to speed up future queries to the “net” TLD as well as all the other responses. With the cached information, when asked for “www.tinned-software.net”, there is no need to send the query to the root name servers or the “net” name servers. The resolver “knows” the responsible name server from the cached information and sends the query directly to the “tinned-software.net” name servers. The same way, when a client requests a different name ending in “.net”, the resolver will skip the root server and send the query straight to the “net” name server.
This caching of DNS data is very important and speeds up the resolving process. As with any caching, the cached information needs to be renewed from time to time to ensure the information is not outdated. Those caching times are controlled by the authoritative DNS server with the TTL value on a RR level. Every name server returns with each resource record a Time-To-Live (TTL) indicating its caching time. When the caching time expires, the resolver will discard those from its cache and resolve the necessary information again.
In DNS, records do not have to be unique, with only a few exceptions. The most often used case where multiple nearly identical records are used are the name server (NS) records. Usually a zone lists its name servers as NS records. To ensure high availability, a zone nearly always lists more then just one name server. Lets take the “example.com” zone which, at the time of writing, shows two name servers.
example.com. 85458 IN NS a.iana-servers.net. example.com. 85458 IN NS b.iana-servers.net.
The example shows two NS resource records with identical name, TTL, class and type. Only the record-data is different. This allows to add any number of NS records to a zone to achieve the level of high availability required. Such a set of records is always sent in one answer which is why such a set of resource records is called a resource record set (RRset).
How is a name server chosen to be queried? When a resolver receives an answer like this it needs to choose one of the name servers. The detail of how this works differs slightly depending on the operating system. Often, the name server responding with a resource record set will shuffle the records each time it is queried. A client can then always choose the first. Other clients might choose randomly from the list. In any way, this approach will distribute the load over the returned name servers.
Additionally, a resolver would choose a different record after a timeout if the first chosen one would not respond. This allows for a fallback to ensure a higher availability even with some name servers not being reachable.
The concept of having multiple records with the same name, class and type is also possible with many other record types. Most commonly used with address records, this technique is called Round-Robin.
It allows for a DNS based cluster / load-balance-like setup. round-robin is no replacement for a real load-balancer but its effects are similar. Having multiple address records where only the IP address in the record data field differs will result in a distribution of traffic across the provided IP addresses. There is no fine control over the distribution like with a real load-balancer but in some situations a round-robin distribution is just enough.
Such records can be created with many different record types with only very few exceptions. The biggest exception being CNAME records. CNAME records have to be unique. If a CNAME record is defined, there is no other record allowed with the same name – not even if the other record is of another type.
Inspect the domain name system
Every time a DNS name is resolved, the client sends a request to the resolver. There are utilities to send DNS requests like these to inspect the response from the resolver or other name servers. One of these utilities is “dig”.
The dig(1) utility is part of the BIND name server project from Internet Systems Consortium (ISC) and allows you to interact with name servers.
Simple DNS query
The most simple request for the address of “www.example.com” contains just the “dig” command and the name to be resolved as the only argument.
$ dig www.example.com ; <<>> DiG 9.11.26-RedHat-9.11.26-6.el8 <<>> www.example.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 43215 ;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 5 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1232 ; COOKIE: 47d568510403f8b04211a101627973d9d5a7d31b293d3e57 (good) ;; QUESTION SECTION: ;www.example.com. IN A ;; ANSWER SECTION: www.example.com. 86400 IN A 188.8.131.52 ;; AUTHORITY SECTION: example.com. 85458 IN NS a.iana-servers.net. example.com. 85458 IN NS b.iana-servers.net. ;; ADDITIONAL SECTION: a.iana-servers.net. 895 IN A 184.108.40.206 b.iana-servers.net. 895 IN A 220.127.116.11 a.iana-servers.net. 895 IN AAAA 2001:500:8f::53 b.iana-servers.net. 895 IN AAAA 2001:500:8d::53 ;; Query time: 101 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon May 09 20:04:41 UTC 2022 ;; MSG SIZE rcvd: 224
This simple command will use the system’s configuration to determine the resolver to query. It sends the query for the address record to the resolver and shows the returned result.
The output shows lines starting with a semicolon “;” indicating a comment. Those comments contain a lot of useful details for investigating name server responses. For this simple example, most information in the comments can be ignored, with the exception of the all capital letter section names in the comment lines.
For inspecting the DNS response, the “QUESTION SECTION” shows the request. The “ANSWER SECTION” shows the answer but not as a comment. The answer show, the name field on the left, the TTL as the second field, the so-called class (“IN”) and the record type “A”. The last field of the answer is the record data. In case of a A record, this is the IP v4 address.
With the same format as in the answer, the “AUTHORITY SECTION” containing the authoritative name server for the zone containing the requested record(s). The “ADDITIONAL SECTION” simply shows the address records for the name servers listed in the “AUTHORITY SECTION”.
In this particular example, the “ADDITIONAL SECTION” doesn’t only return A records with IP v4 addresses, but also AAAA records for IP v6 address records.
Inspect the DNS hierarchy
The previous request just showed the request to the resolver and its response. To inspect the hierarchy of zones and their name servers, the option “+trace” can be used. The dig manpage describes it as follows.
When tracing is enabled, dig makes iterative queries to resolve the name being looked up. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup.
At this point when the “+nodnssec” option is added, it hides the very long DNSSEC related records (DNSSEC is a completely different topic for another time. For now, hiding those records makes it easier to see and read the result of the dig command).
$ dig +trace +nodnssec www.example.com ; <<>> DiG 9.11.26-RedHat-9.11.26-6.el8 <<>> +trace +nodnssec www.example.com ;; global options: +cmd . 482189 IN NS c.root-servers.net. . 482189 IN NS d.root-servers.net. . 482189 IN NS a.root-servers.net. . 482189 IN NS h.root-servers.net. . 482189 IN NS j.root-servers.net. . 482189 IN NS g.root-servers.net. . 482189 IN NS e.root-servers.net. . 482189 IN NS m.root-servers.net. . 482189 IN NS b.root-servers.net. . 482189 IN NS k.root-servers.net. . 482189 IN NS f.root-servers.net. . 482189 IN NS i.root-servers.net. . 482189 IN NS l.root-servers.net. ;; Received 839 bytes from 127.0.0.1#53(127.0.0.1) in 0 ms com. 172800 IN NS b.gtld-servers.net. com. 172800 IN NS l.gtld-servers.net. com. 172800 IN NS e.gtld-servers.net. com. 172800 IN NS g.gtld-servers.net. com. 172800 IN NS k.gtld-servers.net. com. 172800 IN NS j.gtld-servers.net. com. 172800 IN NS m.gtld-servers.net. com. 172800 IN NS c.gtld-servers.net. com. 172800 IN NS h.gtld-servers.net. com. 172800 IN NS i.gtld-servers.net. com. 172800 IN NS d.gtld-servers.net. com. 172800 IN NS f.gtld-servers.net. com. 172800 IN NS a.gtld-servers.net. ;; Received 840 bytes from 2001:dc3::35#53(m.root-servers.net) in 25 ms example.com. 172800 IN NS a.iana-servers.net. example.com. 172800 IN NS b.iana-servers.net. ;; Received 92 bytes from 2001:503:eea3::30#53(g.gtld-servers.net) in 14 ms www.example.com. 86400 IN A 18.104.22.168 ;; Received 60 bytes from 2001:500:8f::53#53(a.iana-servers.net) in 97 ms
As the example above shows, the output of “dig” changes a lot with the “+trace” option. The output is structured into blocks representing the different levels of the DNS hierarchy.
With the exception of the first output line stating the dig version and the options used, the first block shows the well known root name servers. As shown, the are 13 root name servers.
The second block shows the TLD name servers returned from the root name server for the “com” TLD. The last line of the block shows the source of the information. In the example above, the m.root-servers.net root name server was chosen. As the example shows, 13 TLD name servers where returned.
In the same way, the third block shows the name servers for the “example.com” which where retrieved from the “g.gtld-servers.net” in the example.
Finally, the 4th block shows the result queried for and the name server it was retrieved from.
Read more of my posts on my blog at https://blog.tinned-software.net/.