Capture network traffic with tcpdump

A cat with a paw on a faucet dripping
water

After a previous post about how to generate random traffic with netcat, let's have a look at how to watch traffic flowing through our network interfaces. For this I'll be using tcpdump, a command-line utility allowing you to literally dump network traffic, mainly on the terminal output. This post does not aim at replacing the man page, but I hope to give simple and easy to remember commands for when you don't have time to explore the official documentation.

Installation

If tcpdump is usually installed by default on most Unix systems. If you can't find it on your system and need to install it, chances are your package manager provides one simply called "tcpdump". Features shown in this post are pretty basic so you shouldn't worry about which version you're running.

Basic commands and network interface selection

The simplest command is to simply run :

tcpdump

You will mostly get a message like You don't have permission to capture on that device. It's perfectly normal. For the vast majority of its uses, tcpdump need super-user access, so run it as root or with sudo.

Once ran with the appropriate rights, you'll be seeing all the network traffic entering and exiting your computer, from one of the network interfaces. If you have multiple network interfaces, it will show you traffic only from one of them.

Selecting the network interface can be done with the argument -i <interface>, so if you want to get all traffic from interface virbr5, this is simply a matter of :

tcpdump -i virbr5

You can also capture packets from all interfaces by using the word any instead of a network interface.

You can quit tcpdump with a simple Ctrl+C.

tweaking and recording the output

By default, tcpdump will resolve IP adresses to hostnames and replace the port number with its service name coming from /etc/services. You may want to disable this behavior by using the -n argument. Let's add it to our previous example :

tcpdump -n -i virbr5

Another useful change of tcpdump's output is to make it more verbose. There are 4 verbosity levels :

  • the default one, no extra argument needed ;
  • slightly verbose, with argument -v ;
  • more verbose, with argument -vv ;
  • and really verbose, with argument -vvv.

To give an idea of what's displayed, here are two output examples, the one from the default verbosity on a ping, and then with -v :

21:33:15.200556 IP 192.168.7.1 > 192.168.7.60: ICMP echo request, id 3, seq 3, length 64

Now, let's add -v :

21:35:39.295943 IP (tos 0x0, ttl 64, id 18475, offset 0, flags [DF], proto ICMP (1), length 84)
    192.168.7.1 > 192.168.7.60: ICMP echo request, id 4, seq 1, length 64

Showing stuff on screen is nice, but what if you want to save a capture for later analysis and read it later ? tcpdump is able to do both.

To write your capture to a file named example.pcap :

tcpdump -n -i eth0 -w example.pcap

There is only one little hiccup with this command : tcpdump will not show the network traffic on the terminal. You can have a look using the read command below, but tcpdump will print what's on the file and then quit. To put it differently, tcpdump read abilities are more like cat than tail. And the read command for example.pcap ? Here it is :

tcpdump -r example.pcap

What's great with the file writing feature is that you can open this file with Wireshark.

Filters !

One of the most powerful features of tcpdump is the ability to filter out some traffic so you can have a look at what you are really looking for. Let's say you have a webserver that receives no trafic. But that webserver only has one network interface (eth0) and is also running an FTP and SSH server. If you try to look for HTTP traffic without filters and some people are uploading files to the server, you're either gonna need jedi reflexes, or a lot of disk space (assuming you're capturing to a file).

Following our webserver example, let's say we need to capture traffic coming from and to 192.168.1.1 :

tcpdump -n -i eth0 host 192.168.1.1

We can be more precise, and add source or destination with the src and dst keywords. The example below shows it with source filter :

tcpdump -n -i eth0 src host 192.168.1.1

Again with our webserver example, we can display only port 80, in order to avoid packets coming from other services (ssh, rdp or mail) :

tcpdump -n -i eth0 port 80

Of course, the source and destination filters can be used on ports, but the exact command is left as an exercise for the reader.

Another really powerful feature is logical operators. We can use things like and, or, not in order to have more precise filters. Again with our web server example, let's say we want to capture not only http packets but also https packets. It would give :

tcpdump -n -i eth0 port 80 or port 443

I'm only scratching the surface here. More examples can be found in the tcpdump man page. There is also a dedicated page about pcap-filter, with many more keywords. As for the third party documentations, I'll recommend Julia Evans must read "Let's learn tcpdump!", and TCPDump: Set Up and Getting Started from Hak5's Shannon Morse.

I hope you enjoyed this post ! If you did, please share it on your favorite social networks :-)

Photo by Kazuky Akayashi on Unsplash.