tcpdump dns output codes

Captured on the nameserver:

21:54:35.391126 IP resolver.7538 > server.domain: 57385% [1au] A? www.domain.de. (42)

What das the percent sign in 57385% mean? As far as I can see 57385 is the clients sequence number, a plus would mean RD bit set.

Second question: what does the ARCOUNT do in the query? As I understand the tcpdump man page the [1au] means tcpdump treats this as a protocol anomalie - as would I. I see this in a lot of queries.


Solution 1:

Read the source Luke :)

From tcpdump/print-domain.c:

printf("%d%s%s%s", EXTRACT_16BITS(&np->id), ns_ops[DNS_OPCODE(np)],
    DNS_RD(np) ? "+" : "",
    DNS_CD(np) ? "%" : "");

So % indicates "checking disabled" which to my understanding of RFC4035 indicates that the resolver is not enforcing authentication of the RRs on the server.

From bind/lib/bind/resolv/res_mkquery.c:

int
res_nopt(res_state statp,
     int n0,                /*%< current offset in buffer */
     u_char *buf,           /*%< buffer to put query */
     int buflen,            /*%< size of buffer */
     int anslen)            /*%< UDP answer buffer size */
{
[...]
hp->arcount = htons(ntohs(hp->arcount) + 1);

According to RFC2671 it's perfectly legal for a resolver to include additional data, and with this raise the UDP packet size above the 512 byte limit. So Ladadadada's assumption is correct in this aspect.

Thanks for your time and sorry that I didn't read the source before...

Solution 2:

The number 57385 is actually the query ID, not the sequence number. In fact, sequence numbers only exist in TCP and this is UDP. The query ID is required so that the client can tell two answers apart if two queries are made at the same time.

[1au] in queries seems to go with OPT UDPsize=4096 which indicates to the server that the client can handle responses of up to 4096 bytes. In my tests I always found these two together. Without the -vv option, you don't get the extra OPT UDPsize=4096.

Originally DNS responses would only be 512 bytes and if the response was longer than that, only the first 512 bytes were sent and a bit was set to indicate that the answer had been truncated. A follow-up query was made by the client over TCP so that the entire response could be transmitted. With IPv6 records now being much longer than IPv4 records, larger responses are needed and to avoid always using TCP, an extension was added to DNS to allow larger responses.

I ran my own tcpdump until I got a % symbol in my output. Using the -vv and -n options and only looking at queries, this is what I got:

    192.168.1.42.60121 > 8.8.4.4.53: [bad udp cksum 92ce!] 57372+ [1au] MX? blah.com. ar: . OPT UDPsize=4096 OK (37)
21:40:37.185712 IP (tos 0x0, ttl 64, id 19492, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.20518 > 8.8.4.4.53: [bad udp cksum d7d9!] 43610+% [1au] A? ns1.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.185867 IP (tos 0x0, ttl 64, id 19493, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.15605 > 8.8.4.4.53: [bad udp cksum e0b2!] 51586+% [1au] AAAA? ns1.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186023 IP (tos 0x0, ttl 64, id 19494, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.34562 > 8.8.4.4.53: [bad udp cksum 4a5d!] 61450+% [1au] A? ns2.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186177 IP (tos 0x0, ttl 64, id 19495, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.56713 > 8.8.4.4.53: [bad udp cksum 5dd1!] 2672+% [1au] AAAA? ns2.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186327 IP (tos 0x0, ttl 64, id 19496, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.14021 > 8.8.4.4.53: [bad udp cksum 60f3!] 43568+% [1au] A? ns3.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186483 IP (tos 0x0, ttl 64, id 19497, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.22412 > 8.8.4.4.53: [bad udp cksum 4bca!] 38782+% [1au] AAAA? ns3.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186639 IP (tos 0x0, ttl 64, id 19498, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.50256 > 8.8.4.4.53: [bad udp cksum 6a0e!] 411+% [1au] A? ns4.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)
21:40:37.186785 IP (tos 0x0, ttl 64, id 19499, offset 0, flags [none], proto UDP (17), length 74)
    192.168.1.42.3213 > 8.8.4.4.53: [bad udp cksum adcb!] 57626+% [1au] AAAA? ns4.acotel.net.br. ar: . OPT UDPsize=4096 OK (46)

I get a SERVFAIL when requesting the MX records for blah.com. When I request the NS records for blah.com, I get the four domains you can see that have the % symbol. Presumably, some client or resolving library (probably bind9) follows up a SERVFAIL with requests for the NS records. I found this was consistent when doing lookups for the MX records of blah.com and I saw the same pattern with other domains. My guess is that the % symbol indicates that this is a subquery not initiated by the client but necessary to return an answer.

I'm sure tcpdump doesn't know what bind is doing behind the scenes so I expect there must be a flag set in the query that causes tcpdump to put this here. I might have a look at the -x option later on to see if I can find out what it is.