Posted on 38 mins read

DNS (Domain Name System)

You likely have many applications running on your laptop right now, and chances are some of them require an external resource or piece of data that will be retrieved from across a network.

In order for your applications to access these resources they need to know their location. The location is typically identified by an ip address and are written in either decimal or hexadecimal.

When dealing with ips, they can be very hard to memorise; especially as there are two different forms of ip:

  1. IPv4
  2. IPv6

An IPv4 identifier is 32 bits long, written in decimal and separated by periods:

74.125.224.72

An IPv6 identifier is 128 bits long, written in hexadecimal and separated by colons:

3ffe:1900:4545:3:200:f8ff:fe21:67cf

It’s even more awkward if you have a program with a hard coded ip address for a specific resource. If the resource has to change its location, then the program now has to be updated as well to point to that new location.

What’s easier would be the use of a name that maps to an underlying value. So for example, the ip address 74.125.224.72 points to Google’s search page. Rather than type that ip into your web browser (or hard code it inside an application) you would likely instead find it much easier to reference the resource by its name: google.com.

Your application (e.g. web browser, whatever) when encountering this ‘resource’ will lookup the name provided, resolve the underlying ip address and ultimately retrieve the relevant resource.

This is the basis of what is known as DNS (Domain Name System).

Lookup Process

In order for you to access a resource using a name, you need to now know the location of the system that contains the information (also known as ‘records’) for the resource you’re interested in.

The idea being is that if you knew which DNS held a record containing information about the resource you wanted, you could ‘query’ the DNS and say…

“hey, what’s the ip for resource X?”

…the DNS would then respond with the information you needed.

This is what’s known as the ’lookup process’.

The lookup process is where your machine communicates across different networks until it finds one that knows the ip address of the resource you’re looking for. Now there are a few different parts to this lookup process:

  • Resolver
  • Root Name Server(s)
  • TLD Name Server(s)
  • SLD Name Server(s)

Resolver

The ‘resolver’ knows the location of the ‘root name server(s)’. When you make a request for a DNS resource, then the resolver is what you communicate with first. The resolver is typically either assigned via DHCP (client-side) or via /etc/resolv.conf (server-side).

The resolver will have a ‘root hints’ file with a hardcoded list of root name servers (there are thirteen root servers †). The resolver takes the DNS resource request and queries all the root name servers at once. Whichever root name server responds first, the resolver will keep a note of it as being the quickest (so for future requests it’ll favour that server over the other root name servers).

Resolvers also include additional logic for invalidating the favoured root name server, but that’s outside the scope of this article.

† there are only thirteen root server clusters, because that’s all that can fit inside a single UDP packet. Historically, DNS has operated through UDP packets, meaning the response to a request can never be more than 512 bytes.

Now depending on what your query is, the resolver’s job isn’t necessarily finished. For some queries (such as www.example.com) the resolver doesn’t just send a request to one level of name servers.

The resolve first makes a request to the root name servers, waits for a response and then sends another query; this time the query is sent to a ‘sub level’ name server known as a TLD name server.

The TLD name server also returns a referral, this time to a SLD name server which the resolver will query. The SLD should now be able to identify the requested DNS resource.

Root Name Server(s)

There are multiple root name servers and each one knows the location of a sub level name server capable of handling the requested DNS resource (or at least knowing the next level of name servers to delegate the request onto).

Effectively the root name servers parse the requested resource and identify which ‘TLD’ name server the resolver should query. Once the root name server has identified the sub level name server, it returns that information to the resolver.

TLD Name Server(s)

There are multiple TLD name servers and each one knows the location of sub level name servers capable of handling the requested DNS resource and identifying its underlying ip address. The TLD name servers parse the requested resource and identify which ‘SLD’ name server the resolver should query.

Once the TLD name server has identified the SLD name server, it returns that information to the resolver.

Note: TLD name servers are split into two: gTLD (.com, .org, .net etc) and ccTLD (.us, .uk etc)

SLD Name Server(s)

SLD name servers are known by a few different names:

  • User DNS name server
  • Authoritative name server

The latter (authoritative) being the most well known, because these name servers are the final step to hopefully discovering the identity of the requested DNS resource and this DNS server will be responsible for the DNS settings applied to the resource.

Note: you may find some people use the term ‘authoritative’ quite liberally, because in essence even a TLD name server can be considered authoritative in respect to the TLDs it manages (depends on your perspective)

Tree Hierarchy

It can be useful to try and visualise the hierarchy of this lookup process.

The following code snippet shows a potential lookup flowing from an initial request to a ‘root’ name server, into a ‘TLD’ name server (I show both sub categories: gTLD and ccTLD just to be clearer); another request is then made to a specific gTLD (.com in this case) and from there the next step is for the resolver to query the SLD (in this example we’re looking for the resource www.example.com):

         . (root)
        / \
       /   \
(gTLD).     .(ccTLD)
      \
       \
        .(com)
         \
          \
           .(example.com)

The requests that would have been made to fulfil the above flow diagram would have looked something like:

  • Resolver makes multiple requests for www.example.com to its list of root name servers
  • One of the root name servers would have responded first to say “go talk to the .com gTLD”
  • The resolver then sends the same www.example.com query to the .com gTLD
  • The gTLD responds to say “go talk to the example.com authoritative name server”
  • The resolver then sends the same www.example.com query to the relevant authoritative name server
  • The authoritative name server has the record the resolver is looking for and sends back its details
  • The resolver can now provide those details back to the application who originated the request

Note: so far we’ve spoken about name servers that run DNS software. There are many DNS software programs available (some paid, some free), but the most popular is BIND. We’ll see references to it throughout this article

DNS Structure

Each period in a ‘domain’ is actually a ’level’. Hence extensions such as .com or .us are considered a TLD (top-level domain). This also explains why an SLD is named so: because it sits at a ‘secondary’ level (it sits ‘below’ the TLD).

The syntax structure of a domain resembles the following:

<protocol><hostname>.<sld>.<tld>.

This would materialise into something like:

http://www.example.com

Where…

  • http:// is the protocol
  • www is the hostname
  • sld is ’example’
  • tld is ‘com’

Note: things get a little more complicated with ccTLDs
As country codes can have a third level (e.g. example.co.uk)
uk (TLD), co (SLD), example (3LD)

Typically the combination of <sld><tld> is referred to as the ‘domain name’.

Authority Zones

Now that we understand that a domain is made up of ’levels’, the concept of ‘zones’ should be easier to comprehend. A level is equivalent to a zone, but when using the term ‘zone’ we’re being explicit in what context we’re talking about. Effectively each zone is responsible (i.e. an authority) for its own resource records (RR).


Zonefile

A resource record (RR) is simply a line in a text file. This text file defines what records have been created for the level/zone. Each authoritative name server (zone) has its own zonefile because it needs to be able to respond to requests (queries) for records it may have.

Below is an example of what a zonefile might look like for the domain example.com:

$TTL	86400 ; 24 hours could have been written as 24h or 1d
$ORIGIN example.com.
@  1D  IN  SOA ns1.example.com. hostmaster.example.com. (
            2002022401 ; serial
            3H ; refresh
            15 ; retry
            1w ; expire
            3h ; minimum
           )
       IN  NS     ns1.example.com. ; in the domain
       IN  NS     ns2.smokeyjoe.com. ; external to domain
       IN  MX  10 mail.another.com. ; external mail provider
; server host definitions
ns1    IN  A      192.168.0.1  ;name server definition     
www    IN  A      192.168.0.2  ;web server definition
ftp    IN  CNAME  www.example.com.  ;ftp server definition
; non server domain hosts
bill   IN  A      192.168.0.3
fred   IN  A      192.168.0.4 

The zonefile is effectively the mapping between a domain name and its associated ip address (as you’ll see later on, the use of tools such as dig return us similar output).

In the above example zonefile we can see that we have a few records defined, such as an ‘A’ record (e.g. ns1, www, bill and fred) and a ‘CNAME’ record (ftp), as well as a couple of ‘NS’ records and a ‘MX’ record. We’ll take a look at what these records really represent later on in this article.

The format for these records is as follows:

name ttl class rr ...

Note: where ... represents specific arguments for the type of RR being created

The reason I mention this syntax structure is because there are some nuances regarding this zonefile that tie into the syntax structure but might not be immediately clear:

  1. Anything starting with a $ is referred to as a ‘directive’ and affects processing of the zonefile (e.g. $TTL defines the default ttl for the entire zone; this can be overridden by a ttl set within a RR).
  2. The SOA record needs to be the first record defined
  3. The SOA record replaces @ with the value assigned to $ORIGIN
  4. The $ORIGIN directive is not mandatory. If not provided, then BIND (the DNS server software) will acquire a value from the configuration file named.conf (but generally it’s more portable to provide one in your zonefile)
  5. The SOA could be made into a one liner, but uses parentheses to indicate ‘multi-line’
  6. Not all arguments are mandatory and so can be left blank, by way of a space or a tab (known as a ‘field separator’)
  7. Most RR’s utilise IN as the ‘class’ value (which stands for ‘Internet’). There are other values but they’re very rarely used †
  8. The ’name’ used for most of the RR’s in the above example aren’t considered “fully qualified domain names”. I discuss what this means below, but for now you should know that the rule is: if the name doesn’t end with a dot . then the $ORIGIN is appended to the name (see next section for more details)
  9. With RRs you can have the same ip assigned to multiple names (as the one host could potentially be serving up different services, such as a DNS as well as a web server)
  10. You can simplify the creation of multiple records of the same RR type by omitting their value (see above example zonefile). For example, if no value for rr is found then it’ll use the value from the previous record
  11. You can provide very basic DNS ’load balancing’ by creating multiple A records and pointing them to different ips. BIND will handle requests by carrying out either a round-robin process or a random selection (depending on the rrset-order setting inside the configuration named.conf; round-robin being the default)

† the fields date back to an era where there were multiple computer networks in competition with each other. IN (internet) was just one of many. Others at the time might have been CH (CHAOSNET) or HS (Hesiod, and in part is still used by MIT students to this day). You’ll find all available references in the official DNS Parameters RFC.


To put this into context, consider the ICANN organisation, who are responsible for providing an accreditation system for domain ‘registrars’. A domain registrar is an organisation who has been authorised to sell SLDs for a chosen TLD.

Registrars are a special entity who have been given ‘authority’ over a set of TLDs. They’re able to create records for their zone (which is the top level domain itself).

For example, 123-Reg is a domain registrar authorised to sell SLDs for all types of TLDs (such as .org, .com, .net, .co.uk etc). 123-Reg is a registrar who has (in my case) sold me the SLD (and technically a third-level domain) integralist.co for the ccTLD .uk - which means I’m the authority for integralist.co.uk and can create records/hosts/sub domains for it.

This registrar could also sell the SLD example (which gives you ownership and responsibility for example.com and everything to the left of it; e.g. you could create www.example.com). Or maybe this registrar sells you a SLD/3LD combination for something like example.co (which gives you ownership and responsibility for example.co.uk).

Once you purchase a SLD (e.g. you could purchase the SLD example under the TLD .com), you are the authority for that zone (the SLD). This means you are able to create resource records for that zone.

So if you had example.com, then you could create an A record www which points to a specific ip address, or maybe you create a blog CNAME record which acts as an alias to another service such as GitHub pages (we’ll see this demonstrated later on when looking at the different types of records in more detail).

Ultimately you have control over your zone (example), and everything to the left of it, until you reach a new zone that has been delegated to another entity.

Fully Qualified Domains

We should be clear that a ‘record’ isn’t just the hostname part (e.g. www). The record looks more like www.example.com. (notice the dot on the end which indicates the ‘root’).

Most registrars provide a bit of visual sugar in their applications which mean you can create a record for www.example.com. but only require you to enter www, as they will add the ‘origin’ (e.g. example.com.) onto the end of the www automatically for you.

Don’t be confused and think the ‘record’ is just www; it’s not. This is why they are typically referred to as a “fully qualified domain” (FQD).

