Linux tcpdump: Network Packet Capture

tcpdump is the standard command-line packet analyzer for Unix-like systems. It captures network traffic passing through a network interface and displays packet headers or saves them for later...

Key Insights

  • tcpdump uses Berkeley Packet Filter (BPF) expressions to capture specific traffic, reducing noise and focusing on relevant packets—master the syntax of host, port, and logical operators to build precise filters
  • Always save captures to pcap files with -w for later analysis rather than trying to parse real-time output, and use -s to limit snapshot length when you only need headers
  • Combine protocol filters with TCP flags and port numbers to troubleshoot specific issues: tcp[tcpflags] & tcp-syn != 0 catches SYN packets for connection debugging

Introduction to tcpdump

tcpdump is the standard command-line packet analyzer for Unix-like systems. It captures network traffic passing through a network interface and displays packet headers or saves them for later analysis. Whether you’re debugging application connectivity, investigating security incidents, or understanding protocol behavior, tcpdump is an essential tool in your troubleshooting arsenal.

The tool operates at a low level, capturing packets before they reach application code. This makes it invaluable for diagnosing issues that higher-level tools miss—malformed packets, timing problems, or unexpected protocol behavior. You’ll need root privileges or sudo access to capture packets since it requires direct interface access.

Here’s what tcpdump output looks like by default:

sudo tcpdump
15:23:45.123456 IP 192.168.1.100.54321 > 93.184.216.34.443: Flags [S], seq 123456789, win 65535, length 0
15:23:45.145678 IP 93.184.216.34.443 > 192.168.1.100.54321: Flags [S.], seq 987654321, ack 123456790, win 65535, length 0

Each line shows a timestamp, protocol, source and destination addresses with ports, TCP flags, sequence numbers, and packet length. Understanding this format is crucial for effective packet analysis.

Basic Packet Capture Syntax

The fundamental tcpdump syntax follows this pattern: tcpdump [options] [filter expression]. The most important options control which interface to monitor, how many packets to capture, and output verbosity.

Specify an interface with -i. Without this flag, tcpdump uses the first available interface, which might not be what you want:

# Capture on specific interface
sudo tcpdump -i eth0

# Capture on any interface
sudo tcpdump -i any

# List available interfaces
tcpdump -D

Limit the number of packets with -c to avoid overwhelming output:

# Capture exactly 100 packets then stop
sudo tcpdump -i eth0 -c 100

The -n flag prevents DNS lookups, making output faster and avoiding reverse DNS queries that could alter your network behavior:

# No hostname resolution, show IP addresses
sudo tcpdump -i eth0 -n

Increase verbosity with -v, -vv, or -vvv to see more packet details:

# Standard verbosity
sudo tcpdump -i eth0 -v

# More detail (TTL, IP options, checksums)
sudo tcpdump -i eth0 -vv

# Maximum detail
sudo tcpdump -i eth0 -vvv

Higher verbosity levels show additional header fields, checksums, and protocol-specific information. Use -vvv when you need to see everything, but be aware it generates significant output.

Filtering Traffic with BPF Expressions

Berkeley Packet Filter expressions let you capture only relevant traffic. Without filters, tcpdump captures everything—including its own DNS lookups and SSH traffic if you’re connected remotely. Good filters are essential for productive troubleshooting.

Filter by host to capture traffic to or from a specific IP:

# Traffic to/from specific host
sudo tcpdump -i eth0 host 192.168.1.50

# Traffic from specific source
sudo tcpdump -i eth0 src host 192.168.1.50

# Traffic to specific destination
sudo tcpdump -i eth0 dst host 192.168.1.50

Filter by port to focus on specific services:

# HTTP traffic
sudo tcpdump -i eth0 port 80

# HTTPS traffic
sudo tcpdump -i eth0 port 443

# SSH traffic
sudo tcpdump -i eth0 port 22

# Source or destination port
sudo tcpdump -i eth0 src port 54321

Filter by protocol to isolate TCP, UDP, or ICMP traffic:

# Only TCP packets
sudo tcpdump -i eth0 tcp

# Only UDP packets
sudo tcpdump -i eth0 udp

# Only ICMP (ping) packets
sudo tcpdump -i eth0 icmp

Combine filters using logical operators—and, or, and not:

# HTTPS traffic to specific host
sudo tcpdump -i eth0 host 192.168.1.50 and port 443

# HTTP or HTTPS traffic
sudo tcpdump -i eth0 port 80 or port 443

# All traffic except SSH (useful when connected via SSH)
sudo tcpdump -i eth0 not port 22

