What is tcpdump?
tcpdump is a tool that is used for TCP/IP packet analysis. It was first released in 1988 and has since become a very powerful and commonly used traffic analyzer on Linux, as well as many other operating systems.
tcpdump allows you to sniff all traffic that goes in and out of all interfaces. More importantly, it has the ability to filter the traffic by interface, host, destination or source host, type of traffic, and many other criteria. During troubleshooting, this helps isolate only the packets that are relevant to you to avoid being overwhelmed by a deluge of bits and bytes.
In this post, I will present a list of very common tcpdump options to help you get started. This will give you a good taste of what kind of help you can get out of it, but it’s up to you to dig further down, to the nitty gritty details.
In most cases, in order to use tcpdump you have to be a root user or run the commands with the “sudo” keyword. This is because the packet capturing mechanism requires elevated privileges. So, if you run a tcpdump command and you don’t get any output, you may need to run it as a super user. However, tcpdump will actually notify you about the need for elevated privileges.
Traffic on all interfaces
This command will give you all traffic that goes in and out of all interfaces:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:59:04.418446 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 3758317981:3758318085, ack 507133464, win 627, length 104
20:59:04.419036 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 104:144, ack 1, win 627, length 40
20:59:04.419501 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 144:248, ack 1, win 627, length 104
20:59:04.419945 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 248:288, ack 1, win 627, length 40
20:59:04.421950 IP 172.31.0.14.38215 > google-public-dns-a.google.com.domain: 39598+ PTR? 22.214.171.124.in-addr.arpa. (42)
20:59:04.433174 IP google-public-dns-a.google.com.domain > 172.31.0.14.38215: 39598 NXDomain 0/0/0 (42)
20:59:04.433749 IP 172.31.0.14.52244 > google-public-dns-a.google.com.domain: 46628+ PTR? 126.96.36.199.in-addr.arpa. (44)
20:59:04.449237 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 496:632, ack 1, win 627, length 136
20:59:04.450053 IP 172.31.0.14.ssh > 172.30.10.202.50803: Flags [P.], seq 672:808, ack 1, win 627, length 136
20:59:04.451417 IP 172.31.0.14.37553 > google-public-dns-a.google.com.domain: 49199+ PTR? 188.8.131.52.in-addr.arpa. (38)
10 packets captured
16 packets received by filter
5 packets dropped by kernel
The screen will keep scrolling with packet information until you hit Ctrl+C. Alternatively, you can use the option ‘-c’ to print a specific number of packets (e.g. tcpdump -c 10).
Let’s break down the first packet shown above in order to understand what each field represents:
- 20:59:04.418446: timestamp of the packet
- 172.31.0.14.ssh – the source IP address and port (ssh means port 22)
- 172.30.10.202.50803 – the destination IP address and port
- Flags [P.] – any TCP flags; a period ‘.‘ indicates an ACK
- seq 3758317981:3758318085 – the TCP packet’s starting and ending sequence numbers
- ack 507133464 – the TCP packet’s acknowledgement number
- win 627– the source host’s TCP window
- length 104 – the TCP packet length (in Bytes) not including the headers.
Let’s see how we can use some filters to narrow down the traffic we want to inspect.
tcpdump -i eth0
It shows all traffic that goes in and out of interface “eth0.”
tcpdump host 184.108.40.206
tcpdump src host 220.127.116.11
tcpdump dst host 18.104.22.168
It shows all traffic related to host 22.214.171.124, all traffic that comes from 126.96.36.199 and all traffic that goes to 188.8.131.52.
tcpdump port 22
tcpdump dst port 22
tcpdump src port 22
tcpdump portrange 22-30
It shows all traffic related to port 22, all traffic that has as destination the port 22, and as source the port 22, and all traffic related to ports 22-30.
Human readable format
It shows all packets in ascii format. So, you can read the actual payload of the packets when possible.
As an example, let’s see how unencrypted HTTP and encrypted HTTPS traffic really looks like at the packet level with the help of tcpdump. Here are the steps on how to do this:
- Login to a Linux host with two different sessions
- On one session run the command “tcpdump port 80 -A”
- On the other session run the command “curl google.com”
You will see that part of the output is as follows:
#.-*#..HHTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Date: Tue, 11 Dec 2018 05:27:07 GMT
Expires: Thu, 10 Jan 2019 05:27:07 GMT
Cache-Control: public, max-age=2592000
X-XSS-Protection: 1; mode=block
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
The document has moved
As you can see, the raw output of the unencrypted google.com page can be clearly displayed. Consequently, the content of any unencrypted communication is susceptible to eavesdropping.
Let’s see how the encrypted communication looks like. Let’s do the following:
- Login to a Linux host with two different sessions
- On one session run the command “tcpdump port 443 -A”
- On the other session run the command “curl https://google.com”
The output is filled with packets that look like this:
00:30:25.155966 IP 172.31.0.14.37186 > lax17s04-in-f46.1e100.net.https: Flags [P.], seq 644:747, ack 3811, win 296, options [nop,nop,TS val 589176986 ecr 5641080], length $
#. ..V.x....bg.~.....M...W.,.^+..<....=...m.. .....;............x}..#..c%D*O.P.:..Osc P...\.3.M...1.N......M...
This is the ineligible encrypted content of the HTTPS communication.
Inspecting packets is usually a last resort when it comes to troubleshooting because it’s a manual and cumbersome process. Sometimes though, when everything else fails, you need to get to that level of detail to figure out the problem on your network or host. tcpdump gives you the naked truth, but you have to be patient and diligent to pursue it.