How to Use Tcpdump: Commands, Filters and Examples (2026)

Penetration Testing
18 min read
How to Use Tcpdump: Commands, Filters and Examples (2026)
On this page
  1. What Is Tcpdump?
  2. Installing Tcpdump and the Permission Problem Nobody Warns You About
  3. How to Use Tcpdump for Your First Capture
  4. How to Read Tcpdump Output
  5. Tcpdump Filters: The Skill Worth Learning
    1. Filters That Answer a Question
  6. Writing Captures to a File and Opening Them in Wireshark
  7. Reading Payloads with -A and -X: Pulling a Flag Out of a Pcap
    1. ASCII Output with -A
    2. Hex Output with -X
    3. Watching DNS with Tcpdump
  8. Tcpdump vs Wireshark: Which One and When
  9. Legal and Ethical Considerations
  10. Frequently Asked Questions
  11. Your Next Steps

You are on a box over SSH. There is no desktop, no Wireshark, and something on the network is talking to an address nobody can explain. Learning how to use tcpdump is how you answer that question with the one tool that is already installed, in a terminal that is 80 columns wide.

Tcpdump prints packets. That is the whole product. It has been doing it since 1988, it is on nearly every Linux and BSD system you will ever log into, and it is still the fastest way to find out what a machine is actually sending. It is a core skill for penetration testing, for incident response, and for the forensics half of any CTF. Open the Packet Pursuit lab in another tab as you read: it is a capture file with a flag split across three protocols, and everything below applies to it directly.

TL;DR: Tcpdump is a command line packet capture tool built on libpcap. The command you will use most is sudo tcpdump -i eth0 -n 'tcp port 80': pick an interface with -i, skip name resolution with -n, and put a BPF filter in single quotes at the end. Add -c 100 to stop after 100 packets, or -w capture.pcap to save them for Wireshark. The real skill is reading one output line and writing a filter that removes everything you do not care about.

What Is Tcpdump?

Tcpdump is a command line tool that captures packets from a network interface and prints a one line summary of each one. It can also write the raw packets to a .pcap file, the same format Wireshark reads, so a capture taken on a server with no GUI opens perfectly on your laptop.

Van Jacobson, Sally Floyd, Vern Paxson and Steven McCanne wrote it in 1988 at the Lawrence Berkeley Laboratory. It sits on top of libpcap, the capture library behind Wireshark, Nmap, Snort and Suricata, and "the pcap format" is simply the file libpcap writes.

The current stable release on tcpdump.org is 4.99.7 (September 2026), with libpcap 1.10.7. Distributions lag a little: Ubuntu 24.04 LTS ships 4.99.4, and for everything in this article the 4.99.x releases behave identically.

Tcpdump does not decode application protocols the way Wireshark does. It understands headers beautifully: Ethernet, IP, TCP, UDP, ICMP, DNS, ARP. Above that it mostly hands you bytes. There is no "Follow HTTP Stream" and no protocol tree. What you get instead is speed, a filter language that runs in the kernel, and a binary that is already on the target.

Installing Tcpdump and the Permission Problem Nobody Warns You About

On Kali it is installed. On Debian or Ubuntu it is one command:

sudo apt update
sudo apt install tcpdump

Check what you got:

tcpdump --version
tcpdump version 4.99.4
libpcap version 1.10.4 (with TPACKET_V3)
OpenSSL 3.0.13 30 Jan 2024

Capturing packets needs root, or the raw socket capabilities that normally come with it, so every capture command below starts with sudo. If you would rather not, grant the binary the two capabilities it actually needs and run it as yourself:

sudo setcap cap_net_raw,cap_net_admin+eip $(which tcpdump)

Now the part that trips up almost everyone on Debian and Ubuntu: those builds drop privileges to an unprivileged tcpdump account. The official man page documents this under -Z: the switch happens "after opening the capture device or input savefile, but before opening any savefiles for output". So sudo tcpdump -w /root/capture.pcap fails with a permission error even though you are root, and when writing does work, the file is not yours:

-rw-r--r-- 1 tcpdump tcpdump 3115 Sep 14 07:18 cap.pcap

In practice: write captures somewhere the tcpdump user can reach, such as /tmp, then sudo chown $USER capture.pcap. Or tell tcpdump to stay root with -Z root. Two minutes of confusion the first time, never again after that.

