tcpdump Basics: Capturing and Reading Packets
What You'll Learn
- The fastest way to start capturing packets with
tcpdump - How to narrow down to the traffic you care about with BPF filters
- The workflow for saving a pcap and reading it in Wireshark
- How to diagnose "can't connect" and "slow response" at the packet level
Quick Summary
- Start with
sudo tcpdump -i any -nnto watch live traffic - When it's noisy, narrow it down with
host/portfilters - For later analysis, save with
-w cap.pcapand open it in Wireshark - Always add
-nn(so DNS lookups never stall the output)
Prerequisites
- OS: Ubuntu / typical Linux
- Packet capture needs root privileges (
CAP_NET_RAW), so commands assumesudo - If it's not installed:
sudo apt install tcpdump
What Is tcpdump?
Conclusion: tcpdump is a command-line packet capture tool. It grabs and prints the raw packets crossing a NIC, so you can see exactly what is (or isn't) on the wire.
tcpdump captures the packets passing through a network interface (NIC) and prints them as they are. When a web response never comes back or a TCP connection won't establish, it lets you reason from facts: did the packet reach the server, and did a reply come back?
It shares its capture engine (libpcap / BPF) with the GUI tool Wireshark - tcpdump is essentially the CLI counterpart. Its strength is that you can run it instantly on a server over SSH.
Packet capture observes the contents of traffic (sometimes including credentials). Run it only on systems you own or are authorized to inspect.
How Do You Start a Capture Fast?
Conclusion:
sudo tcpdump -i any -nnis your starting point. Master just three things - interface-i, no name resolution-nn, and a count limit-c- and you can already work.
Watch live traffic first
$ sudo tcpdump -i any -nn
-i any: capture on all interfaces (use-i eth0for a specific one)-nn: resolve neither hostnames nor port names (no waiting on DNS, and numbers read faster)
List available interfaces
When you're not sure which interface to pick, list them.
$ tcpdump -D
1.eth0 [Up, Running, Connected] 2.any (Pseudo-device that captures on all interfaces) [Up, Running] 3.lo [Up, Running, Loopback]
Stop after a fixed count
tcpdump keeps running until you stop it. -c caps the number of packets, which is easier to handle.
$ sudo tcpdump -i any -nn -c 20
Press Ctrl + C to stop manually. On exit it prints "received / dropped by kernel" stats - a high dropped count means packets were missed.
How Do You Read a Single Line?
Conclusion: Each line reads "time source > destination flags/seq/length". The direction of
>plus the TCP flags (S/F/P/R/.) tell you the flow and state.
A typical TCP line looks like this.
10:11:12.345678 IP 192.168.1.10.54322 > 93.184.216.34.443: Flags [S], seq 123456, win 64240, length 0
| Element | Meaning |
|---|---|
10:11:12.345678 |
Timestamp |
192.168.1.10.54322 |
Source IP and port (the trailing part) |
> |
Direction (left to right) |
93.184.216.34.443 |
Destination IP and port (443 = HTTPS) |
Flags [S] |
TCP flags (see below) |
length 0 |
Payload length |
Reading TCP flags
| Notation | Flag | Meaning |
|---|---|---|
S |
SYN | Connection request |
S. |
SYN/ACK | Reply to a connection request |
. |
ACK | Acknowledgment only |
P |
PSH | Push data |
F |
FIN | Close the connection |
R |
RST | Forcibly reset the connection |
If the three-way handshake succeeds you'll see [S] then [S.] then [.]. If you send [S] and get back [R] (RST), or nothing at all, the port is likely closed or the path is being blocked.
How Do You Capture Only What You Want? (BPF Filters)
Conclusion: Append a BPF expression to narrow the capture.
host/port/src/dstcombined withand/or/notcovers almost everything.
The condition expression at the end of the tcpdump arguments is a BPF (Berkeley Packet Filter). A handful of keywords is enough for real work.
# Only traffic with a specific host $ sudo tcpdump -i any -nn host 93.184.216.34 # Only a specific port (HTTPS) $ sudo tcpdump -i any -nn port 443 # Limit by source / destination $ sudo tcpdump -i any -nn src 192.168.1.10 $ sudo tcpdump -i any -nn dst port 53 # Limit by protocol $ sudo tcpdump -i any -nn udp port 53
Combine conditions
# host A and port 443 $ sudo tcpdump -i any -nn host 192.168.1.10 and port 443 # Everything except port 22 (SSH) $ sudo tcpdump -i any -nn not port 22 # DNS or HTTPS $ sudo tcpdump -i any -nn 'port 53 or port 443'
When an expression uses and / or / not or parentheses, wrap the whole expression in single quotes to stop the shell from interpreting it (e.g. 'tcp port 80 and host 10.0.0.1').
Common keywords: host / net 192.168.1.0/24 / port / portrange 8000-8100 / src / dst / tcp / udp / icmp / arp.
How Do You See the Payload?
Conclusion:
-Aprints ASCII and-Xprints hex + ASCII. Useful for inspecting plaintext HTTP headers or DNS queries. Tune verbosity with-v/-vv.
Use these when you need more than headers - the actual contents of a packet.
# Print payload as ASCII (good for HTTP headers, etc.) $ sudo tcpdump -i any -nn -A port 80 # Hex + ASCII (good for binary analysis) $ sudo tcpdump -i any -nn -X port 80 # Increase verbosity (TTL, options, etc.) $ sudo tcpdump -i any -nn -vv host 192.168.1.10
HTTPS (443) traffic is encrypted, so -A / -X won't reveal the contents (though the TLS handshake and part of the SNI are visible). Plaintext is only readable for unencrypted traffic such as HTTP and DNS.
Older guides say you need -s 0 to capture full packets, but modern tcpdump already uses a large default snap length (262144 bytes), so you normally don't need it.
How Do You Save a Capture for Later Analysis?
Conclusion:
-w file.pcapwrites a binary capture and-r file.pcapreads it back. A saved pcap opens directly in Wireshark, so you can capture on the server and analyze on your laptop.
Write and read back
# Save in pcap format (writes to file instead of the screen) $ sudo tcpdump -i any -nn -w capture.pcap # Read a saved file (no sudo needed just to read) $ tcpdump -nn -r capture.pcap # You can also apply a filter while reading $ tcpdump -nn -r capture.pcap port 443
Capture on the server, analyze on your laptop
- On the server:
sudo tcpdump -i any -nn -w /tmp/cap.pcap port 443 -c 1000 - Transfer it locally (
scp user@server:/tmp/cap.pcap .) - Open
cap.pcapin Wireshark
Wireshark's filters and stream-following make deep analysis fast, so this split is the quickest route for anything complicated.
Rotate files so they don't pile up
A long capture can fill the disk. You can rotate by size or count.
# Split every ~100MB, keeping at most 10 files in rotation $ sudo tcpdump -i any -nn -w cap_%Y%m%d_%H%M%S.pcap -C 100 -W 10
-C 100: roll over at roughly 100MB per file-W 10: cap on the number of retained files (older ones get overwritten)
A Real Case: Can't Connect
Conclusion: Watching whether a SYN gets a reply (or an RST) settles reachability and port state in one shot.
Checking why you can't reach a host on port 443.
$ sudo tcpdump -i any -nn host 93.184.216.34 and port 443
How to read it:
- Send
[S], get back[S.]-> reachable and the port is open (the issue is at the application layer) - Send
[S], get back[R](RST) -> it reaches the host but the port is closed - Send
[S]but get nothing back -> something on the path (firewall, routing) is dropping it - Your own
[S]never even appears -> suspect local routing, name resolution, or the app itself
Pairing this with ping / traceroute reachability checks makes diagnosis faster. See the related articles for details.
Handy Options at a Glance
Conclusion: Master these seven -
-i/-nn/-c/-w/-r/-A/-v- and you've covered everyday troubleshooting.
| Option | Role |
|---|---|
-i IF |
Interface to capture on (any is allowed) |
-nn |
Don't resolve hostnames or port names |
-c N |
Stop after N packets |
-w FILE |
Write in pcap format |
-r FILE |
Read a pcap file |
-A |
Print payload as ASCII |
-X |
Print hex + ASCII |
-v/-vv |
Increase verbosity |
-e |
Also print the link layer (MAC addresses) |
-D |
List available interfaces |
Copy-paste templates
# Watch first sudo tcpdump -i any -nn -c 50 # Narrow it down sudo tcpdump -i any -nn host 192.168.1.10 and port 443 # Save and analyze later sudo tcpdump -i any -nn -w /tmp/cap.pcap port 443 -c 1000 tcpdump -nn -r /tmp/cap.pcap