This Masterclass article series aims to provide in-depth technical information on the installation, usage and operation of the classic and supremely popular tcpdump network traffic analysis program including alternatives, running tcpdump as a process, building expressions, understanding output and more. I’ve covered the Basics, Parameters and filter Expressions previously; last up in the series is this article.
Strangely this is something I wasn’t too bothered with in the past; I understood enough to get by just fine and was largely focussed on the application layer payload rather than TCP/IP operations. I’m sure most people are the same but the little extra knowledge detailed here might just become invaluable at some point in time when you do need to dig deeper. It’s all in glorious colour too.
If you do have anything useful that I’ve not included here (such as information on other protocols that get formatted), please do let me know. Note that I’ve not covered IPv6 here at all; I really don’t see the point, yet.
Generic TCP
Here’s a line of output related to an SSH session. Note the -v parameter has been used, without it, the IP header information and some of the TCP information is not displayed.
22:24:18.910372 IP (tos 0x10, ttl 64, id 9792, offset 0, flags [DF], proto TCP (6), length 88)
78.47.105.76.ssh > 82.132.219.219.55495: Flags [P.], cksum 0xcb29 (correct), seq 497880562:497880610(48), ack 1593322765, win 379, length 48
So, let’s break down the components (bits and octets relate to the IP header fields);
- 22:24:18.910372 – the datagram’s timestamp
- IP (tos 0x10, ttl 64, id 9792, offset 0, flags [DF], proto TCP (6), length 88) – the layer three datagram’s header fields and values;
- tos 0x10 – the IP TOS value (more correctly in the present context, the DS and ECN fields (8 bits, 2nd octet)
- ttl 64 – the IP TTL value, this field is not shown if the TTL is zero (8 bits, 9th octet)
- id 9792 – used for identifying the parts of a fragmented datagram (16 bits, 5th and 6th octets) [see RFC 791 and RFC 6864]
- offset 0 – the fragment offset, used with fragmented packets, should be 0 or a multiple of 8, displayed in bytes (13 bits of the 7th and 8th octets) [see RFC 791]
- flags [DF] – any IP flags set; [DF] for Don’t Fragment and [+] for More Fragments (3 bits of the 7th octet) [see RFC 791]
- proto TCP (6) – the higher layer (four) protocol and it’s number (8 bits, 10th octet)
- length 88 – the IP packet length, including all headers, in Bytes (16 bits, 3rd and 4th octets)
- tos 0x10 – the IP TOS value (more correctly in the present context, the DS and ECN fields (8 bits, 2nd octet)
- 78.47.105.76.ssh – the source IP address and port
- 82.132.219.219.55495 – the destination IP address and port
- Flags [P.] – any TCP flags; a period ‘.‘ indicates an ACK
- cksum 0xcb29 (correct) – the packet’s TCP checksum value
- seq 497880562:497880610(48) – the TCP packet’s starting and ending sequence numbers, the value in brackets indicates the difference and thus the amount of data carried (in Bytes); this should match the length field
- ack 1593322765 – the TCP packet’s acknowledgement number
- win 379 – the source host’s TCP window
- length 48 – the TCP packet length (in Bytes) not including the headers – in other words, the payload or data’s length. This means the IP and TCP headers combined were 40Bytes long.
So you can see the difference and some more fields, here’s a SYN packet – note the extra options in this one (some only seen because it’s a SYN packet) and the length of 0 as no data can be exchanged yet (TCP Fast Open isn’t in use).
10:26:37.855362 IP (tos 0x0, ttl 64, id 52766, offset 0, flags [DF], proto TCP (6), length 60)
172.20.16.98.53726 > 82.132.219.219.https: Flags [S], cksum 0x694e (correct), seq 2720785584, win 29200, options [mss 1460,sackOK,TS val 18361006 ecr 0,nop,wscale 7], length 0
Let’s take a look at those extra options;
- mss 1460 – the maximum segment size (MSS) this host supports – only seen in a SYN packet [see RFC 793] – this is TCP option kind 2
- sackOK – indicates the host permits the use of Selective Acknowledgement- only seen in a SYN packet [see RFC 2018] – this is TCP option kind 4
- TS val 18361006 – the sending host’s timestamp [see RFC 7323] – this is TCP option kind 8
- ecr 0 – the echo reply timestamp value (the most recent timestamp this host has received from the other end); it’s 0 because this is a SYN packet [see RFC 7323] – this is TCP option kind 8
- nop – used to align option headers to 32-bit word boundaries by padding 1 byte with 00000001, may be used more than once if necessary [see RFC 793] – this is TCP option kind 1
- wscale 7 — window scale and value, only seen in a SYN packet [see RFC 7323] – this is TCP option kind 3
A few not shown in the example which you might also see:
- eol – the ‘end of option list’ option used to indicate the end of all options if necessary; 1 byte of all zeros [see RFC 793] – this is TCP option kind 0
Generic UDP
It’s odd how often people don’t think they even use UDP but we all do for Voice, Video, DNS, DHCP, NTP, VXLAN and the like.
Here’s some output related to DNS. Request without -v;
22:54:40.769351 IP 78.47.105.76.6891 > 213.133.100.100.domain: 28642+ AAAA? vps.allenz.eu. (31)
Response with -v, as you can see, without it the IP header information and the UDP information is not displayed;
22:47:08.352707 IP (tos 0x0, ttl 60, id 1457, offset 0, flags [none], proto UDP (17), length 72)
213.133.99.99.domain > 78.47.105.76.16165: [udp sum ok] 11711 ServFail q: A? 40.1.255.158.bl.tiopan.com. 0/0/0 (44)
So, let’s break down the components of that last one;
- 22:47:08.352707 – the datagram’s timestamp
- IP (tos 0x0, ttl 60, id 1457, offset 0, flags [none], proto UDP (17), length 72) – the layer three datagram’s header fields and values;
- tos 0x0 – the IP TOS value (more correctly in the present context, the DS and ECN fields (8bit, 2nd octet)
- ttl 60 – the IP TTL value (8bit, 9th octet)
- id 1457 – mostly used for identifying the parts of a fragmented datagram; incremented by one with every packet sent (16bit, 5th and 6th octets)
- offset 0 – the fragment offset, used with fragmented packets (13bits of the 7th and 8th octets)
- flags [none] – any IP flags set; [DF] for Don’t Fragment and [MR] for More Fragments (3bits of the 7th octet)
- proto UDP (17) – the higher layer (four) protocol and it’s number (8bits, 10th octet)
- length 72– the entire IP packet length, including headers (16bits, 3rd and 4th octets)
- 213.133.99.99.domain – the source IP address and port
- 78.47.105.76.16165 – the destination IP address and port
- [udp sum ok] – the datagram’s checksum status
- Everything else relates to the DNS application response.
Notes on the proto(col) Field
You can find a full list of protocol number assignments here. Here’s a few more you might know;
- ICMP (1)
- IGMP (2)
- GRE (47)
- ESP (50)
- VINES (83) < Anyone remember this?
- EIGRP (88)
- ETHERIP (97)
- OSPF (89)
- VRRP (112)
- L2TP (115)
- SCTP (132) < Whadya mean you’ve never heard of it 😉
Notes on Service Ports
I’m sure you all know this but anyway, valid port numbers are 0 through to 65535. If you want to live by IANA assignments (and we all should right?);
- 0 to 1023 are reserved for well known applications
- 1024 to 49151 are registered (with IANA) ports
- 49152 to 65535 are user and dynamic ports (aka ephemeral or temporary)
Protocol Formatting
tcpdump provides data formatting for the following protocols amongst others (see Jens comments below for more information);
- ICMP
- ISAKMP
- ARP
- NTP
- DNS
- STP
- HSRP
- SNMP
- RADIUS
Thanks again to Jens for this: If you see ‘[|proto]’ at the end of the verbose output, e.g. ‘[|radius]’ the snap length is too small for the application data to be captured;. just increase it (using the -s0 parameter) to see the complete application data information.
Here’s a few examples;
ARP: 22:45:47.220050 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 78.47.108.52 tell 78.47.108.49, length 46
NTP (with -v);
78.47.105.76.ntp > 213.239.239.166.ntp: NTPv4, length 48
Client, Leap indicator: (0), Stratum 3 (secondary reference), poll 10s, precision -22
Root Delay: 0.020477, Root dispersion: 0.056991, Reference-ID: 83.137.98.96
…
DNS: 213.133.99.99.domain > 78.47.105.76.16165: [udp sum ok] 11711 ServFail q: A? 40.1.255.158.bl.tiopan.com. 0/0/0 (44)
Fragmented Packets
Note that when fragmented packets are encountered;
- Extra fields detailing fragment ID, fragment data size and offset are displayed
- Port numbers are only shown for the first fragment as this is the only one carrying the layer four information
- The data size shown is always for the fragment, not the size that will result when the fragments are recombined
- An offset of @0+ indicates this is the first fragment
- An offset that doesn’t end with a + indicates this is the last fragment
As ever, comments are welcome.
The icon Artwork used in this article is by the GNOME Project and licensed under the Creative Commons Attribution-Share Alike 3.0 United States License.
There are several more protocol formatters in tcpdump just have a look into the names of the print-*.c source files, e.g. STP, HSRP, SNMP, RADIUS, …
One additional hint: if you see ‘[|proto]’ at the end of the verbose output, e.g. ‘[|radius]’ the snap length is too small for the application data to be captured. Just increase that to see the complete application data information.
Personally I really like the ISAKMP formatter that is very handy for quick-debugging proposal problems between VPN gateways. The RADIUS formatter lists all AVPs and is quite nice as well (although the wireshark RADIUS dissector does a very good job to also decrypt the password with a given secret).
Another goodie: In environments where CDP is enabled following tcpdump call can easily find the switch port the device’s interface is connected to:
# tcpdump -i -v -s0 -c1 ‘ether[20:2] == 0x2000’
Thanks DISQUS, but there is no close-tag to name-of-interface 😉
# tcpdump -i name-of-interface -v -s0 -c1 ‘ether[20:2] == 0x2000’
Thanks Jens (again). I’ll incorporate some of this into the article later today. Cheers, it’s appreciated.
OSPF should be IP protocol 89, not 99.
Thanks Mark, I’m duly embarrassed 😉 Article updated.
Found something not exactly obvious about tcpdump this week: a NIC that does TCP offload will reconstruct large fragments even for traffic that has been SPANed to it. So, disable all your offloads (ethtool -k under Linux) when using tcpdump+SPAN to see what is *actually* on the wire.
Thanks Ian, I’ll add a note to the Basics article I think. Cheers
Found something not exactly obvious about tcpdump this week: a NIC that does TCP offload will reconstruct large fragments even for traffic that has been SPANed to it. So, disable all your offloads (ethtool -k under Linux) when using tcpdump+SPAN to see what is *actually* on the wire.