First, a story. For a SANS conference, I wanted a unique t-shirt with a packet on the back. I deliberately inserted an error and we had a prize on site for the first person to find and report the error. We did not announce the contest, we simply gave every attendee a t-shirt. 3rd day of the conference a conference worker came into the speaker ready room at lunch wearing the t-shirt. Judy Novak saw the shirt, cocked her head to the side, (let the reader understand), and finally said wait. She said three things, its UDP, its DNS, hey there's an error. Every instructor stood and bowed. We found a live termite in my office here on Kauai and have been cleaning things out before bringing in the orange oil guy and I found one of the t-shirts. There is no prize this time, but drop me a note if you figure it out :)
Now the packets. I like to look at the traffic on my home net from time to time. Today I saw my computer query for the same server name twice and thought it odd. Let's take a closer look.
The IP header, which is blue, starts off with 45 00 00 45 1d db 00 00 40 11. The 0x11 in byte 9 from offset 0 means the traffic is UDP. At the end of the IP header we see my client, c0 a8 01 65, (192.168.1.101) is talking to the world famous IP address c0 a8 01 01, the most popular router address in the world, 192.168.1.1.
So, we consult the handy SANS TCP cheat sheet for a DNS header.
The blue is the entire DNS query:
Now to try to decode the Query ID/Flags. 28 54 01 00, (first four bytes in the blue).
0x2854 is the Query ID, any responses should reference that.
There is a flag set, so we need the flags field explanation from the cheat sheet.
Let's expand 01 00 to binary:
The first 0 on the left is the QR field, 0 = Query, 1 = Response, this is a query.
The only flag set is RD Recursion Desired. 0x0100 is often referred to as a standard query.
Next, how many questions, answers, authority records additional records:
00 01 00 00 00 00 00 00 breaks down to:
00 01 question
00 00 answers
00 00 authority records
00 00 addition records
On to breakdown our question! The blue is the entire question.
DNS questions have three parts: QNAME, QTYPE, QCLASS in that order. The QNAME has a length followed by the name.
The QNAME begins with 0c and ends with 00.
The 0c, (12 decimal), is the length from the start of the DNS query to the beginning of the question, (remember to start counting from zero).
The 00 says we have reached then end of the name.
0c 73 61 66 65 62 72 6f 77 73 69 6e 67 2e 67 6f 6f 67 6c 65 2e 63 6f 6d 00
73 61 66 65 62 72 6f 77 73 69 6e 67 2e 67 6f 6f 67 6c 65 2e 63 6f 6d is the ASCII representation of safebrowsing.google.com
We are almost done, the last four bytes 00 01 00 01 make up the QTYPE and QCLASS.
The first 00 01 is the QTYPE. There are many types of Resource Records, but this blog post only covers two: 00 01 A Record and 00 05 Canonical or CNAME.
The last 00 01 is the QCLASS is this case an Internet Record, often call IN.
Off goes our query!
And we get a UDP DNS response, a big one!.
28 54 81 80, the 0x2854 matches the transaction ID of our query.
0x8180 is sometimes called a standard response.
The first 1 on the left is the QR field, this is a response. The other 1 that is the low order bit in the high order nibble, (RD), is for Recursion Desired, but we also need to look at the next bit, RA or Recursion Available and notice that it is set, (the first 1 in the low order nibble. Let's go a bit further.
So we have decooded the Transaction or Query ID and Flags. Next is Query Count, Answer Count, Authority Count and Addition Records Count
28 54 81 80 00 01 00 11 1 question, 0x0011, 17 resource records
28 54 81 80 00 01 00 11 00 00 00 00 0 Authority records, 0 Additional records
|The 00 11 indicates the 17 Resource Records|
First we get to the question section of this DNS response. It should look very familiar.
Next we get to the Answer component. Answers are made up of:
NAME, TYPE, CLASS, TTL, RDLENGTH, RDATA. The blue is one of the 17 answers.
NAME, this is the tricky part. It can be a LABLE like our query had OR it can be a pointer. The first two bytes of our answer are c0 0c. Sadly, this is not going to be a LABLE. How do we know, first we convert to binary:
c0 0c becomes:
1100 0000 0000 1100
The blue high order bits above are 11 and 11 means interpret as a pointer.
1100 0000 0000 1100
The 1100 above is the pointer value, decimal 12. For it to be valid it must point to a LABLE format and we already know what is 12 bytes into our DNS packet: safebrowsing.google.com.
TYPE. The blue box below 00 05 is the TYPE Canonical or CNAME. Essentially it is an alias. It is used to refer to safebrowsing.google.com.
CLASS Immediately after TYPE 00 05 comes CLASS 00 01 or Internet.
TTL, in blue, is the number of seconds we can safely cache safebrowsing.google.com. 00 08 83 d2 works out to 558034 seconds, (6 days).
RDLENGTH is immediately after the blue TTL above. That is 00 07, the length of our last field, RDATA.
RDATA, the 7 bytes are shown in blue. First we have the 02, no idea what that means. From the Wireshark ASCIIfication, we expect four of them to be sb.l, (73 62 2e 6c), and they are. C0 19 acts like a pointer, (remember the 11 as the two high bits and 0x19 is 25 decimal while is the displacement for the s in safebrowsing.
We will do this one more time to see if we can get an IP address.
NAME: c0 35 pointer to sb.l
TYPE: 00 01 A record
CLASS: 00 01 Internet or IN
TTL: 00 00 00 1d 29 seconds
RDLENGTH: 00 04 (it is an A record, 4 octets)
RDATA: d8 3a c1 8e 18.104.22.168 and on and on we go with another pointer.
All well and good. But look, another DNS query:
Why am I asking the same question? It is a standard query 0x0100 and also for safebrowsing.google.com. This time the Query ID is 0x24f8.
81 80 00 01 00 02 Flags are 0x8180, standard response. 1 question, 2 Answer Resource Records.
73 61 66 65 62 72 6f 77 73 69 6e 67 2e 67 6f 6f 67 6c 65 2e 63 6f 6d = safebrowsing.google.com
d8 3a db 03 - 22.214.171.124
Looks like lather, rinse, repeat.
Why did my computer ask the same question twice? My best guess is the short TTL of 29 seconds.
UPDATE: 5/13/16 I just noticed that rfc 2181 says:
"Resource Records also have a time to live (TTL). It is possible for
the RRs in an RRSet to have different TTLs. No uses for this have
been found that cannot be better accomplished in other ways. This
can, however, cause partial replies (not marked "truncated") from a
caching server, where the TTLs for some but not all the RRs in the
RRSet have expired.
Consequently the use of differing TTLs in an RRSet is hereby
deprecated, the TTLs of all RRs in an RRSet must be the same.
Should a client receive a response containing RRs from an RRSet with
differing TTLs, it should treat this as an error. If the RRSet
concerned is from a non-authoritative source for this data, the
client should simply ignore the RRSet, and if the values were
required, seek to acquire them from an authoritative source. Clients
that are configured to send all queries to one, or more, particular
servers should treat those servers as authoritative for this purpose.
Should an authoritative source send such a malformed RRSet, the
client should treat the RRs for all purposes as if all TTLs in the
RRSet had been set to the value of the lowest TTL in the RRSet. In
no case may a server send an RRSet with TTLs not all equal."
We clearly have two different TTLs and the second query was almost instant, is it possible my client rejected this DNS response. Wonder where that would be logged?