Learn more about Russian war crimes in Ukraine.

What do DNS datagrams look like?

Let’s write a DNS request. We’ll query the DNS server at 8.8.8.8 for information about the domain www.google.com.

DNS works over UDP. A DNS request is sent to a DNS server in a single datagram to UDP port 53. The response is another single datagram. (This is not strictly true; TCP is also used in places. Let’s ignore that here.)

The format for a request datagram is in RFC 1035. Here’s the header:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Filling in our values, we get a very simple header:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      42                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 0|     0     | 0| 0| 0| 0|   0    |     0     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

This is now followed by a question section.

“The question section contains fields that describe a question to a name server. These fields are a query type (QTYPE), a query class (QCLASS), and a query domain name (QNAME).”

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                     QNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QTYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QCLASS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Let’s first figure out the QNAME. This is “a domain name represented as a sequence of labels, where each label consists of a length octet followed by that number of octets. The domain name terminates with the zero length octet for the null label of the root. Note that this field may be an odd number of octets; no padding is used.”

This is rather confusing, since the diagram very clearly shows that the QNAME must have padding.

For www.google.com, the labels are www, google and com. So we get 3www6google3com0; an even number of octets. Phew, ambiguity avoided.

The QTYPE is a two-octet number. We’ll use an A query to get the host for the domain. An A query is number 1.

The QCLASS should be set to 1, “the Internet”. (There are some funny other options: “CSNET”, “CHAOS”, and “Hesiod”.)

So we get our query section:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           3           |           w           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           w           |           w           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           6           |           g           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           o           |           o           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           g           |           l           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           e           |           3           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           c           |           o           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           m           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Which makes our complete datagram:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      42                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 0|     0     | 0| 0| 0| 0|   0    |     0     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       0                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           3           |           w           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           w           |           w           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           6           |           g           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           o           |           o           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           g           |           l           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           e           |           3           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           c           |           o           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           m           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                       1                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Bits and bytes here are in “network byte order”: “whenever a multi-octet field represents a numeric quantity the left most bit of the whole field is the most significant bit. When a multi-octet quantity is transmitted the most significant octet is transmitted first.” So our bytes are:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           42          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           1           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           3           |          'w'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'w'          |          'w'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           6           |          'g'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'o'          |          'o'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'g'          |          'l'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'e'          |           3           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'c'          |          'o'          |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |          'm'          |           0           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           1           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |           0           |           1           |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

Which we can express in C as:

char msg[] = {
   0 ,  42,                           // HEADER: ID
   0 ,  0 ,                           // HEADER: Various flags
   0 ,  1 ,                           // HEADER: QDCOUNT
   0 ,  0 ,                           // HEADER: ANCOUNT
   0 ,  0 ,                           // HEADER: NSCOUNT
   0 ,  0 ,                           // HEADER: ARCOUNT
   3 , 'w', 'w', 'w',                 // QUESTION: QNAME: label 1
   6 , 'g', 'o', 'o', 'g', 'l', 'e',  // QUESTION: QNAME: label 2
   3 , 'c', 'o', 'm',                 // QUESTION: QNAME: label 3
   0 ,                                // QUESTION: QNAME: null label
   0 ,  1 ,                           // QUESTION: QTYPE
   0 ,  1                             // QUESTION: QCLASS
};

What can computers do? What are the limits of mathematics? And just how busy can a busy beaver be? This year, I’m writing Busy Beavers, a unique interactive book on computability theory. You and I will take a practical and modern approach to answering these questions — or at least learning why some questions are unanswerable!

It’s only $19, and you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

After months of secret toil, I and Andrew Carr released Everyday Data Science, a unique interactive online course! You’ll make the perfect glass of lemonade using Thompson sampling. You’ll lose weight with differential equations. And you might just qualify for the Olympics with a bit of statistics!

It’s $29, but you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

More by Jim

Tagged . All content copyright James Fisher 2016. This post is not associated with my employer. Found an error? Edit this page.