Tcpdump Command Builder
tcpdump -n
Interface & Capture
File I/O
Display
Filters (BPF)
Recipes
What is tcpdump?
tcpdump is the most widely used command-line packet analyzer. It captures network packets and displays them in real-time or saves them to PCAP files for later analysis with tools like Wireshark. tcpdump uses Berkeley Packet Filter (BPF) syntax for filtering traffic. Available on virtually every Linux, macOS, and BSD system, it's the first tool network engineers reach for when diagnosing connectivity issues.
Common BPF Filter Examples
| Filter | Description |
|---|---|
| host 10.0.0.1 | Traffic to/from IP |
| port 80 | HTTP traffic |
| tcp and port 443 | HTTPS traffic |
| net 192.168.1.0/24 | Subnet traffic |
| icmp | Ping traffic |
| not port 22 | Exclude SSH |
Advanced BPF Filter Patterns
BPF filters can be combined with logical operators (and, or, not) and grouped with parentheses for complex filtering. This is critical for isolating specific traffic patterns in production environments.
# DNS queries only (not responses) — filter by UDP src port tcpdump -i eth0 udp dst port 53 # HTTP requests to a specific host (captures GET/POST headers) tcpdump -i eth0 -A 'tcp dst port 80 and host api.example.com' # TCP SYN packets only (new connections) — useful for connection rate analysis tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' # TCP RST packets (connection resets — indicates issues) tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0' # Large packets (MTU issues, jumbo frames) tcpdump -i eth0 'greater 1500' # Traffic between two specific hosts, excluding SSH tcpdump -i eth0 'host 10.0.0.1 and host 10.0.0.2 and not port 22' # VLAN-tagged traffic (802.1Q) tcpdump -i eth0 'vlan and host 10.0.0.1' # ARP traffic (useful for network discovery issues) tcpdump -i eth0 arp
Reading tcpdump Output
A typical tcpdump line looks like: 14:32:01.123456 IP 10.0.0.1.443 > 10.0.0.2.52104: Flags [P.], seq 1:50, ack 1, length 49. The fields are: timestamp, protocol, source.port, destination.port, TCP flags, sequence numbers, and payload length.
| Flag | Symbol | Meaning |
|---|---|---|
| S | SYN | Connection initiation (first packet of 3-way handshake) |
| S. | SYN-ACK | Server acknowledges SYN (second packet of handshake) |
| . | ACK | Acknowledgment (data received successfully) |
| P. | PSH-ACK | Push data to application (most data packets) |
| F. | FIN-ACK | Connection termination (graceful close) |
| R | RST | Connection reset (abrupt close — usually an error) |
| R. | RST-ACK | Reset + acknowledge (rejecting a connection attempt) |
Troubleshooting Patterns
tcpdump is essential for diagnosing specific network problems. Here are the most common production troubleshooting scenarios:
| Problem | tcpdump Command | What to Look For |
|---|---|---|
| Connection timeouts | tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' | SYN without SYN-ACK response — firewall or server down |
| Connection resets | tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0' | RST packets — port not listening, firewall reject, app crash |
| DNS failures | tcpdump -i eth0 port 53 -vv | Queries without responses, NXDOMAIN, SERVFAIL |
| TLS handshake issues | tcpdump -i eth0 port 443 -w tls.pcap | Capture and analyze in Wireshark with TLS dissector |
| Slow responses | tcpdump -i eth0 -ttt host api.backend | Delta timestamps show where latency occurs |
| MTU/fragmentation | tcpdump -i eth0 'icmp[0] == 3 and icmp[1] == 4' | ICMP "fragmentation needed" messages (Path MTU discovery) |
Performance Tips for Production Captures
Running tcpdump in production requires care to avoid impacting performance or filling disk:
# Rotate capture files: 100MB each, keep 10 files tcpdump -i eth0 -w capture-%Y%m%d-%H%M.pcap -C 100 -W 10 # Capture only headers (first 96 bytes) — saves disk, usually enough tcpdump -i eth0 -s 96 -w headers.pcap # Use kernel-level filtering (much faster than post-capture filtering) tcpdump -i eth0 'port 443 and host 10.0.0.1' -w targeted.pcap # Buffer size for high-traffic interfaces (reduces dropped packets) tcpdump -i eth0 -B 4096 -w capture.pcap # Count packets matching a filter (no capture) tcpdump -i eth0 -c 1000 'tcp dst port 80' --count # Time-limited capture (60 seconds via timeout) timeout 60 tcpdump -i eth0 -w short-capture.pcap
Always use -w (write to file) in production rather than printing to stdout — stdout display is 10-50x slower than file writes and will cause packet drops on busy interfaces. Analyze the PCAP file afterwards with tcpdump -r or Wireshark.
tcpdump vs Wireshark vs tshark
| Feature | tcpdump | tshark | Wireshark |
|---|---|---|---|
| Interface | CLI | CLI | GUI |
| Filter syntax | BPF only | BPF + display filters | BPF + display filters |
| Protocol dissectors | Basic (~50) | Extensive (~3000) | Extensive (~3000) |
| Best for | Quick server captures | Scripted analysis | Deep visual analysis |
| Installed by default | Most Linux distros | No | No |
| Typical workflow | Capture to .pcap | Analyze .pcap files | Open .pcap from tcpdump |
The standard workflow: capture with tcpdump -w capture.pcap on a remote server via SSH, transfer the file, then analyze in Wireshark for detailed protocol inspection. For scripted/automated analysis, use tshark — it has the same deep protocol dissectors as Wireshark but runs on the command line.
tcpdump in Docker & Kubernetes
Capturing traffic in containerized environments requires accessing the correct network namespace. Standard tcpdump -i eth0 on the host won't see container-internal traffic. Here are patterns for each environment:
# Docker: run tcpdump inside a container
docker exec -it mycontainer tcpdump -i eth0 -nn port 8080
# Docker: if container has no tcpdump, use a sidecar
docker run --rm --net=container:mycontainer nicolaka/netshoot tcpdump -i eth0 -nn
# Docker: capture on docker bridge (host-level, sees all containers)
tcpdump -i docker0 -nn port 80
# Docker Compose: capture between services
tcpdump -i br-$(docker network ls -q -f name=myproject_default) -nn
# Kubernetes: capture in a pod (if tcpdump is installed)
kubectl exec -it mypod -- tcpdump -i eth0 -nn -c 100
# Kubernetes: ephemeral debug container (no tcpdump in pod image)
kubectl debug -it mypod --image=nicolaka/netshoot --target=mycontainer -- \
tcpdump -i eth0 -nn -w /tmp/capture.pcap
# Kubernetes: capture on node for specific pod IP
# First get pod IP: kubectl get pod mypod -o jsonpath='{.status.podIP}'
ssh node1 "tcpdump -i cni0 -nn host 10.244.1.15"
# nsenter: access container network namespace from host (requires PID)
PID=$(docker inspect --format '{{.State.Pid}}' mycontainer)
nsenter -t $PID -n tcpdump -i eth0 -nn -c 50For Kubernetes, the ephemeral debug container approach (kubectl debug) is preferred because it doesn't require tcpdump in the application image. For Docker, the --net=container: trick with netshoot is the cleanest approach.
Security Monitoring with tcpdump
tcpdump is a first-line tool for detecting suspicious network activity. These patterns help identify common attack vectors in real-time or from saved captures:
| Threat | Detection Command | Indicators |
|---|---|---|
| Port scan (SYN scan) | tcpdump -nn 'tcp[tcpflags] == tcp-syn' | Many SYN packets to different ports from same source |
| SYN flood (DDoS) | tcpdump -nn 'tcp[tcpflags] == tcp-syn' -c 1000 | High SYN rate from many sources, no ACK completion |
| DNS exfiltration | tcpdump -nn port 53 -vv -A | Unusually long DNS queries, high query rate to non-standard resolvers |
| ARP spoofing | tcpdump -nn arp | Multiple ARP replies for same IP with different MACs |
| ICMP tunnel | tcpdump -nn 'icmp and greater 100' | Large ICMP packets (>100 bytes) with data payloads |
| Unauthorized outbound | tcpdump -nn 'dst port 4444 or dst port 1337' | Outbound connections on suspicious ports (reverse shells) |
Automated Analysis & One-Liners
tcpdump output can be piped to standard Unix tools for quick statistics without opening Wireshark. These one-liners are useful for production triage:
# Count connections per source IP (top talkers)
tcpdump -nn -r capture.pcap 'tcp[tcpflags] == tcp-syn' 2>/dev/null | \
awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head -20
# Count packets per protocol
tcpdump -nn -r capture.pcap 2>/dev/null | \
awk '{print $2}' | sort | uniq -c | sort -rn
# Extract all unique destination IPs
tcpdump -nn -r capture.pcap 2>/dev/null | \
awk '{print $5}' | cut -d. -f1-4 | sort -u
# Monitor HTTP requests in real-time (unencrypted only)
tcpdump -i eth0 -A -s 0 'tcp dst port 80' 2>/dev/null | \
grep -oP '(GET|POST|PUT|DELETE|PATCH) S+'
# Calculate packets per second (real-time rate)
tcpdump -i eth0 -nn -q 2>/dev/null | \
awk '{count++; if(NR%100==0) print strftime("%H:%M:%S"), count/100, "pps"; count=0}'
# Extract DNS queries from capture
tcpdump -nn -r capture.pcap port 53 2>/dev/null | \
grep -oP 'A? S+' | sort | uniq -c | sort -rn | head -20
# Measure response latency between SYN and SYN-ACK
tcpdump -i eth0 -nn -ttt 'tcp port 443 and (tcp[tcpflags] & (tcp-syn) != 0)' 2>/dev/nullFor deeper automated analysis, save to PCAP with -w and use tshark instead — it supports display filters like tshark -r capture.pcap -T fields -e ip.src -e http.request.uri for structured field extraction.
Understanding the Three-Way Handshake
Every TCP connection starts with a three-way handshake visible in tcpdump output. Understanding this pattern is fundamental to diagnosing connection problems:
# Successful connection (3-way handshake): 14:32:01.001 IP client.52104 > server.443: Flags [S], seq 100 # 1. SYN 14:32:01.002 IP server.443 > client.52104: Flags [S.], seq 200 ack 101 # 2. SYN-ACK 14:32:01.003 IP client.52104 > server.443: Flags [.], ack 201 # 3. ACK # Failed connection (no response — firewall dropping): 14:32:01.001 IP client.52104 > server.443: Flags [S], seq 100 14:32:02.001 IP client.52104 > server.443: Flags [S], seq 100 # Retransmit after 1s 14:32:04.001 IP client.52104 > server.443: Flags [S], seq 100 # Retransmit after 2s # Failed connection (port closed — RST response): 14:32:01.001 IP client.52104 > server.443: Flags [S], seq 100 14:32:01.002 IP server.443 > client.52104: Flags [R.], ack 101 # RST = port not listening
Privacy: This tool runs entirely in your browser. No commands are sent to any server.