Using tcpdump: Options, Filters and Examples

Lesson

What is tcpdump?

tcpdump is a command-line tool available for UNIX based systems (including macOS and Linux) that captures network traffic and displays it on screen or saves it to a file. It is a simple but powerful tool for troubleshooting network problems, understanding protocols, investigating suspicious network activity, and much more. Therefore, tcpdump is routinely used by cybersecurity professionals, system administrators and network engineers.

For the latest and most comprehensive information about tcpdump, consult the relevant system reference manual pages with man tcpdump.

Installing tcpdump

Depending on your platform, tcpdump may already be installed or may be available from your package repository. For example, on macOS, tcpdump is installed by default. You can check if tcpdump is installed by simply typing the command tcpdump or trying one of the following commands.

# check if tcpdump is installed and which version you have
tcpdump --version

# check if tcpdump is installed and find out where it is on the system
which tcpdump

If you don't already have it, you need to install the tcpdump package.

# Ubuntu and other Debian based systems
apt install tcpdump
# Centos and other Fedora-based systems
dnf install tcpdump

Capturing some network traffic

The generic format for running tcpdump is:

tcpdump <options> <expression>

The options let us do things like select which interface to read traffic from or specify how much detail to display. The expression allows us to filter the raw traffic based on desired criteria. We will dig into the options and filter syntax much more below.

The following is a simple command to capture some traffic from any interface, filter it to show only ICMP (used by the ping command) and print it to the screen.

sudo tcpdump -i any icmp

Because tcpdump needs to use raw sockets to capture the network traffic, you will typically need to run it as root by using sudo or logging in as root.

Useful Options

tcpdump has a large set of flags, or arguments, which can be used to specify different options. This can be pretty overwhelming for beginners. Here we've picked out some of the most common things you might want to do and explained which options will help!

Choosing an interface

If you don't choose a specific interface, tcpdump will automatically pick the lowest numbered interface (e.g. eth0), which may or may not be the one you want. Therefore it is usually best to explicitly choose an interface to capture on.

By default, when capturing from a single interface, tcpdump should use 'promiscuous mode', which will capture all traffic that reaches the interface, even if the interface isn't the intended destination IP address. This behaviour means that you will see all traffic on the same local network that the interface is attached to.

