1. Overview

In this article, we’ll be looking at the tool tcpdump in Linux. In particular, we’ll be learning how to capture network packets using tcpdump in a Linux environment.

2. tcpdump

2.1. tcpdump in a Nutshell

tcpdump is a network packet sniffer tool in Linux. In essence, it listens on an interface and dumps any packets passing through the interface. Through the dumps, we’ll be able to gain more insight into the packets that are traveling through a node.

2.2. Installation

To install tcpdump in Debian-based Linux such as Ubuntu, we can use the apt-get command:

$ sudo apt-get update
$ sudo apt-get install -y tcpdump

Alternatively, we can perform the installation using yum on RHEL-based Linux like CentOS:

$ sudo yum update
$ sudo yum install -y tcpdump

2.3. General Syntax

Generally, tcpdump‘s syntax can be expressed as the command followed by a list of options and an expression:

tcpdump [OPTIONS] [expression]

The OPTIONS argument is an optional list of flags that we can specify to alter the different aspects of tcpdump. Additionally, the expression is a powerful construct that allows the user to further filter the packets by different properties.

2.4. Basic Usage

Let’s run tcpdump with its default configuration, without any flags or expression:

$ tcpdump
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:33:18.583077 IP 927e94ccde39.54226 > 192.168.65.4.53: 39122+ AAAA? www.baeldung.com. (34)
10:33:18.583082 IP 927e94ccde39.36545 > 192.168.65.4.53: 53932+ A? www.baeldung.com. (34)
10:33:18.583450 IP 927e94ccde39.38845 > 192.168.65.4.53: 61341+ PTR? 4.65.168.192.in-addr.arpa. (43)
10:33:18.623951 IP 192.168.65.4.53 > 927e94ccde39.36545: 53932 3/0/0 A 104.26.12.74, A 172.67.72.45, A 104.26.13.74 (82)
10:33:18.624004 IP 192.168.65.4.53 > 927e94ccde39.54226: 39122 3/0/0 AAAA 2606:4700:20::ac43:482d, AAAA 2606:4700:20::681a:c4a, AAAA 2606:4700:20::681a:d4a (118)
10:33:18.624381 IP 927e94ccde39.35182 > 104.26.12.74.80: Flags [S], seq 3026253548, win 64240, options [mss 1460,sackOK,TS val 3916952268 ecr 0,nop,wscale 7], length 0
10:33:18.668779 IP 104.26.12.74.80 > 927e94ccde39.35182: Flags [S.], seq 452853775, ack 3026253549, win 65535, options [mss 1460,wscale 2,eol], length 0
10:33:18.668809 IP 927e94ccde39.35182 > 104.26.12.74.80: Flags [.], ack 1, win 502, length 0
10:33:18.668873 IP 927e94ccde39.35182 > 104.26.12.74.80: Flags [P.], seq 1:81, ack 1, win 502, length 80: HTTP: GET / HTTP/1.1
10:33:18.671819 IP 104.26.12.74.80 > 927e94ccde39.35182: Flags [.], ack 81, win 65535, length 0
10:33:18.691618 IP 104.26.12.74.80 > 927e94ccde39.35182: Flags [P.], seq 1:610, ack 81, win 65535, length 609: HTTP: HTTP/1.1 301 Moved Permanently
10:33:18.691628 IP 927e94ccde39.35182 > 104.26.12.74.80: Flags [.], ack 610, win 501, length 0

When we don’t specify an interface, tcpdump will listen to the lowest numbered interface among the list of interfaces on the system. In this case, it has chosen eth0 as the interface to listen on. Then, it captures and prints to console any packets going through the interface.

From the output, we can see the details of the network packet in each row. Let’s take a deeper look into one example packet dump:

10:33:18.583077 IP 927e94ccde39.54226 > 192.168.65.4.53: 39122+ AAAA? www.baeldung.com. (34)