The dot on the end of the FQD indicates the root, the starting point of the DNS lookup hierarchy.

Practical example

It’s nice to be able to see a practical example of how authority zones work (and in this case it’ll help with understanding some later examples I’ll be showing to you).

I have the domain integralist.co.uk. It has a zone defined there, but it also has a separate zone defined by the host/sub domain www. So www.integralist.co.uk is controlled by another entity (in my case a GitHub related entity).

This is why when looking at the SOA record (we’ll explain what this is later, but in summary it stands for “Start of Authority”) for integralist.co.uk we’ll see that (as of 2015) 123-Reg is the authoritative name server, whereas if you look at www.integralist.co.uk you’ll see that (again, as of 2015) Fastly is the authoritative name server as the www host is set-up as a CNAME that is an alias pointing to GitHub, which in turn is a domain handled by Fastly.

Name Servers

We’ve mentioned ’name servers’ a few times so far in this article and that’s because they’re a key component within the lookup process for a DNS resource. A ’name server’ is a server that runs DNS software and is capable of mapping an ip to an easier to read/remember identifier.

This is why the resolver pings a set of root name servers, as it knows it’ll either get back the ip for the requested domain name, or it’ll be referred to some other name server that can provide that information.

When handling the DNS for a specific zone within your domain, you’ll likely set a NS (NameServer) record to point to a DNS service which allows you to administer DNS services for the zone you are the owner of. These name servers are typically referred to as a “primary” and “secondary” name server.

The primary/secondary name servers are effectively where the authoritative name server (the servers handling DNS responsibilities) is split into sub sections. You’ll have one ‘primary’ name server that contains the ‘zonedata’ file(s) - also known as a zonefile - and then the secondary name server(s) will reference that zonefile via a mechanism known as BIND (which is one of the largest DNS software implementations available).

Note: the way zonefiles are replicated is a much bigger discussion topic and falls outside the focus of this article, but in short there have been a few alternative mechanisms implemented since BIND; such as: rsync, git and even database replication

Commands

I want to take a slight detour now and quickly discuss a set of shell commands that are useful in debugging and querying the DNS. After this section I’ll be explaining the various types of records available, and I’ll be using the following commands to help me demonstrate the different record types.

So for the time being, don’t worry too much if you don’t feel you have a good handle on these commands after reading this section as this is just a light(ish) introduction, whereby I’ll start to elaborate on their usage more in the subsequent sections.

whois

Taking the description direct from the manual:

The whois utility looks up records in the databases maintained by several Network Information Centers (NICs).

So if you want a very top level and general view of a domain and who owns/manages it, then the whois command is for you. Typically you’ll use it to see who has registered a domain and to see the state of the domain (when was it last updated? when is it expiring? which organisation handles the DNS services? etc).

Let’s see what sort of data we get back when querying the domain for my website:

whois integralist.co.uk

This would provide the following response:

Domain name:
    integralist.co.uk

Registrant:
    Mark McDonnell

Registrant type:
    UK Individual

Registrant's address:
    The registrant is a non-trading individual who has opted to have their
    address omitted from the WHOIS service.

Data validation:
    Nominet was able to match the registrant's name and address against a 3rd party data source on 10-Dec-2012

Registrar:
    123-Reg Limited t/a 123-reg [Tag = 123-REG]
    URL: http://www.123-reg.co.uk

Relevant dates:
    Registered on: 19-Jul-2009
    Expiry date:  19-Jul-2017
    Last updated:  12-Jul-2015

Registration status:
    Registered until expiry date.

Name servers:
    ns.123-reg.co.uk
    ns2.123-reg.co.uk

Note: the output will differ depending on the TLD (Top Level Domain)
as they are managed by different NICs (Network Information Centers)

Now there can be problems when doing a simple whois <domain> query. For example, the below output is the result of executing the command whois google.com. You’ll notice that we get back multiple name servers responsible for a google.com domain (and not always the official Google you’re expecting):

Whois Server Version 2.0

Domain names in the .com and .net domains can now be registered
with many different competing registrars. Go to http://www.internic.net
for detailed information.

Aborting search 50 records found .....
GOOGLE.COM.AFRICANBATS.ORG
GOOGLE.COM.ANGRYPIRATES.COM
GOOGLE.COM.AR
GOOGLE.COM.AU
GOOGLE.COM.BAISAD.COM
GOOGLE.COM.BEYONDWHOIS.COM
GOOGLE.COM.BR
GOOGLE.COM.CN
GOOGLE.COM.CO
GOOGLE.COM.DO
GOOGLE.COM.FORSALE
GOOGLE.COM.HACKED.BY.JAPTRON.ES
GOOGLE.COM.HANNAHJESSICA.COM
GOOGLE.COM.HAS.LESS.FREE.PORN.IN.ITS.SEARCH.ENGINE.THAN.SECZY.COM
GOOGLE.COM.HK
GOOGLE.COM.HOUDA.DO.YOU.WANT.TO.MARRY.ME.JEN.RE
GOOGLE.COM.IS.APPROVED.BY.NUMEA.COM
GOOGLE.COM.IS.NOT.HOSTED.BY.ACTIVEDOMAINDNS.NET
GOOGLE.COM.LASERPIPE.COM.DOMAINPENDINGDELETE.COM
GOOGLE.COM.LOLOLOLOLOL.SHTHEAD.COM
GOOGLE.COM.MX
GOOGLE.COM.MY
GOOGLE.COM.NS1.CHALESHGAR.COM
GOOGLE.COM.NS2.CHALESHGAR.COM
GOOGLE.COM.PE
GOOGLE.COM.PK
GOOGLE.COM.SA
GOOGLE.COM.SHQIPERIA.COM
GOOGLE.COM.SOUTHBEACHNEEDLEARTISTRY.COM
GOOGLE.COM.SPAMMING.IS.UNETHICAL.PLEASE.STOP.THEM.HUAXUEERBAN.COM
GOOGLE.COM.SPROSIUYANDEKSA.RU
GOOGLE.COM.SUCKS.FIND.CRACKZ.WITH.SEARCH.GULLI.COM
GOOGLE.COM.TESTZZZZ.3000-RI.COM
GOOGLE.COM.TR
GOOGLE.COM.TW
GOOGLE.COM.UA
GOOGLE.COM.UK
GOOGLE.COM.UY
GOOGLE.COM.VABDAYOFF.COM
GOOGLE.COM.VN
GOOGLE.COM.WORDT.DOOR.VEEL.WHTERS.GEBRUIKT.SERVERTJE.NET
GOOGLE.COM.YUCEHOCA.COM
GOOGLE.COM.YUCEKIRBAC.COM
GOOGLE.COM.ZNAET.PRODOMEN.COM
GOOGLE.COM.ZZZZZ.GET.LAID.AT.WWW.SWINGINGCOMMUNITY.COM
GOOGLE.COM.ZZZZZZZZZZZZZ.GET.ONE.MILLION.DOLLARS.AT.WWW.UNIMUNDI.COM
GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZ.LOLLERSKATES.RENDRAG.NET
GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZZZZZZZ.HAVENDATA.COM
GOOGLE.COMICTOWEL.COM
GOOGLE.COM