Before capturing anything, find out what you can capture on:

tcpdump -D
1.eth0 [Up, Running, Connected]
2.any (Pseudo-device that captures on all interfaces) [Up, Running]
3.lo [Up, Running, Loopback]

eth0 is the real network, lo is loopback where you watch a service talk to a database on the same host, and any captures on everything at once. Start with any when you do not yet know where the traffic is.

How to Use Tcpdump for Your First Capture

Every tcpdump command has the same shape: options, then a filter in single quotes.

sudo tcpdump -i lo -n 'tcp port 8000'

That prints a banner and then sits there until you press Ctrl+C:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
^C
25 packets captured
50 packets received by filter
0 packets dropped by kernel

Three counters at the end, and the third is the one to watch. "Dropped by kernel" means packets arrived faster than tcpdump could handle them and the kernel threw them away. Anything above zero means your capture has holes, and the fix is a tighter filter or -w to a file instead of printing to the terminal. (On loopback, "received by filter" counts every packet twice, once going out and once coming in, so 50 against 25 is normal.)

Four options carry most of the weight:

  • -i eth0 chooses the interface. Use -i any when you are not sure.
  • -n stops tcpdump turning addresses and port numbers into names. Always use it. Without it, every new address triggers a DNS lookup that slows the output, pollutes your capture and tells the DNS server what you are looking at. Older guides say -nn to keep ports numeric too; on current versions a single -n already does both.
  • -c 100 exits after 100 packets. sudo tcpdump -i eth0 -n -c 100 captures 100 packets from eth0, prints a summary of each, and stops on its own.
  • -w capture.pcap writes raw packets to a file instead of printing them.

Three more earn a place in muscle memory:

  • -v, -vv, -vvv decode more of each packet: TTL, IP ID, total length and checksum checks at -v, fully decoded SMB and extra NFS fields at -vv.
  • -e adds the link-layer header, so you see MAC addresses. Essential when chasing ARP problems.
  • -tttt prints a full date before the time, which you want in anything that goes into a report.

There is no -s0 in those lists on purpose. Old tutorials add it because tcpdump once kept only the first 68 bytes of each packet. Full packets have been the default since version 4.1 (2010), and the banner above shows today's 262144 byte snapshot length.

💻
Practice this now: Packet Pursuit - a capture file with a flag hidden across DNS, ICMP and HTTP traffic. It is the exact job tcpdump filters were built for, and it runs in the browser with nothing to install.

How to Read Tcpdump Output

This is the skill everything else rests on. Here is one real line from the capture above:

07:18:27.260675 IP 127.0.0.1.56730 > 127.0.0.1.8000: Flags [S], seq 1533482769, win 65495, options [mss 65495,sackOK,TS val 12321087 ecr 0,nop,wscale 10], length 0

Left to right:

  • 07:18:27.260675 is the timestamp, down to microseconds. Timing is often the finding: a request every 60.0 seconds is a beacon, not a user.
  • IP is the protocol of the outer layer. You will also see IP6 and ARP.
  • 127.0.0.1.56730 > 127.0.0.1.8000 is source then destination, and the number after the final dot is the port. Tcpdump does not use a colon for ports, which catches everyone once.
  • Flags [S] is the TCP flags field, and it is the most useful thing on the line.
  • length 0 is the payload size, not the packet size. A handshake packet carries no data.

The flag notation is compact and worth memorising:

  • [S] SYN, somebody is opening a connection
  • [S.] SYN-ACK, and the dot always means ACK. Something is listening.
  • [.] a plain ACK, usually an acknowledgement with nothing else to say
  • [P.] PSH-ACK, which is the one carrying actual data
  • [F.] FIN-ACK, a polite close
  • [R] or [R.] RST, a refusal. Nothing is listening on that port, or a firewall rejected it.

Now read three consecutive lines from the same capture (TCP options trimmed to fit) and the handshake appears on its own:

07:18:27.260675 IP 127.0.0.1.56730 > 127.0.0.1.8000: Flags [S], seq 1533482769, win 65495, length 0
07:18:27.261001 IP 127.0.0.1.8000 > 127.0.0.1.56730: Flags [S.], seq 62299410, ack 1533482770, win 65483, length 0
07:18:27.261018 IP 127.0.0.1.56730 > 127.0.0.1.8000: Flags [.], ack 1, win 64, length 0

