Skip to content

tcpdump - Packet Capture

tcpdump is a command-line packet analyzer. It captures raw network traffic passing through an interface and lets you inspect it in real-time or save it to a file for later analysis.

tcpdump

It works by putting the network interface into promiscuous mode (captures all frames, not just those addressed to the host) and applying BPF (Berkeley Packet Filter) expressions to select what to capture.


Terminal window
# List available interfaces
tcpdump -D
# 1.eth0 [Up, Running, Connected]
# 2.lo [Up, Running, Loopback]
# Capture on a specific interface (Ctrl+C to stop)
sudo tcpdump -i eth0
# Capture with verbose output
sudo tcpdump -v -i eth0
# Even more verbose (shows all header fields)
sudo tcpdump -vv -i eth0
# Don't resolve hostnames or port names (faster, shows raw IPs:ports)
sudo tcpdump -n -i eth0
# Combine both
sudo tcpdump -nn -i eth0
12:34:56.789012 IP 192.168.1.50.42156 > 8.8.8.8.53: UDP, length 29
│ │ │ │ │ │ │ └─ payload size
│ │ │ │ │ │ └─ protocol
│ │ │ │ │ └─ destination port
│ │ │ │ └─ destination IP
│ │ │ └─ source port (ephemeral)
│ │ └─ source IP
│ └─ protocol (IP/IP6/ARP/etc)
└─ timestamp (HH:MM:SS.microseconds)

pcap

Terminal window
# Save to a .pcap file (can be opened in Wireshark)
sudo tcpdump -i eth0 -w capture.pcap
# Save with rotation (1MB files, keep last 5)
sudo tcpdump -i eth0 -w capture.pcap -C 1 -W 5
# Read from a saved file
tcpdump -r capture.pcap
# Read with no name resolution
tcpdump -nn -r capture.pcap
# Read with verbose output
tcpdump -vv -r capture.pcap

BPF Filter Expressions

Filters are the most important part of tcpdump - without them you see everything and it’s overwhelming.

Terminal window
# Traffic to or from a specific host
sudo tcpdump -nn -i eth0 host 8.8.8.8
# Traffic from a specific host (source only)
sudo tcpdump -nn -i eth0 src host 192.168.1.50
# Traffic to a specific host (destination only)
sudo tcpdump -nn -i eth0 dst host 10.0.0.1
# Entire subnet
sudo tcpdump -nn -i eth0 net 192.168.1.0/24
Terminal window
# All traffic on port 80
sudo tcpdump -nn -i eth0 port 80
# All TCP traffic
sudo tcpdump -nn -i eth0 tcp
# All UDP traffic
sudo tcpdump -nn -i eth0 udp
# All ICMP (ping) traffic
sudo tcpdump -nn -i eth0 icmp
# DNS traffic specifically (UDP port 53)
sudo tcpdump -nn -i eth0 udp port 53
# HTTP traffic
sudo tcpdump -nn -i eth0 tcp port 80
# HTTPS traffic (encrypted - you'll see TLS handshakes but not content)
sudo tcpdump -nn -i eth0 tcp port 443
Terminal window
# AND - both conditions must be true
sudo tcpdump -nn -i eth0 host 8.8.8.8 and port 53
# OR - either condition
sudo tcpdump -nn -i eth0 port 80 or port 443
# NOT - exclude a pattern
sudo tcpdump -nn -i eth0 not port 22
# Complex example: HTTP from a specific host, not SSH
sudo tcpdump -nn -i eth0 src host 192.168.1.50 and port 80 and not port 22
# Parentheses for grouping
sudo tcpdump -nn -i eth0 host 192.168.1.50 and '(port 80 or port 443)'

Terminal window
# Watch all DNS queries and responses
sudo tcpdump -nn -i eth0 udp port 53 -v
# Output example showing a query and response:
# 12:34:56 IP 192.168.1.50.5432 > 8.8.8.8.53: A? google.com. (28)
# 12:34:56 IP 8.8.8.8.53 > 192.168.1.50.5432: A google.com. 142.250.185.46 (44)
Terminal window
# Capture HTTP and show content (ASCII)
sudo tcpdump -nn -i eth0 tcp port 80 -A
# Show first 200 bytes of each packet (headers often visible)
sudo tcpdump -nn -i eth0 tcp port 80 -A -s 200
# -A = print packet data as ASCII
# -s = snap length (bytes to capture per packet, default 262144)
Terminal window
# Show only TCP SYN packets (new connection attempts)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-syn != 0'
# Show only TCP RST packets (rejected connections)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'
# Show SYN and RST together (problems connecting to a port)
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-rst) != 0'
# See TCP connections between two hosts
sudo tcpdump -nn -i eth0 host 10.0.0.1 and host 10.0.0.2 and tcp
Terminal window
# Useful when you suspect a routing problem
# Check if packets from a source are arriving at all
sudo tcpdump -nn -i eth0 src host 192.168.1.100
# If you see nothing, packets are being dropped before reaching this interface
# Check firewall rules, routing table, and switch port
Terminal window
# Debug ARP resolution issues (duplicate IPs, ARP spoofing)
sudo tcpdump -nn -i eth0 arp
# Output:
# 12:34:56 ARP, Request who-has 192.168.1.1 tell 192.168.1.50, length 28
# 12:34:56 ARP, Reply 192.168.1.1 is-at aa:bb:cc:dd:ee:ff, length 28

tcpdump on a Specific Process

Linux doesn’t have per-process packet capture natively, but you can:

Terminal window
# Find the PID and its connections
ss -tlnp | grep <port>
# Then drop unrelated traffic with filters
sudo tcpdump -nn -i eth0 port <port the process is using>
# For containerized apps, capture on the container's veth interface
# (found with: ip link show | grep veth, then ip link show <vethXXX>)

FlagMeaning
-i eth0Interface to capture on
-nDon’t resolve hostnames
-nnDon’t resolve hostnames or port names
-v / -vvVerbose / very verbose output
-APrint packet payload as ASCII
-w file.pcapWrite to file
-r file.pcapRead from file
-c 100Capture only 100 packets
-s 0Capture full packets (no truncation)
-eShow Ethernet MAC addresses
-XShow hex + ASCII of packet payload