▶Prefer to watch? This video runs the guide's main commands on a real Ubuntu 24.04 machine, with on-screen captions and no voiceover. Click to play, or watch it on YouTube. It is part of the Networking and Firewalls playlist.
tcpdump [options] [filter expression]
sudo tcpdump -i eth0 port 80
tcpdump captures and prints network packets as they cross an interface. It is the
fastest way to answer "is the traffic actually arriving?" on a server with no GUI.
It needs root (sudo). Only capture traffic on networks you are authorized to monitor.
Captured packets can contain passwords and personal data. Handle files with care.
Choose the interface
sudo tcpdump -D # list interfaces
sudo tcpdump -i eth0 # one interface
sudo tcpdump -i any # all interfaces (Linux)
sudo tcpdump -i lo # loopback (local traffic)
Common options
-i IFACE Interface to listen on -n Do not resolve hostnames
-nn Also do not resolve port names -c N Stop after N packets
-v / -vv More detail -q Quieter, shorter lines
-X Show packet contents in hex and ASCII -XX also the link header
-A Show contents as ASCII (good for HTTP) -e Show MAC addresses
-s 0 Capture whole packets (default snaplen varies by version)
-t No timestamps -tttt Human-readable date and time
-l Line-buffered output (for piping) -p Do not use promiscuous mode
-w FILE Write raw packets to a file -r FILE Read a saved file
-C SIZE Start a new file every SIZE million bytes -G SECS Rotate files by time
-W N Keep only N files (with -C) -Z USER Drop privileges after opening
-Q in|out Only inbound or outbound packets (Linux) -S Absolute TCP sequence numbers
Good default while investigating: sudo tcpdump -nn -i eth0
Filter by host, network and port
host 192.168.1.10 # to or from this host
src host 192.168.1.10 # from
dst host 192.168.1.10 # to
net 192.168.1.0/24 # a network
src net 10.0.0.0/8
port 443 # a port (TCP or UDP)
src port 22 dst port 53
portrange 8000-9000
ether host aa:bb:cc:dd:ee:ff # by MAC address
Examples:
sudo tcpdump -nn -i eth0 host 8.8.8.8
sudo tcpdump -nn -i eth0 net 10.0.0.0/8 and port 22
Filter by protocol
tcp udp icmp icmp6 arp ip ip6
sudo tcpdump -nn icmp # pings
sudo tcpdump -nn arp # who-has / is-at requests
sudo tcpdump -nn udp port 53 # DNS
sudo tcpdump -nn 'tcp port 80 or tcp port 443'
sudo tcpdump -nn vlan # VLAN-tagged frames
Combine filters
and (or &&) or (or ||) not (or !) Use parentheses, and quote them
sudo tcpdump -nn 'host 10.0.0.5 and (port 80 or port 443)'
sudo tcpdump -nn 'src 10.0.0.5 and not port 22'
sudo tcpdump -nn 'not arp and not icmp'
sudo tcpdump -nn 'tcp and dst port 3306 and net 10.0.0.0/24'
Always quote filters that contain ( ) ! so the shell leaves them alone.
TCP flags
tcp[tcpflags] & (tcp-syn) != 0 # any SYN
tcp[tcpflags] & (tcp-syn|tcp-ack) == tcp-syn # SYN only: new connection attempts
tcp[tcpflags] & (tcp-syn|tcp-ack) == (tcp-syn|tcp-ack) # SYN-ACK
tcp[tcpflags] & (tcp-rst) != 0 # resets: refused or aborted connections
tcp[tcpflags] & (tcp-fin) != 0 # connection closes
sudo tcpdump -nn 'tcp[tcpflags] == tcp-syn'
Flags in the output: [S] SYN [S.] SYN-ACK [.] ACK [P.] push [F.] FIN [R] reset
Packet size and content
less 128 greater 1000 # by packet length
sudo tcpdump -nn 'greater 1400' # large packets (MTU issues)
sudo tcpdump -nn 'ip[8] < 5' # low TTL
sudo tcpdump -nn -A 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' # HTTP with data
Save and read captures
sudo tcpdump -nn -i eth0 -w capture.pcap # save (Ctrl+C to stop)
sudo tcpdump -nn -i eth0 -c 1000 -w cap.pcap # stop after 1000 packets
sudo tcpdump -nn -i eth0 -w cap-%F-%H%M.pcap -G 3600 -W 24 # hourly files, keep 24
sudo tcpdump -nn -i eth0 -C 100 -W 10 -w ring.pcap # 100MB ring buffer of 10 files
tcpdump -nn -r capture.pcap # read it back
tcpdump -nn -r capture.pcap host 10.0.0.5 # filter while reading
tcpdump -nn -r capture.pcap -A | less
Open the .pcap in Wireshark for a deep look (wireshark capture.pcap or tshark -r capture.pcap).
Writing to a file is far faster than printing to the screen. Use -w on busy links.
Reading the output
14:03:22.481 IP 10.0.0.5.51422 > 93.184.216.34.443: Flags [S], seq 3841, win 64240, length 0
time proto source.port > destination.port: flags, sequence, window, payload length
Source and destination are host.port. Flags [S] means the client is starting a connection.
A healthy connection: [S] then [S.] then [.]. Many [S] with no [S.] means the server is not answering.
Practical one-liners
# Is any traffic reaching this port at all?
sudo tcpdump -nn -i any port 8080 -c 10
# Watch DNS queries
sudo tcpdump -nn -i any udp port 53
# See HTTP requests in plain text (unencrypted HTTP only)
sudo tcpdump -nn -A -s 0 'tcp port 80'
# Are pings arriving? (troubleshoot firewalls)
sudo tcpdump -nn -i eth0 icmp
# See who is connecting to SSH
sudo tcpdump -nn -i eth0 'tcp dst port 22 and tcp[tcpflags] & tcp-syn != 0'
# Show DHCP exchanges
sudo tcpdump -nn -i eth0 -vv 'port 67 or port 68'
# Watch ARP on the LAN
sudo tcpdump -nn -i eth0 arp
# Top talkers (source IPs) from a live sample
sudo tcpdump -nn -i eth0 -c 1000 | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn | head
# Capture everything except your own SSH session
sudo tcpdump -nn -i eth0 'not port 22'
# Capture from a remote machine and view it locally in Wireshark
ssh user@server 'sudo tcpdump -nn -U -s 0 -i eth0 -w - not port 22' | wireshark -k -i -
# Look for connection resets
sudo tcpdump -nn -i eth0 'tcp[tcpflags] & tcp-rst != 0'
# Count packets per second
sudo tcpdump -nn -i eth0 -tt | awk '{print int($1)}' | uniq -c
Permissions and safety
sudo setcap cap_net_raw,cap_net_admin=eip /usr/bin/tcpdump # allow non-root capture (use carefully)
Capture files can hold credentials and private data. Store them securely and delete them
when finished. Avoid capturing on shared or production networks without permission.
Common problems
"You don't have permission to capture" Use sudo, or grant capabilities
"No such device exists" Wrong interface name: sudo tcpdump -D or ip -br link
Nothing shows up Wrong interface, wrong filter, or the traffic never arrives
Output is a wall of text Add -nn, a filter, and -c to limit it
"packets dropped by kernel" Too much traffic: write with -w, use a tighter filter, raise -B
Cannot read HTTPS payload It is encrypted. tcpdump shows the packets, not the content
Only see your own SSH traffic Add "not port 22" to hide it
Hostnames slow it down Use -n or -nn so it does not do DNS lookups
Tips
Always use -nn while troubleshooting. DNS lookups slow the output and can create their own traffic.
Filter as tightly as you can. Capturing everything on a busy link loses packets.
Use -w to save a capture and analyze it later in Wireshark. Do not squint at a scrolling terminal.
Watching the TCP handshake ([S], [S.], [.]) tells you quickly whether a service is reachable, blocked, or silent.
Use -i any to find which interface traffic uses, then switch to the specific one.
Exclude your own SSH session (not port 22) so your capture does not record itself.
Encrypted traffic (HTTPS, SSH) shows only headers and sizes. That is still enough to prove a connection exists.
Only capture traffic you are authorized to monitor, and protect the files you create.