Only the last item in that list is the genuine Google domain we wanted to query (GOOGLE.COM). So how do we query that specific domain and not get back all these other variants? To do that we need to find out the ‘whois server’ for that domain.

To find out the ‘whois server’ (that is, the server which holds the ‘whois record’) we need to use the = sign within our command, like so: whois '=google.com' and from there you can discover the whois server and then we can use that information to help us query the server more directly.

The following output is from executing whois '=google.com' and again is shortened for brevity (as there are quite a few results that come through), but this time we’re getting the Whois Server information passed through. Notice out of the three records returned that only the last one is a genuine Google domain:

Server Name: GOOGLE.COM.ZZZZZZZZZZZZZZZZZZZZZZZZZZ.HAVENDATA.COM
IP Address: 162.251.82.121
Registrar: PDR LTD. D/B/A PUBLICDOMAINREGISTRY.COM
Whois Server: whois.PublicDomainRegistry.com
Referral URL: http://www.PublicDomainRegistry.com

Server Name: GOOGLE.COMICTOWEL.COM
IP Address: 216.239.32.21
Registrar: GODADDY.COM, LLC
Whois Server: whois.godaddy.com
Referral URL: http://registrar.godaddy.com

Domain Name: GOOGLE.COM
Registrar: MARKMONITOR INC.
Sponsoring Registrar IANA ID: 292
Whois Server: whois.markmonitor.com
Referral URL: http://www.markmonitor.com
Name Server: NS1.GOOGLE.COM
Name Server: NS2.GOOGLE.COM
Name Server: NS3.GOOGLE.COM
Name Server: NS4.GOOGLE.COM
Status: clientDeleteProhibited http://www.icann.org/epp#clientDeleteProhibited
Status: clientTransferProhibited http://www.icann.org/epp#clientTransferProhibited
Status: clientUpdateProhibited http://www.icann.org/epp#clientUpdateProhibited
Status: serverDeleteProhibited http://www.icann.org/epp#serverDeleteProhibited
Status: serverTransferProhibited http://www.icann.org/epp#serverTransferProhibited
Status: serverUpdateProhibited http://www.icann.org/epp#serverUpdateProhibited
Updated Date: 20-jul-2011
Creation Date: 15-sep-1997
Expiration Date: 14-sep-2020

Note: the use of = in the whois command doesn’t work with .uk TLD’s
You’ll see an error about a strict no = character allowed

Once you find the domain you’re after (in this case we want the real google.com), you can filter out the Whois Server line and use that to query the domain directly via the whois server responsible for the actual google.com domain (this is done by adding the -h flag to the whois command):

whois -h whois.markmonitor.com google.com

Doing this we can now see the actual output we want:

Domain Name: google.com
Registry Domain ID: 2138514_DOMAIN_COM-VRSN
Registrar WHOIS Server: whois.markmonitor.com
Registrar URL: http://www.markmonitor.com
Updated Date: 2015-06-12T10:38:52-0700
Creation Date: 1997-09-15T00:00:00-0700
Registrar Registration Expiration Date: 2020-09-13T21:00:00-0700
Registrar: MarkMonitor, Inc.
Registrar IANA ID: 292
Registrar Abuse Contact Email: abusecomplaints@markmonitor.com
Registrar Abuse Contact Phone: +1.2083895740
Domain Status: clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)
Domain Status: clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)
Domain Status: clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)
Registry Registrant ID:
Registrant Name: Dns Admin
Registrant Organization: Google Inc.
Registrant Street: Please contact contact-admin@google.com, 1600 Amphitheatre Parkway
Registrant City: Mountain View
Registrant State/Province: CA
Registrant Postal Code: 94043
Registrant Country: US
Registrant Phone: +1.6502530000
Registrant Phone Ext:
Registrant Fax: +1.6506188571
Registrant Fax Ext:
Registrant Email: dns-admin@google.com
Registry Admin ID:
Admin Name: DNS Admin
Admin Organization: Google Inc.
Admin Street: 1600 Amphitheatre Parkway
Admin City: Mountain View
Admin State/Province: CA
Admin Postal Code: 94043
Admin Country: US
Admin Phone: +1.6506234000
Admin Phone Ext:
Admin Fax: +1.6506188571
Admin Fax Ext:
Admin Email: dns-admin@google.com
Registry Tech ID:
Tech Name: DNS Admin
Tech Organization: Google Inc.
Tech Street: 2400 E. Bayshore Pkwy
Tech City: Mountain View
Tech State/Province: CA
Tech Postal Code: 94043
Tech Country: US
Tech Phone: +1.6503300100
Tech Phone Ext:
Tech Fax: +1.6506181499
Tech Fax Ext:
Tech Email: dns-admin@google.com
Name Server: ns4.google.com
Name Server: ns2.google.com
Name Server: ns3.google.com
Name Server: ns1.google.com
DNSSEC: unsigned

The structure of this variation of the whois command is:

whois -h <whois_server> <domain>

dig

Taking the description direct from the manual:

dig (domain information groper) is a flexible tool for interrogating DNS name servers. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried

So dig it turns out is, in a practical sense, a great DNS debugging tool. Let’s take a look at a quick example where we want to find out some DNS related information for the domain integralist.co.uk:

dig integralist.co.uk

Executing this command will give us back the following response:

; <<>> DiG 9.8.3-P1 <<>> integralist.co.uk
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5590
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 2

;; QUESTION SECTION:
;integralist.co.uk.   IN  A

;; ANSWER SECTION:
integralist.co.uk.  14400 IN  A 192.30.252.153

;; AUTHORITY SECTION:
integralist.co.uk.  151529  IN  NS  ns2.123-reg.co.uk.
integralist.co.uk.  151529  IN  NS  ns.123-reg.co.uk.

;; ADDITIONAL SECTION:
ns.123-reg.co.uk. 7 IN  A 212.67.202.2
ns2.123-reg.co.uk.  7 IN  A 92.51.159.40

;; Query time: 94 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Sun Sep 27 15:32:02 2015
;; MSG SIZE  rcvd: 126

This was a standard dig command and so you’ll notice that the response has been split up into sections:

  • HEADER: displays which options and flags have been enabled when executing the command (we’ll look at both options and flags in more detail later)
  • QUESTION: displays which record you requested for the specified domain
  • ANSWER: displays ttl (time to live) followed by record/ip for the specified domain
  • AUTHORITY: displays the authoritative name servers (i.e. the service handling DNS responsibilities)
  • ADDITIONAL: displays all the authoritative name servers available for querying (inc. their remaining ttl)
  • STATS: displays basic stats such as query time, server ip, date of query, message size

You can also specify a specific record type you want to query, like so:

dig ns integralist.co.uk

Which gives us back the following response:

; <<>> DiG 9.8.3-P1 <<>> ns integralist.co.uk
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 57285
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2

;; QUESTION SECTION:
;integralist.co.uk.		IN	NS

;; ANSWER SECTION:
integralist.co.uk.	2671	IN	NS	ns.hosteurope.com.
integralist.co.uk.	2671	IN	NS	ns2.hosteurope.com.

;; ADDITIONAL SECTION:
ns.hosteurope.com.	284	IN	A	212.67.202.2
ns2.hosteurope.com.	48488	IN	A	92.51.159.40

;; Query time: 36 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Sun Sep 27 22:15:11 2015
;; MSG SIZE  rcvd: 116

Flags

In the response for a dig command, under the header area, you’ll notice specific flags being set. These flags determine how the dig command should handle certain situations. The following flags are what you’ll likely see the most:

  • QR (Query Response)
  • RD (Recursion Desired)
  • RA (Recursion Available)
  • TC (TrunCated)
  • AA (Authoritative Answer)

When you execute a dig command you’ll pretty much always see QR in the response (e.g. flags: qr) because it indicates what you’re looking at is in fact the response.

The RD (“Recursion Desired”) flag (e.g. flags: qr rd ra) means the query will keep referring queries until it finds an answer from an authoritative name server. The RD flag is set by default but can be disabled with the +norecurse option. The reason for disabling this flag would be to help you identify if a RR (resource record) exists in a cache.

Note: the RA flag (“Recursion Available”) in the response means the server is willing to allow recursion

So if you wanted to see if one of the authoritative name servers for integralist.co.uk had its www CNAME record cached, then you would execute the following command:

dig @ns.123-reg.co.uk www.integralist.co.uk +norecurse

If the response doesn’t have an ANSWER section, then you know it has been cached.

The TC flag (“TrunCated”) is used for when a UDP response is larger than 512 bytes. The response will set TC to 1 and so the client/resolver will need to try again, this time using TCP instead of UDP so it can retrieve the full response.

Note: enabling TC can be used as a DDoS mitigation technique - where the layers in front of your name servers will purposely set TC on - so if an attacker tries using UDP when attacking your DNS, then their request will immediately fail and they’ll be required to try again using TCP (as TCP connections is easier to filter); but it’s unlikely that an automated DDoS attack will retry a failed attempt

You’ll normally see the AA flag in the response (e.g. flags: qr aa) when you query an authoritative name server directly (like we did above when checking to see if the www CNAME for integralist.co.uk was stored in a cache).

option: nostats

Enabling ’no stats’:

dig www.integralist.co.uk +nostats

The response will be missing the following section:

;; Query time: 7 msec
;; SERVER: 192.168.253.250#53(192.168.253.250)
;; WHEN: Wed Sep 23 08:52:18 2015
;; MSG SIZE  rcvd: 273

Note: personally I think this is safe to enable for the majority of use cases (stats are just visual noise I can do without)

option: nocomments

Enabling ’no comments’:

dig www.integralist.co.uk +nocomments

The response will look something like the following:

; <<>> DiG 9.8.3-P1 <<>> www.integralist.co.uk +nocomments
;; global options: +cmd
;www.integralist.co.uk.         IN      A
www.integralist.co.uk.  13920   IN      CNAME   integralist.github.com.
integralist.github.com. 17      IN      CNAME   github.map.fastly.net.
github.map.fastly.net.  2       IN      A       185.31.18.133
;; Query time: 0 msec
;; SERVER: 192.168.253.250#53(192.168.253.250)
;; WHEN: Wed Sep 23 08:54:50 2015
;; MSG SIZE  rcvd: 126

You’ll notice that all the major ‘sections’ have been removed, such as ;; Got answer:, ;; QUESTION SECTION: and ;; ANSWER SECTION:

option: trace

Trace is disabled by default so this is the first option we’ve looked at that actually needs ’enabling’:

dig www.integralist.co.uk +trace

What this will do is display the full delegation path and show all referrals:

; <<>> DiG 9.8.3-P1 <<>> www.integralist.co.uk +trace
;; global options: +cmd
.			489215	IN	NS	e.root-servers.net.
.			489215	IN	NS	k.root-servers.net.
.			489215	IN	NS	m.root-servers.net.
.			489215	IN	NS	h.root-servers.net.
.			489215	IN	NS	d.root-servers.net.
.			489215	IN	NS	j.root-servers.net.
.			489215	IN	NS	f.root-servers.net.
.			489215	IN	NS	c.root-servers.net.
.			489215	IN	NS	g.root-servers.net.
.			489215	IN	NS	l.root-servers.net.
.			489215	IN	NS	b.root-servers.net.
.			489215	IN	NS	i.root-servers.net.
.			489215	IN	NS	a.root-servers.net.
;; Received 496 bytes from 192.168.1.1#53(192.168.1.1) in 85 ms

uk.			172800	IN	NS	nsa.nic.uk.
uk.			172800	IN	NS	nsb.nic.uk.
uk.			172800	IN	NS	nsc.nic.uk.
uk.			172800	IN	NS	nsd.nic.uk.
uk.			172800	IN	NS	dns1.nic.uk.
uk.			172800	IN	NS	dns2.nic.uk.
uk.			172800	IN	NS	dns3.nic.uk.
uk.			172800	IN	NS	dns4.nic.uk.
;; Received 459 bytes from 128.63.2.53#53(128.63.2.53) in 96 ms

integralist.co.uk.	172800	IN	NS	ns.123-reg.co.uk.
integralist.co.uk.	172800	IN	NS	ns2.123-reg.co.uk.
;; Received 82 bytes from 103.49.80.1#53(103.49.80.1) in 75 ms

www.integralist.co.uk.	14400	IN	CNAME	integralist.github.com.
;; Received 75 bytes from 212.67.202.2#53(212.67.202.2) in 21 ms

Other options

For a full list of options that you can play around with, I suggest reviewing:

man dig

host

Taking the description direct from the manual:

host is a simple utility for performing DNS lookups
It is normally used to convert names to IP addresses and vice versa

So a much more basic version of dig but in certain circumstances I could imagine it offering more semantic clarity.

A simple example would be as follows:

host www.integralist.co.uk

Running the above command would return to us the ip address for the specified domain. In this case it would return:

www.integralist.co.uk is an alias for integralist.github.com.
integralist.github.com is an alias for github.map.fastly.net.
github.map.fastly.net has address 23.235.43.133

Notice it displayed the full resolution path:

  • CNAME alias to Github pages
  • CNAME alias to Fastly
  • ip address for Fastly

Now if you tried using the non-www version:

host integralist.co.uk

You’d find you get a different response:

integralist.co.uk has address 192.30.252.153

This is because my domain uses a redirect to www.integralist.co.uk, which is then a CNAME alias to GitHub. So if I carried out the reverse lookup using the ip address above:

host 192.30.252.153

I would subsequently get back the following response, which indicates that my website is actually hosted with GitHub Pages:

153.252.30.192.in-addr.arpa domain name pointer pages.github.com.

Note: dig can do the same with dig -x <ip>

nslookup

Taking the description direct from the manual:

nslookup is a program to query Internet domain name servers

nslookup

From here you’ll be prompted to specify a domain, so for example we could now type:

> integralist.co.uk

Which would return the following response:

Server:   192.168.1.1
Address:  192.168.1.1#53

Non-authoritative answer:
Name: integralist.co.uk
Address: 192.30.252.153

If I was to now use host to find the name this ip resolves to:

host 192.30.252.153

It would display:

153.252.30.192.in-addr.arpa domain name pointer pages.github.com.

Cool, so again we end up at GitHub pages where my website is hosted.

If I was to use nslookup on the www variation of my website then I’d see a slightly different response:

> www.integralist.co.uk

Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
www.integralist.co.uk	canonical name = integralist.github.com.
integralist.github.com	canonical name = github.map.fastly.net.
Name:	github.map.fastly.net
Address: 23.235.43.133

We can also use nslookup to return specific record information. Imagine we want to see the SOA record for integralist.co.uk. We can do this by typing set querytype=soa followed by the domain, like so:

nslookup

> set querytype=soa
> integralist.co.uk                        

Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
integralist.co.uk
  origin = ns.hosteurope.com
  mail addr = hostmaster.integralist.co.uk
  serial = 2012022703
  refresh = 86400
  retry = 3600
  expire = 1209600
  minimum = 14400

Authoritative answers can be found from:
integralist.co.uk	nameserver = ns.123-reg.co.uk.
integralist.co.uk	nameserver = ns2.123-reg.co.uk.
ns.123-reg.co.uk	internet address = 212.67.202.2
ns2.123-reg.co.uk	internet address = 92.51.159.40

We can also see this provides us with an authoritative answer. But as we already know, querying the www host/sub domain will return us slightly different information:

Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
www.integralist.co.uk	canonical name = integralist.github.com.
integralist.github.com	canonical name = github.map.fastly.net.

Authoritative answers can be found from:
fastly.net
  origin = ns1.p04.dynect.net
  mail addr = hostmaster.fastly.com
  serial = 2015092706
  refresh = 3600
  retry = 600
  expire = 604800
  minimum = 3600

So if we decided to try this again but specify the record type as being a CNAME record:

nslookup

> set querytype=cname
> integralist.co.uk

Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
*** Can't find integralist.co.uk: No answer

Authoritative answers can be found from:
integralist.co.uk
  origin = ns.hosteurope.com
  mail addr = hostmaster.integralist.co.uk
  serial = 2012022703
  refresh = 86400
  retry = 3600
  expire = 1209600
  minimum = 14400

We see we get back an error that says there is no answer for this type of query. But if I was to try again and now use the host/sub domain www (which I know to be a CNAME) then we get the following response:

Server:		192.168.1.1
Address:	192.168.1.1#53

Non-authoritative answer:
www.integralist.co.uk	canonical name = integralist.github.com.

Authoritative answers can be found from:
integralist.co.uk	nameserver = ns.hosteurope.com.
integralist.co.uk	nameserver = ns2.hosteurope.com.
ns.hosteurope.com	internet address = 212.67.202.2
ns2.hosteurope.com	internet address = 92.51.159.40

Now we see that www.integralist.co.uk is a CNAME (Canonical Name) to integralist.github.com.

Note: to exit nslookup press <Ctrl-c>

Record Types

There are many different RR (Resource Record) types availble within DNS, the following are the most popular:

