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:
- host for an individual host (e.g.
host 192.168.1.1
) - net for network (e.g.
net 192.168.0.0/24
), - port for a port number (e.g.
port 22
) - portrange for a ranges of ports (e.g.
portrange 1000-2000
)
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:
- src - source only
- dst - destination only
- src or dst - either side of the connection may match
- src and dst both source and destination should match the specified identifier
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:
- ether (Ethernet)
- wlan (Wireless Lan)
- ip (Internet Protocol v4)
- ip6 (Internet Protocol v6)
- arp (Address Resolution Protocol)
- rarp (Reverse - ARP)
- tcp (Transmission Control Protocol)
- udp (User Datagram Protocol)
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