From the output, we can identify the time this packet has been captured. Besides that, we know that this packet is an IP packet, as the protocol is displayed beside the timestamp.

Additionally, we know from the dump that this packet originated from the host 927e94ccde39 on port 54226 and it’s going towards 192.168.65.4 on port 53.

3. Options for Network Interfaces

3.1. Listing System Interfaces

We can query the list of interfaces that are available on the system using the -D flag:

$ tcpdump -D
1.eth0 [Up, Running]
2.eth1 [Up, Running]
3.lo [Up, Running, Loopback]
4.any (Pseudo-device that captures on all interfaces) [Up, Running]
5.bluetooth-monitor (Bluetooth Linux Monitor) [none]
6.nflog (Linux netfilter log (NFLOG) interface) [none]
7.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
8.tunl0 [none]
9.ip6tnl0 [none]

As we can see, tcpdump also displays the status of each interface. In addition to the actual network interfaces, tcpdump creates a pseudo-device called “any”. By listening to this pseudo-device any, tcpdump will capture the packet passing through all the interfaces.

3.2. Specifying an Interface

On a system with multiple interfaces, we can select which interface to listen to using the -i flag:

$ tcpdump -i wlan0

The command above starts tcpdump on the interface wlan0. Additionally, we can capture the packets of all the interfaces using the pseudodevice any:

$ tcpdump -i any

4. Formatting the Timestamp

On each packet dump output, tcpdump appends a timestamp at the first column to indicate the time at which the packet is captured. tcpdump supports the formatting of this timestamp output using the -t flag.

4.1. Suppressing Timestamp Information

To prevent tcpdump from printing any timestamp information, we can specify the -t flag:

$ tcpdump -t
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
IP centos-box.intra.40600 > 927e94ccde39.443: Flags [P.], seq 1584919446:1584919451, ack 1644285291, win 502, options [nop,nop,TS val 1654074382 ecr 2691638716], length 5
IP 927e94ccde39.443 > centos-box.intra.40600: Flags [.], ack 5, win 510, options [nop,nop,TS val 2693653313 ecr 1654074382], length 0

4.2. Printing Timestamp in Epoch Time

We can also print the timestamp in seconds after the epoch (January 1, 1970 00:00:00 UTC) using the -tt flag:

$ tcpdump -tt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
1615623341.099481 IP centos-box.intra.40600 > 927e94ccde39.443: Flags [P.], seq 1584919451:1584919456, ack 1644285291, win 502, options [nop,nop,TS val 1654246252 ecr 2693653313], length 5
1615623341.099494 IP 927e94ccde39.443 > centos-box.intra.40600: Flags [.], ack 5, win 510, options [nop,nop,TS val 2693825183 ecr 1654246252], length 0

From the output, we can observe that the timestamp resolution is down to the microsecond level.

4.3. Printing Timestamp in Time Delta

We can output the timestamp in terms of the delta using the -ttt flag. Concretely, tcpdump will print on each line the time difference between the current dump and the previous dump:

$ tcpdump -ttt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
 00:00:00.000000 IP centos-box.intra.40600 > 927e94ccde39.443: Flags [P.], seq 1584919456:1584919461, ack 1644285291, win 502, options [nop,nop,TS val 1654379130 ecr 2693825183], length 5
 00:00:00.000014 IP 927e94ccde39.443 > centos-box.intra.40600: Flags [.], ack 5, win 510, options [nop,nop,TS val 2693958061 ecr 1654379130], length 0

In the example above, we can easily deduce that the time difference between the first and second packets is 14 microseconds.

4.4. Printing Timestamp With Date

Finally, we can print the timestamp and the date using the -tttt flag:

$ tcpdump -tttt
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
2021-03-13 08:20:05.370345 IP centos-box.intra.40600 > 927e94ccde39.443: Flags [P.], seq 1584919461:1584919466, ack 1644285291, win 502, options [nop,nop,TS val 1654510522 ecr 2693958061], length 5
2021-03-13 08:20:05.370400 IP 927e94ccde39.443 > centos-box.intra.40600: Flags [.], ack 5, win 510, options [nop,nop,TS val 2694089454 ecr 1654510522], length 0