NS

The NS record should be pointed to the entity responsible for handling DNS duties for your domain.

You must have at least two name server records for the sake of resiliency.

The sequence/ordering of listed name servers has nothing to do with priority (unlike with MX records, see below for more details). For example, the following process DOESN’T happen: “query the A name server first and if no response then query the B name server”.

Multiple NS records simply means that there are multiple name servers available to query for the records required by the client application.

The NS record indicates the authoritative name servers for the current origin. But remember that different parts of an overall domain can be controlled by different entities (i.e. different Zone/SOA).

If you’re interested in seeing which root servers are responsible for knowing about a particular TLD, then again we can use dig to find this information. For example, to see the ccTLD name servers for .co.uk execute the following command:

dig +short -t ns co.uk

Note: we use the +short flag provided by dig
This enables us to reduce the visual noise
Another trick is to use +short +noshort together
Which gives you reduced noise + additional info

This will return the following response:

dnsd.nic.uk.
dns4.nic.uk.
nsb.nic.uk.
dns1.nic.uk.
dns2.nic.uk.
nsc.nic.uk.
nsa.nic.uk.
dns3.nic.uk.

If you’re interested in seeing the very root servers which your resolver will query for information about a particular domain then you can use the following variation of the dig command:

dig +short -t ns .

Note: you’ll notice the dot on the end
As we’ve mentioned previously,
the dot represents the ‘root’ of the DNS hierarchy

Executing this command will return the following output:

a.root-servers.net.
b.root-servers.net.
c.root-servers.net.
d.root-servers.net.
e.root-servers.net.
f.root-servers.net.
g.root-servers.net.
h.root-servers.net.
i.root-servers.net.
j.root-servers.net.
k.root-servers.net.
l.root-servers.net.
m.root-servers.net.

A

An A record should point to an ip address (i.e. it’s an “address record”).

In order to provide redundancy, you can have multiple A records associated with a domain. For example, imagine your service is sitting behind a load balancer such as AWS ELB. What you would likely do is create a CNAME (see below section for more details) that points to your load balancer’s own CNAME (it’s unlikely you’ll point your domain to a direct ip address when using a load balancer because if the load balancer changes then you’d need to update your DNS, which would result in potentially significant downtime) and then the load balancer would handle the responsibility of creating multiple A records that point to the actual ip addresses of your running servers.

CNAME

A CNAME record is one that points not to an ip address (like an A record does), but instead points to either a CNAME or A record.

Let’s see a real world example by diging this website (specifically the www host name):

dig www.integralist.co.uk

The information returned (see below), indicates that we have a CNAME (www.integralist.co.uk.) that points to GitHub (integralist.github.com.); and that in turn points to an A record (github.map.fastly.net.), which itself points to the ip address of the server hosting the content:

;; ANSWER SECTION:
www.integralist.co.uk.  14266   IN      CNAME   integralist.github.com.
integralist.github.com. 2       IN      CNAME   github.map.fastly.net.
github.map.fastly.net.  17      IN      A       185.31.19.133

MX

I wont spend much time on MX records, but in short it stands for “Mail eXchange” and you can have multiple records for the purposes of redundancy. Each MX record has a ‘priority value’ which indicates a relative value compared to the other MX records listed. What this means is that a lower value is considered a higher priority and so it’s used first when directing email.

I don’t have email set-up for my integralist.co.uk domain so dig mx integralist.co.uk wont help me demonstrate anything. Instead let’s look at the BBC:

dig mx bbc.co.uk +short

This will return the following response:

20 cluster1a.eu.messagelabs.com.
10 cluster1.eu.messagelabs.com.

As you can see, the BBC appear to be using http://messagelabs.com/ as the entry point for managing their email systems.

SOA

Near the beginning of this article we discussed the concept of ‘zones’ to indicate which entity had authority over the DNS for a specific section of a domain. An SOA record (which stands for “Start of Authority”) details specific information related to TTLs regarding the current zone.

So for example, if I look at the SOA for integralist.co.uk using the following command:

dig soa integralist.co.uk +short

I would get back the following response:

ns.hosteurope.com. hostmaster.integralist.co.uk. 2012022703 86400 3600 1209600 14400

