View Single Post
  #3   (View Single Post)  
Old 30th December 2009
J65nko J65nko is offline
Administrator
 
Join Date: May 2008
Location: Budel - the Netherlands
Posts: 4,131
Default

SNAP LENGTH for DNS requests and answers

If you are debugging DNS requests issued by BIND you need to capture the complete DNS packet of 512 bytes, thus you need -s512

Recently I noticed that a snap length of 512 is not good enough any more.

It used to be that if a name server could not cram an answer in 512 bytes, it would send what fitted in, and indicate the incompleteness of the answer, by setting the truncation bit, a special flag, reserved for this purpose.
Upon noticing this truncation flag, the DNS client then would repeat the DNS query, but this time not using UPD but TCP so the server could send the complete answer over TCP.

This fall back mechanism to TCP is one of the reasons you need to allow port 53 traffic for both UDP and TCP. The second reason: DNS zone transfers use TCP too.

Using TCP is not without costs. Just setting up a TCP connection already takes 3 packets, the TCP handshake, then a packet for the repeated request, another one for the answer, then a few packets for tearing the TCP connection down. It takes a lot of time compared with sending one UDP packet for the request, and the second for the answer.

With IPv6 and DNSSEC mechanisms the articifial 512 byte limit became too restrictive. Nowadays there is an DNS extension, which allows a DNS client to say, "Hey I can receive 4096 bytes long answer over UDP"
See http://en.wikipedia.org/wiki/EDNS

Conclusion: if you want to capture DNS traffic, you really need a snap length of 4096. On some tcpdump versions, the FreeBSD version for example, you can have tcpdump figure out the snap length by using -s0.

Troubles caused by absence of -n flag

To assist in making sense of the it's output, tcpdump by default resolves the host addresses and port numbers to names.
For finding the port names it simply consults "/etc/services". A snippet from that file:
Code:
ssh             22/tcp
ssh             22/udp
telnet          23/tcp
smtp            25/tcp          mail
[snip]
domain          53/tcp          nameserver      # name-domain server
domain          53/udp          nameserver
For converting the hostnames, tcpdump directs reverse DNS lookups to the nameserver(s) specified in the "/etc/resolv.conf" file.
If you happen to debug a nameserver problem and thus are watching port 53 traffic, the tcpdump reverse lookups also show up in your log of dump file. To prevent these extra lookups from interfering you can use the "-n" flag:
Code:
     -n        Do not convert addresses (host addresses, port numbers, etc.)
               to names
Although still issuing extra reverse name lookups, and only mentioned here for completeness sake:
Code:
     -N        Do not print domain name qualification of host names.  For ex-
               ample, if you specify this flag then tcpdump will print ``nic''
               instead of ``nic.ddn.mil''.
Illustrating the two ways of display:
Code:
# tcpdump header output using '-n' option
20:33:44.739528 198.41.0.4.53 > 192.168.222.244.45428

# default tcpdump header output 
20:33:44.739528 a.root-servers.net.domain > vintrax.utp.xnet.45428
Circumventing the extra reverse DNS lookups at capture time

In tracing a DNS issue I thought to be be smart. We all do sometimes, isn't it? I instructed tcpdump to write the packets to file using the "-n" flag.
Code:
tcpdump -ni re0 -s4096 -w file
To analyze output I would use
Code:
tcpdump  -r file
Without any danger of messing up the data written to file, tcpdump could resolve the host addresses to names at analyzing time, not during capture time. That appeared to work nicely.

Code:
# tcpdump -vv -r dns.tcpdump

20:33:44.739528 a.root-servers.net.domain > vintrax.utp.xnet.45428:
[udp sum ok] 7429- q: A? ns1.isc-sns.net. 0/13/16 ns: net. NS
G.GTLD-SERVERS.net., net. NS D.GTLD-SERVERS.net., net. NS
J.GTLD-SERVERS.net., net. NS B.GTLD-SERVERS.net., net. NS
E.GTLD-SERVERS.net., net. NS I.GTLD-SERVERS.net., net. NS
M.GTLD-SERVERS.net., net. NS A.GTLD-SERVERS.net., net. NS
L.GTLD-SERVERS.net., net. NS F.GTLD-SERVERS.net., net. NS
C.GTLD-SERVERS.net., net. NS H.GTLD-SERVERS.net., net. NS
K.GTLD-SERVERS.net. ar:

A.GTLD-SERVERS.net. A a.gtld-servers.net,
A.GTLD-SERVERS.net. AAAA a.gtld-servers.net,
B.GTLD-SERVERS.net. A b.gtld-servers.net,
B.GTLD-SERVERS.net. AAAA b.gtld-servers.net,
C.GTLD-SERVERS.net. A c.gtld-servers.net,
D.GTLD-SERVERS.net. A d.gtld-servers.net,
E.GTLD-SERVERS.net. A e.gtld-servers.net,
F.GTLD-SERVERS.net. A f.gtld-servers.net,
G.GTLD-SERVERS.net. A g.gtld-servers.net,
H.GTLD-SERVERS.net. A h.gtld-servers.net,
I.GTLD-SERVERS.net. A i.gtld-servers.net,
J.GTLD-SERVERS.net. A j.gtld-servers.net,
K.GTLD-SERVERS.net. A k.gtld-servers.net,
L.GTLD-SERVERS.net. A l.gtld-servers.net,
M.GTLD-SERVERS.net. A m.gtld-servers.net,
. OPT UDPsize=4096 (529) (DF) (ttl 244, id 35057, len 557)
Nice isn't it? We see her an answer from 'a.root-servers.net' with source port domain directed to host 'vintrax.utp.xnet' with destination port 45428.

But aren't A records supposed to be IP addresses like this?
Code:
i.gtld-servers.net.     166755  IN      A       192.43.172.30
Yes, they are, but tcpdump in trying to be overly helpful also resolved the IP addresses from the A records in the packet payload.

To see the difference, the same file now decoded with "-n":
Code:
# tcpdump -vvn -r forums-dns.tcpdump

20:33:44.739528 198.41.0.4.53 > 192.168.222.244.45428: [udp sum ok]
7429- q: A? ns1.isc-sns.net. 0/13/16 ns: net. NS G.GTLD-SERVERS.net.,
net. NS D.GTLD-SERVERS.net., net. NS J.GTLD-SERVERS.net., net. NS
B.GTLD-SERVERS.net., net. NS E.GTLD-SERVERS.net., net. NS
I.GTLD-SERVERS.net., net. NS M.GTLD-SERVERS.net., net. NS
A.GTLD-SERVERS.net., net. NS L.GTLD-SERVERS.net., net. NS
F.GTLD-SERVERS.net., net. NS C.GTLD-SERVERS.net., net. NS
H.GTLD-SERVERS.net., net. NS K.GTLD-SERVERS.net. ar:

A.GTLD-SERVERS.net.  A 192.5.6.30,
A.GTLD-SERVERS.net. AAAA 2001:503:a83e::2:30,
B.GTLD-SERVERS.net. A 192.33.14.30,
B.GTLD-SERVERS.net. AAAA 2001:503:231d::2:30,
C.GTLD-SERVERS.net. A 192.26.92.30,
D.GTLD-SERVERS.net. A 192.31.80.30,
E.GTLD-SERVERS.net. A 192.12.94.30,
F.GTLD-SERVERS.net. A 192.35.51.30,
G.GTLD-SERVERS.net. A 192.42.93.30,
H.GTLD-SERVERS.net. A 192.54.112.30,
I.GTLD-SERVERS.net. A 192.43.172.30,
J.GTLD-SERVERS.net. A 192.48.79.30,
K.GTLD-SERVERS.net. A 192.52.178.30,
L.GTLD-SERVERS.net. A 192.41.162.30,
M.GTLD-SERVERS.net. A 192.55.83.30,
. OPT UDPsize=4096 (529) (DF) (ttl 244, id 35057, len 557)
Here we see the answer from 'a.root-servers.net' in it's full glory.

Anyway, happy tcpdump'ing
__________________
You don't need to be a genius to debug a pf.conf firewall ruleset, you just need the guts to run tcpdump
Reply With Quote