# TCP traffic to specific host, excluding port 22
sudo tcpdump -i eth0 tcp and host 192.168.1.50 and not port 22

Use parentheses for complex expressions, but escape them in the shell:

sudo tcpdump -i eth0 'host 192.168.1.50 and (port 80 or port 443)'

Advanced Filtering and Output Options

Save captures to files for later analysis with Wireshark or other tools:

# Save to pcap file
sudo tcpdump -i eth0 -w capture.pcap

# Save with packet count limit
sudo tcpdump -i eth0 -w capture.pcap -c 1000

# Read from saved file
tcpdump -r capture.pcap

# Read and apply filter
tcpdump -r capture.pcap port 443

Display packet contents in ASCII or hexadecimal:

# ASCII output (useful for HTTP)
sudo tcpdump -i eth0 -A port 80

# Hex and ASCII output
sudo tcpdump -i eth0 -X port 80

# Hex output only
sudo tcpdump -i eth0 -xx

Filter by TCP flags to capture specific connection states:

# Capture SYN packets (connection attempts)
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0'

# Capture SYN-ACK packets
sudo tcpdump -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack)'

# Capture FIN packets (connection termination)
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-fin != 0'

# Capture RST packets (connection reset)
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-rst != 0'

Control timestamp format:

# Absolute timestamps (default)
sudo tcpdump -i eth0 -tttt

# No timestamp
sudo tcpdump -i eth0 -t

# Delta between packets
sudo tcpdump -i eth0 -ttt

Practical Use Cases

Capture HTTP traffic to debug API calls or web application issues:

# Capture HTTP requests and responses
sudo tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

# Simpler: capture HTTP with payload
sudo tcpdump -i eth0 -A -s 0 port 80

Monitor DNS queries to troubleshoot name resolution:

# Capture DNS queries and responses
sudo tcpdump -i eth0 -n port 53

# More readable DNS output
sudo tcpdump -i eth0 -n -vv port 53

Debug SSH connection problems:

# Capture SSH handshake
sudo tcpdump -i eth0 -n port 22

# Capture SSH with SYN packets only
sudo tcpdump -i eth0 -n 'port 22 and tcp[tcpflags] & tcp-syn != 0'

Detect potential port scans by monitoring SYN packets without established connections:

# Watch for SYN packets to multiple ports
sudo tcpdump -i eth0 -n 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0'

Troubleshoot network connectivity by combining ICMP with specific hosts:

# Monitor ping to specific host
sudo tcpdump -i eth0 icmp and host 8.8.8.8

# Check for ICMP unreachable messages
sudo tcpdump -i eth0 'icmp[icmptype] == icmp-unreach'

Performance Considerations and Best Practices

When capturing high-volume traffic, increase the buffer size to prevent packet loss:

# Set buffer to 4MB
sudo tcpdump -i eth0 -B 4096 -w capture.pcap

Limit snapshot length when you only need headers, not full payloads. This reduces file size and processing overhead:

# Capture only first 96 bytes (headers only)
sudo tcpdump -i eth0 -s 96 -w headers.pcap

# Capture full packets (default in modern tcpdump)
sudo tcpdump -i eth0 -s 0 -w full.pcap

For long-running captures, rotate files to manage disk space:

# Rotate files every 100MB, keep 5 files
sudo tcpdump -i eth0 -w capture.pcap -C 100 -W 5

This creates capture.pcap0 through capture.pcap4, overwriting the oldest when the limit is reached.

Always apply filters as early as possible. Filtering during capture is more efficient than capturing everything and filtering during analysis:

# Good: filter during capture
sudo tcpdump -i eth0 port 443 -w https.pcap

# Bad: capture everything, filter later
sudo tcpdump -i eth0 -w everything.pcap
tcpdump -r everything.pcap port 443

Be mindful of security implications. Packet captures contain sensitive data—passwords, session tokens, personal information. Encrypt or securely delete captures when finished. Never capture on production systems without authorization.

When troubleshooting remotely via SSH, always exclude SSH traffic from captures to avoid feedback loops and overwhelming output:

sudo tcpdump -i eth0 not port 22 -w capture.pcap

Use tcpdump in combination with other tools. Capture with tcpdump, analyze with Wireshark. The command-line interface is perfect for remote servers, while Wireshark’s GUI excels at detailed protocol analysis.

tcpdump is powerful but requires practice. Start with simple captures on test systems, gradually building more complex filters as you understand the output. The investment in learning tcpdump pays dividends throughout your career—it’s a tool you’ll reach for repeatedly when networks misbehave.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.