5. Saving Packet Dumps to Files

tcpdump also provides several flags that allow us to write the packet dumps to files.

5.1. Writing to File

To write the packet dumps to file, we can use the flag -w followed by the filename:

$ tcpdump -w packet-captured.pcap

When we write the dumps to the file, tcpdump will no longer print the dumps to standard output.

5.2. Limiting the Size of Each File

We can limit the size of each file using the -C flag. The flag accepts an integer value that represents the size limit of each file in millions of bytes:

$ tcpdump -w out.pcap -C 2

In the example above, tcpdump will write the packets captured into the file out.pcap. Once the file reaches the size of 2MB, and for each 2MB increment thereafter, it’ll save the subsequent packets into new files out.pcap1, out.pcap2, out.pcap3, and so on.

5.3. Rotating Save Files on Interval

With the -G flag, tcpdump saves the dumps into a new file at a specified interval. For example, we can rotate the save files every five seconds:

$ tcpdump -w out-%Y%m%d-%H%M%S.pcap -G 5

In the example above, we’re naming our file dynamically based on the strftime format. If the filename is specified in such a way that it is constant every specified interval, the previous save file will be overwritten.

6. Running in Monitor Mode

On IEEE 802.11 WiFi interfaces, monitor mode allows the interface to capture all the packets received on the wireless channel. Additionally, it can sniff the packets without even associating or linking to a particular access point.

To run tcpdump on an interface in monitoring mode, we can use the -I flag:

$ tcpdump -I

However, do note that not all interfaces support monitor mode. tcpdump will output an error message if we’ve tried to run monitor mode on interfaces that do not support it:

$ tcpdump -i eth0 -I
tcpdump: eth0: That device doesn't support monitor mode

7. Other Useful Options

7.1. Suppressing Address Lookup

By default, tcpdump automatically resolves the names of host addresses. This might be undesirable, as it induces network overhead for DNS lookup. We can suppress the lookup using the -n flag:

$ tcpdump -n

7.2. Direction of Packet

tcpdump captures both incoming and outgoing traffic of an interface. We can capture packets of a specific direction using the -Q flag followed by the direction value in, out, or inout. For example, we can capture only the outgoing packets on interface eth0:

$ tcpdump -i eth0 -Q out

7.3. Printing the Packet Number

We can make tcpdump to display the packet number in each output line using the -# flag:

$ tcpdump -#
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
    1  10:33:50.254707 IP 927e94ccde39.55667 > 192.168.65.4.53: 36710+ AAAA? www.baeldung.com. (34)
    2  10:33:50.254897 IP 927e94ccde39.49841 > 192.168.65.4.53: 19808+ A? www.baeldung.com. (34)
    3  10:33:50.255044 IP 927e94ccde39.58436 > 192.168.65.4.53: 37800+ PTR? 4.65.168.192.in-addr.arpa. (43)

As we can see, each of the output lines will now have a number. This number runs in sequence and provides an indication of the number of packets captured so far.

8. Expression

Other than the myriad of options flag we can use, tcpdump also offers a set of syntax that we can specify as the final argument. Using the expression, we can construct a ruleset that’ll filter the packets based on their attributes, such as the protocol.

8.1. Syntax Structure

Generally, the expressions are made up of primitives and qualifiers:

[qualifier...] qualifier primitive [and|or|not] [primitive...]

The primitives are generally number or string. These primitives do not have meaning in themselves. To give meaning to these primitives, we’ll precede them with one or more qualifiers.

There are three different qualifiers in the syntax — namely, type, dir, and proto. The type qualifier specifies the type of the primitives. For example, if a primitive of 80 is specified along with a type port, then the primitive value of 80 stands for port number 80. The possible values of type qualifiers are host, net, port, and portrange. The value host is assumed for an expression if there is no type qualifier specified.

