Wireshark vs tcpdump: pick the right tool, then use the other one anyway.
When you reach for a GUI, when you reach for a CLI, and how to make them work together in real incident response.
Wireshark and tcpdump are not a choice. They are a workflow. tcpdump captures the bytes; Wireshark reads the pcap. You can do everything with either, but you will be slow doing it. The right move is to learn what each is good at and let them do that.
The split, in one table
| Job | Tool |
|---|---|
| Capture on a remote / headless box | tcpdump |
| Capture with a tight kernel filter, low CPU | tcpdump |
| Read a pcap and follow a TCP stream | Wireshark |
| Decode an obscure protocol (DICOM, BACnet, SCADA) | Wireshark |
| Pull bytes from a 50 GB capture without opening it | tcpdump / tshark |
| Show a non-network person what is wrong | Wireshark |
Two filter languages, do not confuse them
This is where most people get hurt. There are two filter languages and they look similar but are not.
- BPF (capture) filters — applied at the kernel, decide what enters the capture buffer. Used by tcpdump and Wireshark's capture dialog. Looks like
tcp port 443. - Display filters — applied to a loaded pcap, decide what is shown. Wireshark and tshark only. Looks like
tcp.port == 443.
Same intent, different syntax, different semantics. BPF cannot reach into application layers; display filters can. Mistakenly using a display filter at capture time silently produces an empty pcap.
Capture playbook
# Ring buffer: keep last 1 GB across 10 files of 100 MB each
sudo tcpdump -i eth0 -w cap-%Y%m%d-%H%M%S.pcap -W 10 -C 100
# Capture only traffic to/from a host, no DNS noise
sudo tcpdump -i eth0 'host 10.0.0.42 and not port 53' -w host42.pcap
# Slice each packet so PII never lands on disk
sudo tcpdump -i eth0 -s 96 -w headers-only.pcap
The last one matters more than people think. A capture with full payloads on a shared workstation is a data-protection incident waiting to happen. -s 96 keeps headers and a sliver of payload — enough for most protocol troubleshooting, nothing for content recovery.
Reading a pcap headlessly with tshark
Wireshark's CLI sibling. Same dissectors, same display filter syntax. Lets you do half of what people open Wireshark for, in a shell, on a server.
# Top 10 hosts by bytes sent
tshark -r cap.pcap -q -z conv,ip | head -25
# Every TLS SNI in the file
tshark -r cap.pcap -Y 'tls.handshake.type == 1' -T fields -e tls.handshake.extensions_server_name | sort -u
# All HTTP request paths
tshark -r cap.pcap -Y http.request -T fields -e http.request.full_uri
When Wireshark earns its weight
"Follow TCP stream" is the feature you cannot live without and cannot replicate in five lines of script. Two clicks turn a thousand packets into a clean transcript of an HTTP or SMTP or Telnet session. Decoded, in order, with the right encoding guessed.
Wireshark's protocol dissector library is the other reason. Niche industrial and medical protocols — Modbus, BACnet, DICOM, S7 — are decoded out of the box. tcpdump shows you bytes; Wireshark shows you the meaning.
Operational rules
- Never run Wireshark as root on a production capture. Capture with tcpdump as root, read the pcap as your user.
- Use
editcap(ships with Wireshark) to slice a giant pcap by time window before opening it. Wireshark will open multi-GB files; it will not be fun. - If a colleague asks for "the packet", send the smallest pcap that demonstrates the problem. tcpdump's BPF lets you build that in one line.
- Strip secrets first:
tshark -F pcap -r in.pcap -w out.pcap -Y 'not (tcp.port == 22)'drops every SSH packet.
The takeaway
tcpdump captures. Wireshark explains. tshark scripts both. You do not pick — you assemble.