Intro
Tcpdump is the Swiss Army knife of packet capture. It’s lean, scriptable, and ships with almost every Unix-like system. That makes it ideal for automation, troubleshooting, or handing to a customer when you need a reproducible capture without walking them through a GUI.
Most people analyze captures in something like Wireshark, a solid open-source packet analyzer. But tcpdump is often the better tool for actually collecting the data in the first place since it can be scripted, shared as a one-liner, and run with minimal instructions.
Packet captures are rarely trivial though: they can result in big files, require various permissions, approvals, and scheduled maintenance windows. They’re not something you want to repeat needlessly. The goal is to get it right the first time .
Photo: Ave Maria / Jonas, via Wikimedia Commons, CC BY 2.0
Where to Capture?
Before worrying about command flags, it helps to think about point of view you need to target. Packet captures are always relative. What you see depends on where you’re listening from.
If you’re debugging a client/server exchange, you could capture on the client to confirm whether requests are leaving, or on the server to see if they arrive. Sometimes you need both perspectives: one to prove the client sent the packet, the other to prove the server received it (or didn’t).
The network itself matters too. On a flat LAN or broadcast domain, a capture may show you traffic between many hosts. But on a switched or routed network, you’ll only see packets destined to or from the machine you’re capturing on. That’s why capturing on the endpoint itself is often the simplest, most reliable approach.
For complex problems, it’s common to gather multiple captures — one at the client, one at the server, perhaps one taken at a switch or router. When you line them up by timestamp, you can follow the packet’s journey across the path and pinpoint where things break down.
Once you know where you need to capture from, you can follow a simple workflow:
- Start capture
- Start Repro (it’s really helpful to take notes and record the time you start, when you notice a behavior or error etc)
- Stop capture
- Analyze in Wireshark or a similar tool
Choosing the Right Interface
Once you know where you want to capture from you’ll need to choose the correct interface. This varies by system but typically you want Ethernet or Wi-fi. On modern systems, there can be a lot of interfaces for things like VPN tunnels, virtual intefaces and so on.
List available interfaces with:
tcpdump -D
On my system i get this potentially confusing list:
1.loopback0 [Up, Running, Connected]
2.eth2 [Up, Running, Connected]
3.eth0 [Up, Running, Connected]
4.any (Pseudo-device that captures on all interfaces) [Up, Running]
5.lo [Up, Running, Loopback]
6.docker0 [Up, Disconnected]
7.bluetooth-monitor (Bluetooth Linux Monitor) [Wireless]
8.nflog (Linux netfilter log (NFLOG) interface) [none]
9.nfqueue (Linux netfilter queue (NFQUEUE) interface) [none]
10.dbus-system (D-Bus system bus) [none]
11.dbus-session (D-Bus session bus) [none]
12.eth1 [none, Disconnected]
13.eth3 [none, Disconnected]
14.eth4 [none, Disconnected]
Most of these aren’t very interesting, like loopback, D-Bus, netfilter hooks etc. You typically want your Ethernet or Wi-Fi interface (the eth0, eth2.. interfaces in my list. You might see ens33 or wlan0 or en0 on yours).
You can get a more helpful list with a simple filter on the interface flags:
tcpdump -D | grep Connected
That returns a much more reasonable list although loopback is always a valid connected interface so it remains:
└─$ tcpdump -D | grep Connected
1.loopback0 [Up, Running, Connected]
2.eth2 [Up, Running, Connected]
3.eth0 [Up, Running, Connected]
You usually won’t be interested in loopback so that leaves two ethernet connections to choose from. If you’re not sure, you can usually just check to see which one has the ip address you want to capture on:
ifconfig eth0
On a lot of newer linuxes, the command is:
ip addr show eth0
If it’s still not clear, you can check to see which of the interfaces is “busy” and take a peek at the traffic. To check an interface you can grab a quick capture with:
sudo tcpdump -i eth0 -c 20
On my system, both eth0 and eth2 are active but within seconds of watching tcpdump on eth2 i could recognize familiar ips and dns names from my lan.
Gathering a Solid Capture
Now that you’ve thought about where to capture and how to focus your test, the next step is setting up tcpdump to record everything you need without losing detail.
Save to a File
For later analysis in Wireshark or another tool, always write to a .pcap:
sudo tcpdump -i eth0 -s 0 -w capture.pcap
-s 0→ capture the entire packet, not just the default snap length.-w→ write raw packets to a file (not human-readable).- Use
Ctrl+Cto stop when you’ve got enough.
Quick Checks
Sometimes you only need a small slice:
sudo tcpdump -i eth0 -s 0 -c 500 -w sample.pcap
-cstops after N packets.- Great for reproducible test runs.
Reading It Back
To verify or skim without Wireshark:
tcpdump -r capture.pcap
Pro Tips
- Always run with
sudo(or root). - Watch disk space — captures grow quickly.
- Time matters: make sure your system clock is accurate for useful logs.
Capturing Mobile Traffic
Both iOS and Android expose interfaces that tcpdump can hook into from a computer. In both cases you’ll need the device plugged in with a USB cable.
iOS (macOS host required)
On macOS, Apple provides a Remote Virtual Interface (RVI) that exposes iPhone or iPad network traffic over USB. The device must be unlocked and you’ll need to tap Trust this computer the first time you connect. Once enabled, the phone appears as a virtual interface (rvi0) that you can capture from with tcpdump.
The only catch: you need the device’s UDID (Unique Device Identifier). You can get it a few ways:
-
System Profiler (built-in):
Plug in your device, then run:system_profiler SPUSBDataType | grep -w "Serial Number"This prints the serial numbers of connected USB devices. For iPhones and iPads, that string is the UDID.
-
libimobiledevice (third-party tools):
If you have libimobiledevice installed, you can run:idevice_id -lwhich lists all connected iOS devices by UDID.
Pro-Tip If you’re giving instructions to someone else, you can make it a one-liner:
rvictl -s $(system_profiler SPUSBDataType | awk '/Serial Number/{print $3; exit}')
That command automatically grabs the first iOS device’s UDID and passes it to rvictl.
Once the RVI is active, check with:
rvictl -l
When finished, tear it down with:
rvictl -x <device-udid>
At that point, rvi0 behaves like any other interface. You can capture traffic from it just like you would on Ethernet or Wi-Fi:
sudo tcpdump -i rvi0 -s 0 -w iphone.pcap
This gives you a complete packet trace of the phone’s traffic.
Android (USB required)
Android doesn’t expose an RVI, but you can capture traffic via the Android Debug Bridge (adb). Your phone must be plugged in over USB with USB debugging enabled. On many devices this works out of the box, but some builds require a tcpdump binary installed on the phone and root privileges to run it.
- macOS:
brew install android-platform-tools - Debian/Ubuntu:
sudo apt install android-tools-adb - Fedora:
sudo dnf install android-tools - Windows:
Download Android Platform Tools from Google.
With adb installed and your phone connected by USB (with USB debugging enabled), verify the device is detected:
adb devices
You may need to accept a prompt on the phone.
From there, you have two approaches:
-
Capture directly on the device:
adb shell tcpdump -i any -s 0 -w /sdcard/capture.pcap adb pull /sdcard/capture.pcapThis writes a
.pcapfile to the device and then pulls it back to your computer. -
Stream packets live to your desktop:
adb exec-out tcpdump -i any -s 0 -w - > android.pcapThis writes the capture directly to your computer for later analysis in Wireshark (or the moral equivalent).
Filtering for Relevance
Captures get big quickly so it’s important to filter out as much noise as possible. Tcpdump uses the Berkeley Packet Filter (BPF) syntax, which is fairly simple once you know a few basics.
In practice, you’ll usually want to capture full packets and write them to a file for later analysis in Wireshark. For example:
sudo tcpdump -i eth0 -s 0 -w capture.pcap 'tcp port 443 and host example.com'
-s 0→ capture the entire packet-w capture.pcap→ write to a file instead of printing to the screen- Filter expression in quotes → what traffic to capture
For the examples below, we’ll omit the -s 0 -w ... parts to keep things short, but remember to include them when you’re running a real capture.
Common Filters
# Host-based
tcpdump host 192.168.1.50
tcpdump src host 10.0.0.5
tcpdump dst host example.com
# Port-based
tcpdump port 80
tcpdump tcp port 443
# Protocol
tcpdump icmp
tcpdump arp
tcpdump udp
Practical Filtering Recipes
# DNS traffic only
tcpdump -i eth0 port 53
# HTTP traffic to a specific host
tcpdump -i eth0 tcp port 80 and host example.com
# HTTPS traffic to a specific host
tcpdump -i eth0 tcp port 443 and host 203.0.113.42
# All web traffic (HTTP + HTTPS) from one client
tcpdump -i eth0 host 192.168.1.25 and \( port 80 or port 443 \)
# Capture traffic in a subnet
tcpdump net 192.168.1.0/24
# Capture all but one noisy host
tcpdump not host 192.168.1.10
# SSH traffic to or from a specific server
tcpdump tcp port 22 and host bastion.example.com
# ICMP (pings) except from a certain host
tcpdump icmp and not src host 10.0.0.5
# Multiple conditions: HTTPS to a subnet, but ignore one host
tcpdump tcp port 443 and net 10.0.0.0/24 and not host 10.0.0.50
Tips
- Use parentheses
()when combining multiple expressions (escape them in shells with\(\)). - Add
-nto prevent tcpdump from resolving hostnames (faster, less noise). - Increase detail with
-v,-vv, or-vvvwhen reviewing packets live. - Filters in tcpdump (BPF) are not the same as Wireshark display filters — capture filters decide what packets are saved, while display filters decide what you see later.
Links & Stuff
Essential Documentation:
Further Reading:
- Tcpdump Zine by Julia Evans — a fun, visual guide that complements this article.
- Packet Life Cheat Sheets — quick reference sheets for tcpdump, Wireshark, and more.
Conclusion
pcaps or it didn’t happen!
If you found this post useful or if you have questions, I’d love to hear from you: feedback@adminjitsu.com