The qualifier dir specifies the direction of the packets. Some of the possible values for this qualifier are src, dst, src or dst, and src and dst.

Besides that, the qualifier proto stands for the protocol of the packets to match. The possible values for this qualifier include ether, ip, ip6, arp, tcp, and udp.

Finally, the syntax also contains words like and, or, and not, that allows us to combine primitives to build up complex expressions. Their symbolic representations like &&, ||, and ! are also recognized by the expression parser.

Let’s look at some examples.

8.2. Filter Packets by Host

One of the simplest ways to filter the packets is to filter by their host. Concretely, we can capture packets that are associated with a particular host using the host syntax:

$ tcpdump 'host www.baeldung.com'

The command above will only dump packets if they are originating from or going to www.baeldung.com.

8.3. Filter Packets by Port

We can also filter the packets by their port number using the qualifier port:

$ tcpdump 'port 80'

The command above only captures any packets that are coming from or going to port 80. Additionally, we can be specific about the direction using src or dst. For example, if we only want to capture packets if the source field is of port 80, we can prepend the expression with src:

$ tcpdump 'src port 80'

Besides that, the qualifier portrange allows us to specify the range of port numbers we wish to capture the packets from:

$ tcpdump 'portrange 80-90'

With the expression above, tcpdump capture any packets that fall within the port range from 80 to 90.

8.4. Filter Packets by Network

Using the net qualifier, we can filter the packets based on the network they belong to. For instance, we can capture packets that come from the 192.168.0.1/16 network:

$ tcpdump 'net 192.168'

When we omit the last two bytes, tcpdump automatically applies the netmask /16 to the network.

The netmask can be explicitly specified using the mask qualifier as well:

$ tcpdump 'net 192.168.0.1 mask 255.255.0.0'

The two different expressions ultimately construct the same filter.

8.5. Filter Packets by Protocol

To filter the packets by their protocol, we can use the qualifier proto followed by the protocol name. For example, we can dump only the UDP packets:

$ tcpdump 'proto udp'

The tool provides a few shortcuts for the more commonly known protocols, such as tcp, udp, and icmp. For example, the command above can be rewritten with just the tcp expression:

$ tcpdump 'udp'

8.6. Other Useful Expressions

Using the syntax less or greater, we can filter packets by their packet length. For example, to only capture packets that are less than 40 in length:

$ tcpdump 'less 40'

On the other hand, to capture packets only if they are greater than 40 in length:

$ tcpdump 'greater 40'

Instead of using the flags, we can filter the packets by their direction using the qualifiers inbound and outbound. For example, to capture only the incoming packets, we can use the inbound syntax:

$ tcpdump 'inbound'

Similarly, we can dump only outgoing packets using the syntax outbound:

$ tcpdump 'outbound'

8.7. Logical Syntax

tcpdump supports logical constructs like and, or, and not that allow us to build a more complex ruleset. For example, we can build a filter that only captures traffic that comes from either host www.baeldung.com or www.google.com:

$ tcpdump 'src host www.baeldung.com or www.google.com'

Additionally, we can construct a filter that captures packets coming from www.baeldung.com on port 443 using the and operator:

$ tcpdump 'host www.baeldung.com and port 443'

Finally, the not operator can be used to negate the expression. For example, we can capture every packet except those that come from the 192.168.0.1/16 network:

$ tcpdump 'not net 192.168'

9. Conclusion

In this article, we’ve looked at tcpdump in depth.

We’ve started off with a basic introduction to the tool. Then, we’ve demonstrated its basic usage. The subsequent sections then introduce some of the flags that we can use on the tool.

Besides that, we’ve also looked at the various flags we can use to change how tcpdump writes the dumps into files.

Finally, we’ve shown how the expression can be constructed to filter the packets for different purposes.