Let’s break down this response into sections:

  • ns.hosteurope.com.: primary authoritative name server
  • hostmaster.integralist.co.uk.: party responsible for your domain
  • 2012022703: timestamp that is updated when the domain is updated
  • 86400: zone refresh TTL (in seconds)
  • 3600: failed zone refresh retry (in seconds)
  • 1209600: zone authoritative ownership expiration (in seconds)
  • 14400: negative result TTL (how long resolver should consider a ’negative result’ for a subdomain to be a valid result before retrying a query to the host/subdomain

Each ‘zone’ (i.e. each name server/entity who has authority at a specific point of the domain) will provide their own SOA record. So if I were to look at the CNAME www for integralist.co.uk, then I would find that this points to a GitHub CNAME which points to a Fastly CNAME, and whose authoritative name servers are (as of 2015) ns1.p04.dynect.net. This means a new ‘zone’ is defined by Fastly and so they have authority to add host names to the left of the www section of the overall domain:

dig soa www.integralist.co.uk

I would get back the following response:

;; QUESTION SECTION:
;www.integralist.co.uk.		IN	SOA

;; ANSWER SECTION:
www.integralist.co.uk.	14389	IN	CNAME	integralist.github.com.
integralist.github.com.	19	IN	CNAME	github.map.fastly.net.

;; AUTHORITY SECTION:
fastly.net.		289	IN	SOA	ns1.p04.dynect.net. hostmaster.fastly.com. 2015092706 3600 600 604800 3600

SRV

The purpose of an SRV record is simply to provide information about services available via your domain. You’ll find services such as SkyDNS and Etc use DNS and specifically SRV records as a way of handling distributed ‘service discovery’.

There is a very specific format to the records, which looks something like the following:

_<name>._<protocol>.<domain>.

Note: the ’name’ should be a easy to identify name
but otherwise there isn’t any other structure or restrictions I know of

So if I wanted to indicate to some other service or application that I had a website available somewhere underneath the top level domain integralist.co.uk then I would create the following SRV record:

_website._tcp.integralist.co.uk.

You could then verify the SRV record was set-up by using dig like so:

dig _website._tcp.integralist.co.uk SRV +short +noshort

This would respond with the following output:

_website._tcp.integralist.co.uk. 14400 IN SRV 11 1 80 www.integralist.co.uk.

I set this up using my DNS provider’s own GUI (so your own provider may have a different interface), but effectively the response indicates to a requester that I have a single service available at www.integralist.co.uk which you can access via TCP on port 80.

The full details of which are broken down into sections, like so:

  • Hostname: _website._tcp
  • Type: SRV
  • Priority: 11 (a lower number is a higher priority)
  • TTL: 60 (in seconds)
  • Destination: 1 80 www.integralist.co.uk. (<weight> <port> <fully-qualified origin>)

Note: the priority is useful for when you have multiple hosts configured for the same service, while the weight is typically used for services that have the same priority value

PTR

The PTR record is surprisingly complex in its implementation and yet fairly simple with regards to its purpose and set-up. In short you use the PTR to do a reverse-mapping, which is the process of forwarding an ip to a hostname (the typical RR process is known as forward-mapping, where by you forward a hostname onto an ip).

The purpose of a PTR record is traditionally for authentication/security reasons. Think of mail servers that try to prevent spam messages being sent from what looks like valid hosts. In this scenario the mail server will attempt to verify that the host/ip match both ways: forward and reverse. If they don’t match then the mail is rejected.

Note: in the past when I’ve had clients complain their emails are being rejected by their intended recipient, you’ll find they’re missing a PTR record in their DNS. The recipient’s email provider will nearly always request we add a PTR record to our client’s DNS

I won’t go into the implementation details here, as I mentioned earlier it’s quite complex, but in essence there is another top level domain called arpa with a sub level domain in-addr.

This new domain works in a similar way to gTLD and ccTLDs in the sense that it has third level domains, but the difference is that the order is reversed from this point. So if your web server’s ip was 185.31.19.133 then the third level domain would use 185 as the name. These third level domains will also have their own zonefiles that describe the DNS at that level.

In the zonefile you would see something like the following (notice the ip address we mentioned above has been reversed due to the standard DNS hierarchy structure):

$ORIGIN 19.31.185.IN-ADDR.ARPA.

Note: convention states that although domains are case-insensitive, the in-addr.arpa. should be capitalised

As far as the PTR record is concerned, you now take the last part of your ip and use that as the name of your PTR record. For example, if you had the ip 185.31.19.133 then 133 would be the name of the PTR record, while its value would be a fully qualified domain such as www.example.com.:

133      IN    PTR    www.example.com.

Note: because we’ve defined an $ORIGIN in our zonefile that is an arpa address we’d typically use fully qualified domain names for all other RRs (such as we have in the above PTR example)

This now means that the DNS can carry out a reverse-lookup, and for the ip 185.31.19.133 it’ll locate the 133 PTR record and see that is resolves to www.example.com. which when doing a forward-mapping DNS request results in the ip 185.31.19.133 thus providing reasonable authentication that the queries are related and not being spoofed.

TXT

The TXT record simply provides a description for the domain being queried. You must also wrap the description in double quotes (if you’re adding this record via a DNS provider then they might do this for you as you’ll likely be typing the value of this record into a HTML input field).

Let’s see a real-world example of this record using both dig and host commands:

dig txt my-service-description.integralist.co.uk +short
host -t txt my-service-description.integralist.co.uk

This query should return a response similar to the following (it’ll be slightly different for the host command as it has no comparible flag to dig’s +short flag):

"integralist.co.uk is a tech blog"

Note: if no TXT record is found then dig will return nothing, whereas host will return integralist.co.uk has no TXT record

When I initially set-up the TXT record, it wasn’t available via my local DNS resolver and so in the following example I query one of the authoritative name servers as well as a Google server to see the new TXT record before it has propagated around the internet:

dig txt my-service-description.integralist.co.uk @ns.123-reg.co.uk. +short
dig txt my-service-description.integralist.co.uk @8.8.8.8 +short

Note: 8.8.8.8 is one of Google’s own DNS name servers and although not an authoritative name server for my domain, it was very fast at getting the new record

TTL (Time to Live)

Every resource record (e.g. A, MX, CNAME etc) has a TTL set for it. When you make a request for a record, it will be cached for the length of time that the TTL is set. This is both good and a bad thing (as is usually the case with caching scenarios) as you need to find a good balance between a TTL that’s too high (meaning you lose the ‘freshness’ for DNS updates) and a TTL that’s too low (and subsequently ends up affecting the performance of your server).

Consider the following example, which is a query for an MX record from the BBC:

dig mx bbc.co.uk +short +noshort

The response to this query is as follows:

bbc.co.uk.		300	IN	MX	10 cluster1.eu.messagelabs.com.
bbc.co.uk.		300	IN	MX	20 cluster1a.eu.messagelabs.com.

We can see the TTL for this record is 300 seconds (that’s 5 minutes). If you were to execute the same dig command again, you would now notice the value for the TTL has dropped. Run it yet again and you’ll see the value drops even more. This is the TTL expiring second by second.

So if you make a change to your DNS and are wondering why it hasn’t taken effect, this might be because it’s cached and waiting to expire before the new changes are visible.

Local Caching

If you want to bypass your local ISP caching of DNS requests, then you’ll need to query an authoritative name server directly to see if the change has indeed been made and is just waiting to take effect.

The following snippet demonstrates the command syntax structure using dig:

dig <domain> @<authoritative_nameserver>

If after executing the query the response is the one you expect, then it means the record has been updated in your DNS provider’s system but the changes still need to propagate.

References

Conclusion

Although a fairly long article, this has really only barely scratched the surface of what’s possible with DNS. I’ll be improving the contents of this page over the next few weeks, as I learn more, so stayed tuned for updates. If there are any glaring issues or inaccurate details then do please let me know. Feedback is always welcome.


But before we wrap up... time (once again) for some self-promotion 🙊