Use the `-i' flag, followed by an interface to specify where to capture traffic from:

tcpdump -i eth0

Alternatively, we can use the longer but more descriptive syntax of --interface=:

tcpdump --interface=eth0

On most modern systems, you can also specify 'any' to capture traffic from all interfaces (this will not use promiscuous mode though):

tcpdump -i all

If you want to see which interfaces are available, you can use the -D or --list-interfaces option to print a list:

tcpdump -D
tcpdump --list interfaces

Writing to file

Sometimes you may want to record captured network traffic to a file on disk. You may wish to do this for retention/future reference or analysis in another tool such as Wireshark. It is easy to achieve this in tcpdump with the -w option followed by your chosen filename. You can use any filename and extension that you choose, but it is common to use the .pcap suffix.

tcpdump -w pings.pcap icmp

When -w is used, the packets won't be displayed in the terminal.

When capturing a lot of traffic, files can become very large. Therefore, tcpdump has an option for splitting a large capture across multiple files, using the -C option to express a limit at which to create a new file. The -C option must be used with -w and will create a series of files with an incrementing number appended at the end of the filename. The file size limit is specified in millions of bytes - for example, -C 2 would limit files to 2,000,000 bytes. When the file size limit is reached, the next packet will be written to a new file.

tcpdump -w test.pcap -C 2

If you wish to display packet output in the terminal and write to a file, you can use the -w flag with the --print option.

tcpdump --print -w pings.pcap icmp

Read from a file

Sometimes you may want to read network data into tcpdump from a file rather than capturing it live from an interface. The file may have been previously generated by tcpdump or with a network sensor or alternative application such as Wireshark. We can then apply options and filters to the traffic as required. As with writing files, you can use any extension (or no extension), and tcpdump will still read the file provided it is a valid packet capture, but the convention is to use .pcap.

The -r option is used to specify a file to read from:

tcpdump -r example.pcap

You can also read from standard input (for example, if you want to pipe the output of another program into tcpdump) by specifying - instead of giving a file name.

cat example.pcap | tcpdump -r -

If you have multiple files to read from (for example, sequential captures from a long session), you can specify a list of files to read from by using the -V option. -V should be followed by the location of a file which specifies all of the file tcpdump should read.

tcpdump -V captures.txt

Verbosity and printing packet contents with tcpdump

We get fine-grained control over what information tcpdump will display. Firstly, we can specify different 'verbosity' levels using -v, -vv and -vvv. Verbosity refers to how much detail to include: more verbose output will give you more information. Each level will print additional fields and information related to the packets - depending on what protocols you are looking at, you may not notice a significant difference between the three levels. Using a verbosity flag will also force tcpdump to do additional checks on the packet, such as verifying the IP header checksum. The example below shows the difference between standard and verbose outputs for an ICMP packet - notice the additional field information (such as TTL and flags).

$ tcpdump -n -c 1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
09:00:00.000001 IP 10.0.1.10 > 8.8.8.8: ICMP echo request, id 2, seq 11, length 64

$tcpdump -v -n -c 1 icmp
tcpdump: listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
09:00:01.000001 IP (tos 0x0, ttl 64, id 4040, offset 0, flags [DF], proto ICMP (1), length 84)
    10.0.1.10 > 8.8.8.8: ICMP echo request, id 2, seq 17, length 64

If you also want to print the content of each packet in ASCII, you can use the -A option. For example, this will show the content of HTTP requests and responses.

$ tcpdump -A -n src port 80    # some output removed for brevity
08:06:59.145538 IP 93.184.216.34.80 > 10.0.2.15.50840: Flags [P.], seq 1:1591, ack 139, win 65535, length 1590: HTTP: HTTP/1.1 200 OK
E..^.~..@..3].."
....P....j...O.P...H:..HTTP/1.1 200 OK
Age: 54528
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8

    # output removed

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    # output removed

</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>

Finally, you can also print the raw hexadecimal (hex) data of the packet using the -x and xx options. -x will print the hex data of each packet but not the link-layer header (e.g. the Ethernet header). -xx will print the hex data of each packet including the link-layer header - for example, for Ethernet traffic this will include the MAC address of the data frame.

$ tcpdump -x -n -c 1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
09:00:10.000001 IP 10.0.2.15 > 8.8.8.8: ICMP echo request, id 3, seq 1, length 64
0x0000:  4500 0054 7382 4000 4001 ab08 0a00 020f
0x0010:  0808 0808 0800 b01c 0003 0001 762f 9a60
0x0020:  0000 0000 777c 0100 0000 0000 1011 1213
0x0030:  1415 1617 1819 1a1b 1c1d 1e1f 2021 2223
0x0040:  2425 2627 2829 2a2b 2c2d 2e2f 3031 3233
0x0050:  3435 3637
1 packet captured
1 packet received by filter
0 packets dropped by kernel

tcpdump -xx -n -c 1 icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on enp0s3, link-type EN10MB (Ethernet), capture size 262144 bytes
09:00:20.000001 IP 10.0.2.15 > 8.8.8.8: ICMP echo request, id 3, seq 120, length 64
0x0000:  0600 4567 4567 0200 1234 1234 0800 4500
0x0010:  0054 b0b1 4000 4001 6dd9 0a00 020f 0808
0x0020:  0808 0800 d712 0003 0078 ed2f 9a60 0000
0x0030:  0000 cd0e 0d00 0000 0000 1011 1213 1415
0x0040:  1617 1819 1a1b 1c1d 1e1f 2021 2223 2425
0x0050:  2627 2829 2a2b 2c2d 2e2f 3031 3233 3435
0x0060:  3637
1 packet captured
1 packet received by filter
0 packets dropped by kernel

Other useful options

Read through the official documentation for all available options. Below are some other flags which you may find useful.

-c - you can limit the number of packets to capture by using -c followed by a number. For example, to stop capturing after five packets, you would use -c 5.

-e - print the link-level header for each packet. Useful if you want to see MAC addresses for Ethernet connections.

-n - by default, tcpdump will try to convert IP addresses to host addresses (e.g. instead of printing '8.8.8.8', it will show 'dns.google'). This behaviour can be helpful, but it can also be confusing or slow things down. The -n option will stop this behaviour and cause tcpdump to print plain IP addresses and port numbers instead of trying to look them up. If you have a lag/latency problem when using tcpdump, try using the -n option to speed things up.

-p or --no-promiscuous-mode - using this flag will stop tcpdump from putting an interface into promiscuous mode. Using this option will result in only capturing traffic destined for the specified interface.

tcpdump filter syntax

To select traffic that meets certain conditions, you can create filter expressions with pcap-filter syntax. tcpdump uses this filter syntax to apply Berkeley Packet Filters (BPF) to your traffic. These tcpdump expressions give you a simple, powerful way of filtering down traffic based on specific criteria.

For additional information about the syntax, consult the pcap-filter man pages.

Packet Filter Basics

A basic packet filter expression is made up of an id (such as an IP address or port number) preceded by one or more qualifiers which indicate what property that id should be applied to. The qualifiers which can be used are:

type

What is the identifier. For example, the host type indicates that the identifier is a host address (e.g. an IP address or hostname). The following types are available:

If no type is specified, host is assumed.

dir

Specify the direction of traffic that the id should be applied to. For example, only evaluate the source address (src) for a match on the given id. Possible directions include the following:

If no direction is specified, src or dst is assumed.

proto

This qualifier lets you target only a specific protocol. Protocols that you may wish to specify include:

Default qualifiers

We don't have to use all (or any) qualifiers - tcpdump will make an educated guess. If no type is specified, the default of host will be used. If no direction is specified, the default of src or dst is assumed. If no protocol is specified, all possible protocols for the given identifier will be assumed. The below examples demonstrate this.

tcpdump ip src or dst host 192.168.1.1    # qualifiers stated explicitly
tcpdump 192.168.1.1    # tcpdump will make assumptions about the qualifiers to apply

How many qualifiers you need to use will depend on precisely what traffic you are trying to isolate and how much noise there is on the network.

Check out the man pages for a complete list of qualifiers.

Combining filter expressions with and, or, not

It is possible to build up more specific filters by modifying and combining filter expressions. The following keywords are used to achieve this:

not

Can also be written as ! - select only traffic which does not match the expression which follows.

tcpdump not tcp # match only traffic which doesn't use the TCP protocol

and

Can also be written as && - select traffic which matches both the preceding expression and the following expression.

tcpdump icmp and host google.dns

or

Can also be written as || - select traffic which matches the preceding expression or the following expression.

Simplifying complex expressions

To make life easier, you can combine _id_s without restating the qualifiers where they are the same. For example, the following expressions are equivalent.

tcpdump tcp dst port 80 or tcp dst port 443

In the example below, tcpdump assumes that you also want to treat 443 as a tcp dst port.

tcpdump tcp dst port 80 or 443

You can use parentheses () to define your logic further:

tcpdump host athena and (port 80 or 443)

Filtering on protocol

It is easy to select network traffic based on protocol with tcpdump by simply specifying which protocol you are interested in. For example: ip, tcp, udp, icmp, ip6, icmp6. You may specify different layers of the protocol stack you want to filter on by first specifying the outer protocol (e.g. IP) and then using the proto type qualifier to specify the next layer (e.g. TCP).

tcpdump ip proto tcp

Filtering based on IP address

One of the most common operations is to isolate traffic based on one or more IP addresses. This can be useful for troubleshooting network problems to/from a specific host by using the host type. When filtering on IP address, it is common to use a directional qualifier too.

tcpdump src host 192.168.1.1 and dst host 192.168.1.2

We can also isolate traffic from a specific network with the net type. The network is specified by either providing dotted decimal notation for just the portion of the address representing the subnet of interest (for example, 192.168 would correspond to 192.168.0.0/16).

tcpdump net 192.168.1    # filter for all traffic from the 192.168.1.0/24 subnet

Port Filters

You can filter based on port or portrange using direction qualifiers to choose which end of the communication the filter is applied to.

tcpdump src portrange 10000-20000 and dst port 443

You can also specify which port to filter on by using a service name. For example, dst port http is equivalent to dst port 80.

Packet Length

It is possible to select only packets which are less than or greater than a certain length as follows:

tcpdump ip host 192.168.1.1 and less 100
tcpdump icmp greater 50

References

Learn more about this topic by checking out these references.


Other Lessons

Learn more by checking out these related lessons

How does IPv4 work?

lesson

View

Ping and ICMP

lesson

View

Summary of the TCP/IP Model

lesson

View