Last week we took a deep dive into decoding TCP headers, so that we would know what the heck we were looking at when firing up tcpdump. Today we'll dig into specific tcpdump commands for looking at traffic from specific protocols, hosts, or ports, and how to save tcpdump's output to various file formats for analysis with other utilities.
Exporting tcpdumps to File
tcpdump merely captures packet headers; it does not have reporting or analysis capabilities. If you are going to do any kind of extended packet capture and analysis, it is best to capture it to a file, then use something like Ethereal or Snort to sort it out. As with all things Linux, there are several ways to do this. Use the -l switch to create re-directable output, or as man tcpdump says "Make stdout line buffered." The following command stores output in webdump.txt, and displays it on the screen at the same time:
# tcpdump port 80 -l > webdump.txt & tail -f webdump.txt
And so does this:
# tcpdump -l | tee webdump.txt
This creates a human-readable ASCII text file. Another way to do this is to capture the raw data in a binary file. This is a good thing to do when you want to capture a huge glob of unfiltered traffic and analyze it later with Ethereal or Snort:
# tcpdump -w rawdump
You can also replay it in tcpdump by naming the file to be read with the -r switch, then re-directing the output to another file:
# tcpdump -r rawdump > rawdump.txt
tcpdump runs until you stop it with Ctrl+c, so you might want to set a limit on the number of packets to capture, so that it will stop itself:
# tcpdump -c1000 -w rawdump
tcpdump defaults to the lowest-numbered NIC, which is usually eth0. Use the -i flag to specify a different NIC:
# tcpdump -i eth1 -c1000 -w rawdump
These two commands are the tcpdump workhorses. The first one captures traffic on a specific port. The second one captures traffic on a specific host on the LAN. (See Part 1, "Hubs Are Blabbermouths" and "Foiled By Switches" for more on how to do this.)
# tcpdump port nn
# tcpdump host 220.127.116.11
You can select several hosts on your LAN, and capture the traffic that passes between them:
# tcpdump host workstation4 and workstation11 and workstation13
Or capture all the LAN traffic between workstation4 and the LAN, except for workstation11:
# tcpdump workstation4 except workstation11
It can be useful to show the MAC addresses, especially when you're debugging network problems, because the MAC address is the definitive identification for a host. Use the -e flag:
# tcpdump -e host workstation4 and workstation11 and workstation13
Yes, astute reader, you read it right- you can spy on the traffic exchanged between certain computers on your LAN.
Excluding ThingsThe default is to capture all packets. You can capture all packets except those for certain ports, like this:
# tcpdump not port 110 and not port 25 and not port 53 and not port 22
A useful option is to declutter the display with the -t flag, which suppresses the timestamps:
# tcpdump -t not port 110 and not port 25
You can speed up performance and decrease clutter further by turning off DNS lookups with the -n flag:
# tcpdump -tn not port 110 and not port 25
Or you can go nuts and increase the amount of data shown with the -v and -vv flags. -vv is the most verbose:
# tcpdump -vv
Here is a sample of what you'll see with -vv:
192.168.1.5.35401 > 18.104.22.168.995: R [tcp sum ok] 394522529:394522529(0) win 0 (DF) (ttl 64, id 684, len 40)
22.214.171.124.1985 > 126.96.36.199.1985: [udp sum ok] udp 20 [tos 0xc0] (ttl 2, id 0, len 48)
Some of the additional fields displayed are:
checksum. A checksum is computed for each segment; damaged segments are discarded.
ttl is time to live. The standard ttl is two minutes; if a packet is still floating around undelivered after two minutes, it is discarded. In this example, the limit is 64 seconds.
id is a segment identification number, to assist in re-assembling datagram fragments.
tos, type of service, contains the values for precedence, delay, throughput, and reliability. Applications can theoretically set these values; for example, streaming video wants low latency, which is the delay value. In practice, this field is mostly useless in IPv4, because routers can be configured to ignore the TOS field, and there is no way to enforce the sensible use of it. IPv6 promises to make it meaningful, but again the problem lies in the implementation, not the standard.
len is the length, in bytes, of the segment.
Filtering on Protocols
A very useful tcpdump filter is the ability to filter on different protocols. Suppose you want to see only udp traffic:
# tcpdump udp
tcpdump recognizes the keywords ip, igmp, tcp, udp, and icmp. You can also specify any protocol named in /etc/protocols by using the proto qualifier. This example captures ospf (Open Shortest Path First) traffic, which is useful for eavesdropping on routers:
# tcpdump ip proto OSPFIGP
To capture traffic on a specific host and restrict by protocol, do this:
# tcpdump host server02 and ip
# tcpdump host server03 and not udp
# tcpdump host server03 and ip and igmp and not udp
When you look at what goes over the wires after the simple act of clicking on a URL, or checking email, it is amazing that it works at all. In these here spyware-infested times, one of the most useful things you can do with a packet sniffer is monitor the traffic coming off Windows PCs. Nothing can be hidden, it's all there for your keen probing eye to find.
- See Scripting Clinic: Have a bash with this Linux Shell for more information on the various bash-isms used here, such as the pipe, re-direct, and control operators.
- See Mind Your Packets with Ethereal to learn more about using ethereal to parse and analyze packets.
- Unlike my columns, RFCs are less-than-riveting reading. but they contain complete information.
- RFC 793 describes the transmission control protocol (tcp) in exhaustive detail.
- RFC 1180 is an excellent tcp tutorial.
- tcpdump home page