SYN, SYN-ACK, ACK. Once you spot that pattern at a glance, a port scan, a failed connection and a working service all read straight off the terminal. A scan looks like hundreds of [S] packets with [R.] coming back from every closed port, which is precisely how an Nmap scan looks from the receiving end.

Notice the sequence numbers too. The first packet in each direction shows the real value, and from then on tcpdump prints numbers relative to it, which is why the third line says ack 1. Pass -S to keep the absolute values.

Tcpdump Filters: The Skill Worth Learning

An unfiltered capture on a real interface is unreadable within two seconds. Filters are not an optimisation here, they are the tool.

Tcpdump uses BPF, the Berkeley Packet Filter language, documented in the pcap-filter man page. The filter is compiled and runs in the kernel, so packets you did not ask for are discarded before they are ever copied to tcpdump. That is why a good filter also fixes dropped packets.

A BPF expression is built from three kinds of word:

  • Type: host, net, port, portrange
  • Direction: src, dst, or neither, which matches either direction
  • Protocol: tcp, udp, icmp, arp, ip, ip6

Combine them with and, or and not, and always wrap the whole thing in single quotes so your shell leaves the parentheses alone.

sudo tcpdump -i any -n 'host 192.0.2.10'
sudo tcpdump -i any -n 'dst port 443'
sudo tcpdump -i any -n 'net 10.0.0.0/8'
sudo tcpdump -i any -n 'portrange 8000-8100'
sudo tcpdump -i any -n 'src 192.0.2.10 and not port 22'

That last one is the filter you will type most often in real life. Over SSH, an unfiltered capture shows you your own SSH session, which generates more packets, which print more lines. Excluding port 22 is the difference between a readable capture and a runaway terminal.

One trap catches experienced people too: and and or have equal precedence and are read left to right. 'host 192.0.2.10 and port 80 or port 443' means "(that host on port 80) or any port 443 traffic from anyone", and on a busy interface the second half drowns the first. Write what you mean:

sudo tcpdump -i any -n 'host 192.0.2.10 and (port 80 or port 443)'

Filters That Answer a Question

  • 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' shows connection attempts only, with no replies and no data. This is how you watch a port scan in progress, or confirm that a host really is trying to reach a service that never answers.
  • 'udp port 53' is DNS, and DNS is where a surprising amount of trouble hides.
  • 'port 80 or port 8080 or port 8000' catches cleartext HTTP on the ports people actually use.
  • 'arp' shows the local network asking who owns which address. Add -e and ARP spoofing becomes visible as one IP claimed by two MAC addresses.

The confusion worth clearing up: BPF capture filters and Wireshark display filters are two different languages that look similar and are not interchangeable. host 192.0.2.10 is BPF. ip.addr == 192.0.2.10 is a Wireshark display filter. Typing the Wireshark version into tcpdump gives you a syntax error, and typing the tcpdump version into Wireshark's display filter bar turns it red. Wireshark accepts BPF only in its capture options. Our Wireshark cheat sheet lists both syntaxes side by side.

Writing Captures to a File and Opening Them in Wireshark

Printing to the terminal is for watching. Anything you intend to analyse should go to a file.

sudo tcpdump -i eth0 -n -w /tmp/capture.pcap 'port 80 or port 443'

Nothing prints while that runs, which always feels broken the first time; add -v for a running packet count. The 25 packet capture in this article came out at 3,115 bytes, but a busy uplink produces gigabytes an hour, and the fix is rotation:

sudo tcpdump -i eth0 -n -w /tmp/cap.pcap -C 100 -W 10

-C 100 starts a new file every 100 MB (millions of bytes), and -W 10 keeps ten of them before overwriting the oldest: a capped 1 GB ring buffer you can leave running for days. For one file per hour, use -G 3600 and put a date format in the file name, otherwise every rotation overwrites the previous file:

sudo tcpdump -i eth0 -n -G 3600 -w '/tmp/cap-%Y%m%d-%H%M.pcap'

Read a saved file back with -r, which needs no root at all. Filters work on read as well as on capture, and this is the habit that makes big captures manageable: capture broadly once, then filter the file as many times as you need.

tcpdump -r capture.pcap -n 'host 192.0.2.10 and port 443'

