BSD DevCenter
oreilly.comSafari Books Online.Conferences.


FreeBSD Basics

Capturing TCP Packets


In last week's article, we went through the various fields found in the Layer 3 and Layer 4 headers of an IP packet. While these fields may seem mind-numbingly technical at first, there is a good reason to be aware of the possible values for each field.

The values found in an IP packet's headers provide all of the information necessary to successfully send data from one computer running TCP/IP to another computer running TCP/IP; it doesn't matter if the two computers are cabled onto the same LAN or if they are physically separated by large geographic distances, the data will still arrive intact. Unfortunately, this robustness is a double-edged sword. If someone is so inclined, they can exploit the values found in an IP packet's headers in order to break into a computer running TCP/IP so they can steal or tamper with its data.

Your FreeBSD system provides many mechanisms to help protect your data from such exploits; these include ipfw, natd, ipfilter, and tcp wrappers. In order to successfully configure these mechanisms and ensure that they are blocking unwanted IP packets but are still allowing the delivery of wanted IP packets, you need to be aware of the differences in the values in the IP headers of a wanted and unwanted IP packet.

In today's article, I'd like to demonstrate the use of the tcpdump utility. This utility captures packets so you can examine the data and the headers within each packet. For this reason, you only run this utility on your own network; I repeat, don't run this utility on someone else's network unless they have given you explicit permission to do so.

When you run tcpdump, it will put your NIC into what is known as "promiscuous" mode. Normally, when a NIC sees a packet being transmitted on the media, it only monitors the signal long enough to determine if that packet is destined for its MAC address. If it is addressed to its MAC address, it will load the entire packet into RAM until the TCP/IP protocol has a chance to process the packet. If it is not addressed to its MAC address, it will simply ignore the rest of the packet and wait to monitor the next packet that is transmitted. When a NIC is placed into promiscuous mode, it will load and process all packets, regardless of whom the packets are destined for. This doesn't mean that the original recipient won't receive its packet; instead, it means that the packet will be received by both the intended recipient and the NIC that is running in promiscuous mode.

When you put a NIC into promiscuous mode on a FreeBSD system, the Berkeley Packet filter or bpf device is loaded. If you are running a recent version of FreeBSD, the bpf device should already be in your kernel. If it is not, this FAQ tells you what line you need to add to your kernel, and this link will give instructions on how to rebuild your kernel.

There is one last thing we need to be aware of before we run the tcpdump utility. Before an IP packet can be transmitted over a media, it must first be placed into a "frame"; this process is known as encapsulation. Encapsulation occurs at what is known as Layer 2, and it is the job of the interface that will transmit the packet to first encapsulate that packet into a frame. Just as there are many types of interfaces capable of transmitting packets, there are many types of frames. For example, a NIC may be cabled to an Ethernet network or to a Token Ring network; accordingly, there are Token Ring frames, which are different from Ethernet frames. Instead of a NIC, you may use a dial-up modem to connect to a network; in this case, your modem uses PPP, which in turn uses a protocol known as HDLC to create the PPP frames.

In my home network, I have a computer named "genisis" with an IP address of; it is connected using an Ethernet topology to a computer named "biko" whose IP address is I'll use the tcpdump utility to capture the packets that are used to establish and disconnect a telnet session between these two computers.

Only the superuser can run the tcpdump utility; regular users will receive this warning message instead:

tcpdump: /dev/bpf0: Permission denied

On the computer "genisis," I'll become the superuser and start the tcpdump utility like so:


tcpdump -s 1518 -i ed0 -w dump
tcpdump: listening on ed0

A note on the switches I used: I specified the maximum number of bytes to capture per frame with -s 1518, which is the maximum size of an Ethernet frame. I specified which interface to monitor with -i ed0, and I told tcpdump to send its output to a file named dump instead of to my screen with -w dump.

If I now press ALT-F1, I'll also see the following console message:

Mar 4 10:25:24 genisis /kernel: ed0: promiscuous mode enabled

Now, at the computer named "biko," I'll telnet into the computer "genisis"; once I've successfully logged in, I'll immediately exit from the telnet connection:

Connected to genisis.
Escape character is '^]'.

FreeBSD/i386 ( (ttyp0)

login: genisis
Warning: your password expires on Thu Mar  8 17:31:47 2001
Last login: Sun Mar 4 10:23:04 from
Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994
	The Regents of the University of California.  All rights reserved.

FreeBSD 4.2-RELEASE (SOUND) #0 Tue Dec 12 20:01P29 EST 2000

			Welcome to FreeBSD 4.2!!!

You have mail.

Everybody is somebody else's weirdo.

Connection closed by foreign host.

I then return to the keyboard on "genisis" and end the tcpdump like so:

88 packets received by filter
0 packets dropped by kernel

And if I double-check the console:

Mar 4 10:25:44 genisis /kernel: ed0: promiscuous mode disabled

Since there aren't any other computers on this network, all of those 88 packets captured during that 20-second interval dealt with establishing and ending that telnet session.

There are several ways to analyze the output of my newly created "dump" file. I'll demonstrate several ways to view this file so you can see that different utilities vary in the amount of detail they show you regarding the contents of each captured frame.

Let's start by seeing what type of file tcpdump created:

file dump
dump: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 1518)

The dump file is not a text file, so we won't be using an editor or a pager to view its contents. We can use the tcpdump utility with the r switch to analyze the contents of this file; however, this output is not exactly novice friendly. I'll show some snipped output to demonstrate; at the very least, you may recognize some fields from last week's article:

tcpdump -r dump

<snipped to just show packets 10-12>

10:25:36.854420 > S 3205630181:3205630181(0) win 16384 <mss 1460> (DF) [tos 0x10]
10:25:36.854653 > S 1746119590:1746119590(0) ack 3205630182 win 17520 <mss 1460> (DF)
10:25:36.854996 > . ack 1 win 17520 (DF) [tos 0x10]

The FreeBSD ports collection contains a utility known as tcpshow that can be used to display dump files created by tcpdump. Let's build this utility as the superuser and try it out:

cd /usr/ports/net/tcpshow
make install clean

Once your build is finished, you can exit the superuser account, as you don't need to be the superuser to use the tcpshow utility. Assuming you are in the same directory as the dump file to be analyzed, type:

tcpshow < dump |more

I won't analyze every packet with you, but I would like to look at some of the highlights of packets 10 to 12. You may remember from Understanding BSD Daemons (page 2) that TCP uses a three-way handshake before any data is actually transmitted. Let's take a look at packet number 10:

Packet 10
TIME: 10:25:36.854420 (6.232947)
LINK: 00:00:B4:3C:56:40 -> 00:50:BA:DE:36:33 type=IP
  IP: biko -> genisis hlen=20 TOS=10 dgramlen=44 id=0013
  MF/DF=0/1 frag=0 TTL=64 proto=TCP cksum=26A7
 TCP: port blackjack -> telnet seq=3205630181 ack=0000000000
      hlen=24 (data=0) UAPRSF=000010 wnd=16384 cksum=7814 urg=0
DATA: <No data>

Not counting the TIME heading, there are four parts to this packet. The LINK heading represents the Layer 2 frame. Normally, this is the portion of the packet that is monitored by the NIC; you'll note that it contains the MAC address of the sending computer and the MAC address of the destination computer. There are several different types of Ethernet frames; I can tell this is an Ethernet_II frame since it contains a "type" field.

Pages: 1, 2

Next Pagearrow

Sponsored by: