How does DNS work?
Table of Contents
- Before DNS
- Domain Names
- Root servers and Top-Level Domains
- Domains and sub-domains alike
- Records
- Querying the Domain Name System the manual way
The Domain Name System (or Servers, depending on the context) is one of the key parts of our modern internet. You'd rather type "google.com" than learn a bunch of IP adresses by heart like a nerd, right??
So let's take a deep dive on how this whole DNS thing works under the hood, from registrars to records, explaining how everything is linked. Oh and without boring you to death too, hopefully.

Before DNS
Let's start with a bit of History to have some context, because in order to understand what's DNS, you kind of need to ask: why DNS?
As with all things tech-related, everything is just (to a certain extent) an evolution of whatever popular was there before.
The ARPANET era
When connecting a bunch of computers together during the ARPANET era, it was clear pretty fast that using bare IP addresses was kind of hard, and as the network was growing pretty rapidly, it posed some issues with keeping track of these IPs and remembering everything.
If only there was a way to use easy-to-remember words or set of words to reference a computer by its name instead of a bunch of random-ish numbers like some kind of cavemen...
HOSTS.TXT
Here was born the HOSTS.TXT file: out of necessity.
If you've ever messed with a computer for long enough (definitely not for cracking softwares when you were younger, though), chances are that you somewhat stumbled on a strange file named "hosts". What's this hosts file? Taking a look at it, it just contains some gibberish:
127.0.0.1 localhost localhost.localdomain
Pretty boring, right? An IP address on the left, multiple names on the right, what gives?
Well... That's the ancestor of the DNS as we know it today.
The then Standford Research Institute did the bookkeeping at this point in time. Needed an IP to be mapped to a name to make it easy to remember for other users? They could be called during business hours and that was done! With everything centralized, it was easy to update this list and getting a new version of it was a breeze!
But as with everything centralized, it also meant that scalability was somewhat limited. As the network was still growing fast, they needed something that could accomodate this growth. It'd be so nice to have a system which would be de-centralized, that people could manage themselves with delegation, which would help avoid naming conflicts, and that would also be standardized...
And this is basically how and why the Domain Name System was born!
Of course, I skipped a bunch of parts as this was not a History lesson by any stretch, but you get the idea.
Domain Names
As stated before, the Domain Name System is de-centralized by design. Its original RFC, DOMAIN NAMES - CONCEPTS and FACILITIES, referred to this architecture as:
The domain name space is a tree structure. Each node and leaf on the tree corresponds to a resource set (which may be empty). Each node and leaf has an associated label. Labels are NOT guaranteed to be unique, with the exception of the root node, which has a null label. By convention, the labels that compose a domain name are read left to right, from the most specific (lowest) to the least specific (highest).
Okay, so to paraphrase this, Domain Names are a bunch of labels organised as a tree of resources, with the least specific node of this label being the root node, represented by a null label... Okay, got it. That'd be really nice to have a way to represent that using text though. What's coming next in the RFC?
When domain names are printed, labels in a path are separated by dots ("."). The root label and its associated dot are omitted from printed domain names, but the root can be named by a null domain name (" " in this memo).
Right, so those labels we just talked about can just be represented by a bunch of grouped letters, ordered by their specificity, separated by dots.
Then, if it's a tree-shaped structure, I should start querying it by its root, right?
Root servers and Top-Level Domains
Yes, that's where it (and by it, I mean, well, this journey) starts: from the root.

