DNS Message Format And Name Compression
The DNS message is composed of a the following sections:
- Question (if this is a query or a response)
- Answer (if this a response)
- Additional information
DNS Message format: the Header section
The DNS message header is 12B long (32*3/8). The DNS message header is colored in salmon in the figure.
- ID, aka Identification or Transaction ID. It identifies a query-response pair in a DNS communication
- from QR to RCODE, these are flags. We will learn them below,
- QDCOUNT: the number of questions in the message,
- ANCOUNT: the number of RRs in the answer in the message,
- NSCOUNT: the number of authority RRs in the message,
- ARCOUNT: the number of additional information RR in the message.
Here are some of the flags that appear in the DNS message header (whether the message is a query or a response):
- QR: identifies whether this message is a query or a response.
- Opcode: if this value is 0 then the message is a standard query.
- Authoritative Answer: this bit is available only for DNS replies. It tells whether the server is authoritative for the requested domain name.
- AA = 1; the DNS server is authoritative on the domain name
- AA = 0; the DNS server is not authoritative on the domain name
- TrunCated: tells whether the message is truncated or not. A DNS message is truncated when it can not fit in a single UDP datagram with a maximum size of 512 Bytes.
- Recursion Desired: expresses the querying host’s desire to make a recursive query or not.
- If set to 1, then it means “the querying host desires a recursive query”. This flag is copied in the response too.
- Recursion Available: appears only in DNS responses. It tells whether the name server that receives the query can do recursive queries or not
- If set to 1, this flag says “I can do recursive queries”,
- if set to 0, this flag says “Sorry dude I can not do recursive queries”.
- Zero : actually set to 0. This flag is developed for future use.
- ReplyCODE: This flag is only valid in a DNS reply. It tells whether the response contains errors or not
- if RCODE = 0, then there are no errors,
- else: there is an error
DNS message: the remaining sections
We learned the parts that constitute the Header. This is just one part of a DNS message. In fact, the DNS message contains, in addition to the header, other sections :
- Question section, if it’s a DNS query or a reply. Strangely enough, the DNS reply contains the Question section too,
- Answer section, if it’s a DNS reply,
- Authority section (optional in a DNS reply),
- Additional section (optional in a DNS reply).
The Question section in a DNS message
When the DNS message is a DNS query, then it has a header and a Question section. The Question section is composed of the three 16-bits fields:
- QNAME: QNAME is the domain name encoded in labels (we will learn about labels later),
- QTYPE: determines the type of the query. You can find a complete list of types on Wikipedia,
- QCLASS: determines the class of the query. Usually QCLASS has the value “IN” to mean “INternet”.
The Answer section in a DNS message
A DNS response message has at least a header, a Question section and an Answer section. I said “at least” because there can be an Authority section and an Additional section.
The Answer section contains the following parts:
- NAME: has the same format as QNAME
- CLASS: has the same format as QCLASS
- TYPE: has the same format as QTYPE
- TTL: describes how much time – in seconds- can this record be cached before it must be discarded
- RDLENGTH: describes the length of the RDATA field
- RDATA: contains the resource itself. For example, if the RR is of type A, then RDATA is an IPv4 address. If the RR is of type NS, then RDATA is a name server alias hostname.
We saw that QNAME, NAME and RDATA (in case of NS record) contain an alias hostname. But how is the hostname written in the DNS packet?
How a domain name is represented inside the DNS packet
To understand how QNAME is represented (and also NAME and RDATA), we need to understand the way a domain name is represented in a DNS packet. It may seem a bit odd, but once you get the idea, it will become simple.
As I mentioned earlier, the domain name is represented in the form of labels separated by dots (.):
A label can be of two types:
- Data label
- Compression label
We’ll talk about compression labels in the DNS Name Compression paragraph. Let’s now define data labels.
A data label is composed of :
- Label length: a byte that describes the length of the current label (just before the dot). The value ranges from 0 to 63.
- the bytes of the current label. Their maximum size is 63 bytes.
For example, the domaine name “www.microsoft.com” has three labels and is encoded in the DNS message in this format:
3 ‘w’ ‘w’ ‘w’ 9 ‘m’ ‘i’ ‘c’ ‘r’ ‘o’ ‘s’ ‘o’ ‘f’ ‘t’ 3 ‘c’ ‘o’ ‘m’ 0
Notice the trailing “0”. This is called the label of length 0 and means the root label. Remember that all DNS domain names end with a root domain; the dot.
The maximum size of a domain name is 255 Bytes (or 255 characters if we suppose that each character is encoded in 1 Byte), including the length bytes and the trailing label of length 0. The dots between labels are not counted.
Pay attention that this is not name compression. It’s just how DNS domain names are encoded in a DNS message.
This domain name encoding is found in the following fields: QNAME, NAME and RDATA.
DNS name compression
A DNS reply message can contain the same domain name multiple times. This repetition is a waste of bits in the message. A compression technique can be used to reduce the number used bits and replace the repeated domain name by a pointer.
Remember that we talked earlier about compression label? A compression label is a pointer that occupies the NAME field of the Answer section (16 bits). So the pointer is written on 16 bits and has the following format:
Remember when I said that the label length of a data label is one byte long, and its value is between 0 and 63? 63 is 00111111 in binary. The compression label, however, has the first two bits set to 1, to differentiate it from data labels.
The compression label can only be used if the pointed domain name (called compression target) has already been mentioned in the DNS message (you can’t point to a something that does not exist already).
The significance of the compression label is as follows: the first 2 bits are set to 1, the 14 remaining bits describe the offset, i.e. the position of the compression target from the beginning of the DNS message.
DNS name compression example
Here is an example to illustrate the use of name compression. Let’s assume a DNS UDP datagram needs to use the following domain names: F.ISI.ARPA, FOO.F.ISI.ARPA and ARPA. In this example we assume that bytes start at offset 0.
The first domain name F.ISI.ARPA will be encoded as a data label because it appeared for the first time in the DNS packet. Here is the coding of the domain name F.ISI.ARPA :
Now here is how FOO.F.ISI.ARPA is encoded: FOO appears for the first time so it is encoded as a data label. Then, since F.ISI.ARPA was already mentioned in the datagram, we can simply leverage compression and point to F.ISI.ARPA by indicating the offset (here F.ISI.ARPA appeared the first time at byte number 20).
Also, ARPA appeared before at byte number 26. So we simply point to it by its offset:
The TCP/IP Guide: A Comprehensive, Illustrated Internet Protocols Reference
TCP/IP Illustrated, Volume 1: The Protocols (2nd Edition)