Now the one command that makes tcpdump and Wireshark into a single tool. If the traffic you need is on a remote server with no GUI, do not capture, copy and open. Pipe it:

ssh [email protected] 'sudo tcpdump -i eth0 -U -w - not port 22' | wireshark -k -i -

-w - writes the capture to standard output, -U flushes each packet immediately, and wireshark -k -i - starts capturing from standard input straight away. You get Wireshark's full protocol decoding, live, on packets from a machine that has never heard of a window manager. Two details matter: not port 22 keeps your own SSH traffic out of the capture, and the remote sudo must not prompt for a password, because there is no terminal to type it into.

Reading Payloads with -A and -X: Pulling a Flag Out of a Pcap

Forensics challenges hand you a pcap and a question. Two more flags and tcpdump gets you there faster than a GUI.

ASCII Output with -A

-A prints each packet's payload as ASCII. On cleartext protocols it is close to reading the conversation:

tcpdump -r capture.pcap -nA 'tcp port 8000'
07:18:27.261121 IP 127.0.0.1.56730 > 127.0.0.1.8000: Flags [P.], seq 1:88, ack 1, win 64, length 87
E....+@.@..?...........@[g.........@.......
[email protected] /index.html HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/8.5.0
Accept: */*

The line of noise before the request is the IP and TCP header rendered as ASCII, meaningless by design. Everything after it is the HTTP request as it went over the wire. Keep going through the same capture and a POST appears:

POST /login HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: curl/8.5.0
Accept: */*
Content-Length: 26
Content-Type: application/x-www-form-urlencoded

user=dana&password=hunter2

There it is, in the clear, because the form posted over HTTP. This is the most common finding in beginner forensics challenges, and it still turns up on real internal networks in 2026, usually on a management interface nobody has touched in years.

Hex Output with -X

-X prints hex alongside ASCII, which is what you want when the payload is not text (-XX includes the link-layer header as well):

tcpdump -r capture.pcap -nX -c 1
07:18:27.260675 IP 127.0.0.1.56730 > 127.0.0.1.8000: Flags [S], seq 1533482769, win 65495, options [mss 65495,sackOK,TS val 12321087 ecr 0,nop,wscale 10], length 0
	0x0000:  4500 003c a829 4000 4006 9490 7f00 0001  E..<.)@.@.......
	0x0010:  7f00 0001 dd9a 1f40 5b67 1711 0000 0000  .......@[g......
	0x0020:  a002 ffd7 fe30 0000 0204 ffd7 0402 080a  .....0..........
	0x0030:  00bc 013f 0000 0000 0103 030a            ...?........

That is where file headers hide. 4500 at offset zero is the start of an IPv4 header, and 1f40 at 0x0016 is port 8000. Further into a payload, 504b 0304 is a ZIP file and 8950 4e47 is a PNG. Spotting a signature like that is how you know there is a file to carve out of the capture.

The workflow in a challenge is three steps. Get a shape for the traffic with tcpdump -r capture.pcap -nq, which prints one short line per packet. Filter down to the protocol the challenge is about. Then dump payloads with -A and pipe the lot through grep:

tcpdump -r capture.pcap -nA | grep -i -E 'flag|password|user='

Watching DNS with Tcpdump

DNS deserves its own look, because it carries data out of networks that block everything else. A normal query is unremarkable:

sudo tcpdump -i any -n 'udp port 53'
07:20:43.478932 eth0  Out IP 192.0.2.2.43351 > 8.8.8.8.53: 24085+ AAAA? hackerdna.com. (31)
07:20:43.494090 eth0  In  IP 8.8.8.8.53 > 192.0.2.2.43351: 24085 3/0/0 AAAA 2606:4700:20::681a:f29, AAAA 2606:4700:20::681a:e29, AAAA 2606:4700:20::ac43:4840 (115)

The query type, name and answers appear without extra flags (3/0/0 means three answers, no authority or additional records), and -i any adds the interface and direction. In an investigation, watch the shape of the names: long random looking subdomains, hundreds of unique names under one parent domain, queries that never repeat. That is data being encoded into hostnames, and the DNS Tunneling Detective lab gives you a capture with it running.

Tcpdump vs Wireshark: Which One and When

This is not a rivalry. They share libpcap and read the same file format, and on most days the right answer is both.

Capability Tcpdump Wireshark
Runs over SSH on a headless server Yes No
Already installed on the target Usually Rarely
Application protocol decoding Headers only Hundreds of protocols
Reassembling a whole TCP conversation No Follow TCP Stream
Extracting files from a capture No Export Objects
Long unattended captures Ring buffer with -C and -W Possible, heavier
Scriptable in a pipeline Yes Via tshark

Capture with tcpdump, because it is on the box, it is light, and it will still be running tomorrow. Analyse in Wireshark, because reassembling streams and exporting files by hand is work nobody should be doing. Our guide to Wireshark covers the analysis half in detail.

The exception is a real one: when you know what you are looking for, tcpdump plus grep beats loading a 2 GB pcap into a GUI every time. "Did this host ever talk to that address" is a one line question. Do not open Wireshark to answer it.

Critical reminder: Always get explicit written authorization before capturing traffic on any network. Packet capture is interception: in the United States it falls under the Wiretap Act, in the United Kingdom under the Investigatory Powers Act, and across the EU under national implementations of the ePrivacy Directive. You do not have to change anything for a capture to be an offence. Reading other people's traffic is the offence.

  • Capture only on networks you own or that are named in a signed scope document
  • Coffee shop and hotel Wi-Fi is somebody else's network carrying somebody else's private traffic. It is not a practice environment.
  • Filter at capture time to what the scope covers. Collecting everything and promising to ignore most of it is not a defence.
  • A capture file holds credentials, cookies and private messages. Encrypt it at rest and delete it when the engagement ends.
  • On a shared or corporate network, tell the people who run it before you start. A promiscuous interface shows up in monitoring and looks identical to an attack.

Lab captures and CTF challenges exist precisely so you can build these reflexes without any of that hanging over you.

Frequently Asked Questions

What is tcpdump used for?

Capturing and inspecting network traffic from the command line. Administrators use it to prove which side of a connection is failing, incident responders to see what a compromised host is talking to, penetration testers to find cleartext credentials and map a network, and CTF players to read the pcap files that forensics challenges hand them.

How do I capture a set number of packets with tcpdump?

Use -c. sudo tcpdump -i eth0 -n -c 100 captures 100 packets on eth0, prints a one line summary of each, and exits on its own. Add -w capture.pcap to save exactly those 100 packets to a file instead.

How do I write a tcpdump capture to a file?

Use -w: sudo tcpdump -i eth0 -n -w /tmp/capture.pcap. Nothing prints while it runs, which is normal. Read it back with tcpdump -r or open it in Wireshark. On Debian and Ubuntu, write to /tmp or another directory the unprivileged tcpdump user can reach.

Can tcpdump see UDP traffic?

Yes. Tcpdump captures every protocol the interface sees, including UDP, ICMP and ARP. The name is a historical accident from 1988. Filter with udp, or narrow it: sudo tcpdump -i any -n 'udp port 53' shows DNS, and tcpdump decodes the queries and answers for you.

Does tcpdump need root?

Capturing does, because it needs raw socket access; reading a saved file with -r does not. To capture without sudo, run sudo setcap cap_net_raw,cap_net_admin+eip $(which tcpdump) once.

Can tcpdump read HTTPS traffic?

No. TLS encrypts the payload, so -A shows random bytes. You still get the metadata: addresses, ports, timing, volume, and usually the requested hostname in the TLS handshake (unless Encrypted Client Hello hides it). That answers "who talked to what and when", never "what did they say".

Your Next Steps

Knowing how to use tcpdump takes an afternoon for the flags and a few real captures for the reading. There is no shortcut past doing them.

So go and do one. Work through the Packet Pursuit lab and find a flag split across three protocols on purpose, then take the network forensics chapter of our DFIR course, which follows the same captures further into beaconing, DNS tunneling and TLS fingerprinting. Everything runs in the browser, and you can start on HackerDNA's free tier with no credit card. Then run tcpdump on your own machine for five minutes and watch what your laptop talks to when you think it is idle. It is usually a surprise.

HackerDNA Team

HackerDNA Team

Written by the HackerDNA team - cybersecurity professionals building hands-on hacking labs and educational content to help you develop real-world security skills.

Meet the Team

Ready to put this into practice?

Stop reading, start hacking. Real machines, in your browser, free.

Start Hacking Free
30,000+ Hackers Real labs Free
Start Hacking Free or solve today's hack, no account needed