So the root servers know everything about the domain names and that's it? Wrong! This a tree structure, as we said, so root servers will only tell who to ask for the next label of your query: the top level domains.
It was decided that in order to make things simpler than just bare names
separated by dots, some of these labels could mean something. It would be kind
of nice that the education-related domain names would fall under the edu label,
if you see what I mean. It would also help reduce naming conflicts, so there is no
single example domain name, but one could be allowed per top level domain, such
as example.edu in this example, which would not conflict with a potential example.com.
To make things simpler to manage, the IANA is the organization in charge of supervising those top-level domains. They don't only oversee this, but that's one thing that they do (besides small Internet things like the global allocation of the address space, nothing special, okay?).
"Only I get to choose what gets to be a top level domain and what does not." -- The IANA, maybe
The IANA then delegates the management of some of these TLDs to some other
entities, such as EURid for the eu or the
AFNIC for the fr. These entities can impose some kind
of limitations when registering a domain with them, such as needing to be a
citizen of a given country before using its TLD, or being a government agency
for using the gov TLDs.
The root servers will then help you find the Domain Name.. Servers (gotcha) for the TLD relevant to your query.
But wait... "Top-Level Domains"... What's the last one of those three words? Domains? Never heard of those before...
Domains and sub-domains alike
Those top-level domains help separate domains in some kind of logical categories, so what's coming next are domains.
The entities managing a TLD can allow other entities to do the registration and management of domains under them for further delegation, usually in exchange for a fee. Those entities are named registrars.
Domains can then have sub-domains, with multiple levels of depth. Subdomains can be used for a bunch of reasons, such as:
- delegating different sub-domains to different internal organization teams so they can be autonomous with their usage
- separating different environments, such as the development and production spaces
- specializing domains based on geographical criteria, such as the east and the west branches of an office
The uses are infinite, and as long as it can be represented by a logical tree, chances are that it can also be represented with the Domain Name System.
Following this logic, let's take the following fully-qualified domain name:
web.fr.kubernetes.production.example.com
Based on this, we can (somewhat safely) assume that it would correspond to the following structure:
example.comis the domain (registered under thecomTLD)- there is a
productionenvironment- there is a
kubernetescluster in this environment- there is a french region in this cluster (denoted by
fr)- there is a
webresource in this specific region
- there is a
- there is a french region in this cluster (denoted by
- there is a
- there is a
As you can see, organizing things hierarchically, from least to most specific, is pretty easy with the Domain Name System, all while being intuitively understandable for us flesh and bones machines.
Having a way to reference a specific resource in this system is fun and all, but what can a fully-qualified domain name be used for?
Records
Records are the actual contents of a fully-qualified domain name. What can you store in records then? Well... as with all things, it depends!
A record mainly has the following properties (to keep things simpler):
- a name
- a type
- a cache retention policy (in seconds)
- the content (which format will vary from type to type)
The most common types can be:
A, referring to an IPv4 addressAAAA, referring to an IPv6 address (and not to a battery type)MX, for e-mail serversNS, for delegating name servers
Okay, I get it now, but querying this data every time it was needed would waste a lot of resources, and most of this data won't change that often anyway, right?
Cache
Yes, it's true, and that's why there is a "cache policy", expressed in seconds
and named TTL (which stands for Time To Live) baked in the protocol. This
value tells users and servers alike how long they can cache the queried result.
It can also be reduced when the query has already been cached before, such as in this example:
Let's say that we have Alice and Bob, both querying example.com for its A
records, and both are using an intermediate server for caching their queries.
The result of this query contains only one such record, point to 1.1.1.1 with
a TTL of 60. Let's also say that the cache of the caching server is empty before
all of this.
The result that Alice will obtain will be 1.1.1.1 with a TTL of 60, meaning that
it can be kept in cache for the next 60 seconds. When Bob does the same query,
but 23 seconds later, the result still says 1.1.1.1, but with a TTL of only 37
seconds. This was returned by the cache server to make sure the original 60 seconds
TTL would still be respected.
Querying the Domain Name System the manual way
Everything has been explained, but how could we test this knowledge in real life? It's not like it'd be easy to apply in the real world, with free and open source tools widely available...

Anyway, for this part, we're going to use the dig command to query the Domain
Name resource of this current blog: blog.louis-vallat.dev. (notice the last
dot, for the root name servers).
As we learned before, we always start with the less specific label on the right: the root servers.
So we just run dig without any argument to get a list of those root servers:
$ dig
;; QUESTION SECTION:
;. IN NS
;; ANSWER SECTION:
. 516797 IN NS a.root-servers.net.
. 516797 IN NS b.root-servers.net.
. 516797 IN NS c.root-servers.net.
. 516797 IN NS d.root-servers.net.
. 516797 IN NS e.root-servers.net.
. 516797 IN NS f.root-servers.net.
. 516797 IN NS g.root-servers.net.
. 516797 IN NS h.root-servers.net.
. 516797 IN NS i.root-servers.net.
. 516797 IN NS j.root-servers.net.
. 516797 IN NS k.root-servers.net.
. 516797 IN NS l.root-servers.net.
. 516797 IN NS m.root-servers.net.
;; ADDITIONAL SECTION:
a.root-servers.net. 6942 IN A 198.41.0.4
As we can see by the QUESTION SECTION, dig asked for the root servers .,
with a type of query being NS (for Name Servers), and got a bunch of servers
returned as a result.
As I already ran a query that is still in cache for the A records corresponding
to a.root-servers.net, my local resolver replied in the additional section that
this record is 198.41.0.4, valid for the next 6942 seconds.
Let's ask this server for the dev TLD:
$ dig dev @198.41.0.4
;; QUESTION SECTION:
;dev. IN A
;; AUTHORITY SECTION:
dev. 172800 IN NS ns-tld1.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld3.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld5.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld2.charlestonroadregistry.com.
dev. 172800 IN NS ns-tld4.charlestonroadregistry.com.
;; ADDITIONAL SECTION:
ns-tld1.charlestonroadregistry.com. 172800 IN A 216.239.32.105
ns-tld1.charlestonroadregistry.com. 172800 IN AAAA 2001:4860:4802:32::69
ns-tld3.charlestonroadregistry.com. 172800 IN A 216.239.36.105
ns-tld3.charlestonroadregistry.com. 172800 IN AAAA 2001:4860:4802:36::69
ns-tld5.charlestonroadregistry.com. 172800 IN A 216.239.60.105
ns-tld5.charlestonroadregistry.com. 172800 IN AAAA 2001:4860:4805::69
ns-tld2.charlestonroadregistry.com. 172800 IN A 216.239.34.105
ns-tld2.charlestonroadregistry.com. 172800 IN AAAA 2001:4860:4802:34::69
ns-tld4.charlestonroadregistry.com. 172800 IN A 216.239.38.105
ns-tld4.charlestonroadregistry.com. 172800 IN AAAA 2001:4860:4802:38::69
Here also, we get a bunch of name servers in the response, with a few IP addresses
corresponding to those same name servers, so that we don't need to run another query
to get those. Let's ask the first one of these servers,
ns-tld1.charlestonroadregistry.com, with the next label in line: louis-vallat.dev.:
$ dig louis-vallat.dev. @216.239.32.105
;; QUESTION SECTION:
;louis-vallat.dev. IN A
;; AUTHORITY SECTION:
louis-vallat.dev. 10800 IN NS ns1.louis-vallat.dev.
louis-vallat.dev. 10800 IN NS ns2.louis-vallat.dev.
;; ADDITIONAL SECTION:
ns1.louis-vallat.dev. 3600 IN A 116.202.43.167
ns1.louis-vallat.dev. 3600 IN AAAA 2a01:4f8:a0:3357::67fa
ns2.louis-vallat.dev. 3600 IN A 51.159.144.14
ns2.louis-vallat.dev. 3600 IN AAAA 2001:bc8:1210:5c28:dc00:ff:fe6e:b44d
Again, we get a bunch of name servers telling us where to look for the information
we queried, with their corresponding addresses in the additional section.
Let's continue digging a bit more, querying the first name server with one more
label: blog.louis-vallat.dev:
$ dig blog.louis-vallat.dev. @116.202.43.167
;; QUESTION SECTION:
;blog.louis-vallat.dev. IN A
;; ANSWER SECTION:
blog.louis-vallat.dev. 60 IN A 116.202.43.162
We finally get the long-awaited answer, being 116.202.43.162, with a TTL of
60 seconds!
Congratulations, you now understand how the Domain Name System works!
