tcpdump is a powerful, lightweight, command-line packet analyzer originally released in 1988 by researchers at the Lawrence Berkeley National Laboratory. It is built on top of libpcap, the same packet capture library that underlies Wireshark and Tshark, and it uses the Berkeley Packet Filter (BPF) language to select which packets to capture at the kernel level, before they are even copied into user space. This makes tcpdump extremely fast and efficient, even under high traffic loads.
Unlike Wireshark and Tshark, tcpdump does not include a full protocol dissection engine covering hundreds of application-layer protocols; instead it focuses on efficient capture and reasonably detailed decoding of common protocols (Ethernet, IP, TCP, UDP, ICMP, ARP, DNS, and more), printing results as concise, single-line-per-packet summaries directly to standard output, or writing raw packets to a .pcap file for later analysis in Wireshark/Tshark. Because it ships by default or is trivially installable on virtually every Unix-like system, tcpdump is often the very first tool reached for when quick traffic visibility is needed — especially on remote servers, embedded devices, or during incident response on a live, possibly compromised host.
In Kali Linux, tcpdump is pre-installed and forms a core part of the network reconnaissance and analysis toolkit.
How to Install
tcpdump ships by default on Kali Linux. To verify or reinstall:
sudo apt update
sudo apt install tcpdump -y
Verify installation and version:
tcpdump --version
Expected output:
tcpdump version 4.99.4
libpcap version 1.10.4 (with TPACKET_V3)
OpenSSL 3.2.1 30 Jan 2024
To allow a non-root user to run tcpdump without sudo:
sudo groupadd pcap
sudo usermod -aG pcap $USER
sudo chgrp pcap /usr/sbin/tcpdump
sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump
Then log out/in for group membership to apply.
Syntax
tcpdump [OPTIONS] [expression]
Where expression is a BPF (Berkeley Packet Filter) filter expression that selects which packets to display/capture. Basic patterns:
tcpdump -i eth0 # Capture on eth0, print summaries
tcpdump -i eth0 -w out.pcap # Capture and save to file
tcpdump -r out.pcap # Read from saved file
tcpdump -i eth0 host 8.8.8.8 # Filter: only traffic to/from 8.8.8.8
tcpdump -i eth0 port 80 and tcp # Filter: only TCP port 80
All Command-Line Options (Kali Linux)
-a Attempt to convert network/broadcast addresses to names
-A Print each packet's payload in ASCII
-b Print AS numbers in BGP packets in ASDOT notation
-B <buffer size> Set the OS capture buffer size (in KiB)
-c <count> Exit after receiving count packets
-C <file size> Rotate the dump file after file size (MB) when using -w
-d Dump the compiled packet-matching code in human-readable form
-dd Dump packet-matching code as a C program fragment
-ddd Dump packet-matching code as decimal numbers
-D Print list of available capture interfaces
-e Print the link-level header on each dump line
-E <algo:secret> Decrypt IPsec ESP packets using specified algorithm/key
-f Print 'foreign' IPv4 addresses numerically
-F <file> Use file as input for the filter expression
-G <seconds> Rotate dump file every N seconds when used with -w
-h, --help Print help and exit
--version Print version and exit
-i <interface> Listen on specified interface ('any' = all interfaces)
-I Put wireless interface in monitor mode
-j <tstamp_type> Set time stamp type
-J List time stamp types supported
-K Don't verify checksums
-l Make stdout line-buffered (useful for piping)
-L List data link types for the interface
-m <module> Load SMI MIB module for SNMP decoding
-M <secret> Use secret for TCP MD5 signature validation
-n Don't convert addresses (host/port) to names
-N Don't print domain qualification of host names
-# Print an optional packet number at start of each line
-O Do not run the packet-matching code optimizer
-p Don't put interface into promiscuous mode
-q Quick output (less protocol information per line)
-Q, --direction Choose direction: in / out / inout
-r <file> Read packets from file
-S Print absolute TCP sequence numbers
-s <snaplen> Snapshot length (bytes captured per packet; 0 = full)
-T <type> Force interpretation as specified type (e.g., rpc, rtp, wb)
-t Don't print a timestamp on each line
-tt Print an unformatted (epoch) timestamp
-ttt Print a delta (microsecond) from previous line
-tttt Print a full date-and-time timestamp
-u Print undecoded NFS handles
-U Force packets to be written to file as soon as captured
-v, -vv, -vvv Increase verbosity of output
-w <file> Write raw packets to file (for later analysis)
-W <count> Limit number of rotated dump files (used with -C/-G)
-x Print each packet's data in hex
-X Print each packet's data in hex and ASCII
-y <datalinktype> Set the data link type
-z <postrotate cmd> Run command after each file rotation (with -C/-G)
-Z <user> Drop privileges to specified user after opening capture
Basic Usage (Expected Output in Bash)
List available interfaces:
tcpdump -D
Output:
1.eth0 [Up, Running]
2.wlan0 [Up, Running, Wireless]
3.lo [Up, Running, Loopback]
4.any (Pseudo-device that captures on all interfaces) [Up, Running]
5.bluetooth0 [Wireless]
6.nflog (Linux netfilter log (NFLOG) interface)
7.nfqueue (Linux netfilter queue (NFQUEUE) interface)
Basic capture (requires root or capabilities):
sudo tcpdump -i eth0
Output:
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:22:41.821034 IP 192.168.1.10.51322 > 93.184.216.34.443: Flags [S], seq 1832910442, win 64240, options [mss 1460,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0
10:22:41.843992 IP 93.184.216.34.443 > 192.168.1.10.51322: Flags [S.], seq 921233, ack 1832910443, win 65535, options [mss 1440,sackOK,TS val 654321 ecr 123456,nop,wscale 8], length 0
^C
2 packets captured
2 packets received by filter
0 packets dropped by kernel
Practical Examples with Output
Example 1: Capture and save 50 packets to a file
sudo tcpdump -i eth0 -c 50 -w capture.pcap
Output:
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
50 packets captured
50 packets received by filter
0 packets dropped by kernel
Example 2: Capture only traffic to/from a specific host
sudo tcpdump -i eth0 host 192.168.1.50
Output:
10:25:10.112233 IP 192.168.1.10.54010 > 192.168.1.50.22: Flags [P.], seq 1:37, ack 1, win 501, length 36
10:25:10.112810 IP 192.168.1.50.22 > 192.168.1.10.54010: Flags [.], ack 37, win 505, length 0
Example 3: Capture only TCP port 22 (SSH) traffic
sudo tcpdump -i eth0 tcp port 22
Output:
10:26:03.771102 IP 192.168.1.10.55123 > 192.168.1.50.22: Flags [S], seq 200201, win 64240, length 0
10:26:03.771523 IP 192.168.1.50.22 > 192.168.1.10.55123: Flags [S.], seq 90211, ack 200202, win 65535, length 0
Example 4: Read from a saved capture and show verbose output
tcpdump -r capture.pcap -v
Output:
reading from file capture.pcap, link-type EN10MB (Ethernet)
10:22:41.821034 IP (tos 0x0, ttl 64, id 21432, offset 0, flags [DF], proto TCP (6), length 60)
192.168.1.10.51322 > 93.184.216.34.443: Flags [S], cksum 0x1a2b (correct), seq 1832910442, win 64240, options [mss 1460,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0
Example 5: Filter with logical operators (exclude SSH, only show HTTP/HTTPS)
sudo tcpdump -i eth0 '(tcp port 80 or tcp port 443) and not port 22'
Output:
10:27:14.552112 IP 192.168.1.10.55210 > 93.184.216.34.443: Flags [S], seq 33221, win 64240, length 0
10:27:14.573889 IP 93.184.216.34.443 > 192.168.1.10.55210: Flags [S.], seq 88123, ack 33222, win 65535, length 0
Example 6: Show hex and ASCII dump of packets (payload inspection)
sudo tcpdump -i eth0 -X port 80 -c 1
Output:
10:28:02.113322 IP 192.168.1.10.55432 > 93.184.216.34.80: Flags [P.], seq 1:80, ack 1, win 501, length 79
0x0000: 4500 006b 1a2c 4000 4006 0000 c0a8 010a E..k.,@.@.......
0x0010: 5db8 d822 d888 0050 12ab 33cc 90ee 12ff ]..".Å..P..3.....
0x0020: 5018 01f5 0a1b 0000 4745 5420 2f20 4854 P.......GET / HT
0x0030: 5450 2f31 2e31 0d0a 486f 7374 3a20 6578 TP/1.1..Host: ex
0x0040: 616d 706c 652e 636f 6d0d 0a0d 0a ample.com....
Example 7: Capture with rotating output files (log rotation for long-term monitoring)
sudo tcpdump -i eth0 -w /var/log/tcpdump/capture.pcap -C 100 -W 10
Output:
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
(writes capture.pcap, capture.pcap1, capture.pcap2 ... rotating every 100MB,
keeping a maximum of 10 files, overwriting oldest)
Example 8: Capture ARP traffic only (detect ARP spoofing attempts)
sudo tcpdump -i eth0 arp
Output:
10:30:11.221011 ARP, Request who-has 192.168.1.1 tell 192.168.1.10, length 28
10:30:11.221532 ARP, Reply 192.168.1.1 is-at aa:bb:cc:dd:ee:ff, length 46
Example 9: Show timestamps with microsecond delta between packets
sudo tcpdump -i eth0 -ttt -c 5
Output:
00:00:00.000000 IP 192.168.1.10.51322 > 93.184.216.34.443: Flags [S], seq 1832910442
00:00:00.021958 IP 93.184.216.34.443 > 192.168.1.10.51322: Flags [S.], seq 921233
00:00:00.001880 IP 192.168.1.10.51322 > 93.184.216.34.443: Flags [.], ack 921234
00:00:00.034221 IP 192.168.1.10.51322 > 93.184.216.34.443: Flags [P.], seq 1:80
00:00:00.023120 IP 93.184.216.34.443 > 192.168.1.10.51322: Flags [.], ack 80
Example 10: Capture on all interfaces simultaneously
sudo tcpdump -i any -c 10
Output:
listening on any, link-type LINUX_SLL (Linux cooked v1), snapshot length 262144 bytes
10:31:00.112233 IP 192.168.1.10.51322 > 93.184.216.34.443: Flags [S], seq 100200
10:31:00.113001 IP6 fe80::1a2b > ff02::1: ICMP6, router advertisement
...
Example 11: Filter by packet length (find large or small packets)
sudo tcpdump -i eth0 greater 1000
Output:
10:32:15.331209 IP 93.184.216.34.443 > 192.168.1.10.51322: Flags [P.], seq 1:1448, ack 80, win 65535, length 1448
Example 12: Drop privileges after opening capture (defense-in-depth)
sudo tcpdump -i eth0 -Z nobody -w /tmp/capture.pcap
Output:
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
(process continues running as user "nobody" instead of root after
the capture socket is opened, reducing privilege-escalation risk)
Common Use Cases
- Quick, dependency-free traffic visibility on any Linux/Unix host, especially during live incident response.
- Capturing traffic on a remote or headless server over SSH, then transferring the resulting
.pcapfor deep analysis in Wireshark. - Long-term, low-overhead network monitoring using rotating capture files.
- Verifying connectivity and routing issues (e.g., confirming SYN packets leave but no SYN-ACK returns).
- Detecting ARP spoofing, DNS tunneling, or unusual protocol usage at a glance.
- Capturing traffic on compromised or suspect hosts as part of forensic evidence collection.
- Filtering traffic at the kernel level (via BPF) for very high-throughput environments where a full GUI tool would be too slow.
Automation with Bash
Continuous rotating capture with a cron-friendly wrapper:
#!/bin/bash
# capture_rotate.sh - continuous capture with size-based rotation
IFACE="eth0"
OUTDIR="/var/log/tcpdump"
mkdir -p "$OUTDIR"
sudo tcpdump -i "$IFACE" -w "${OUTDIR}/cap_%Y%m%d_%H%M%S.pcap" -G 3600 -W 24 -Z "$USER"
Trigger an alert script whenever a rotated file is written, using -z:
#!/bin/bash
# alert_on_rotate.sh - runs after each rotated capture file is closed
FILE="$1"
COUNT=$(tcpdump -r "$FILE" 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' 2>/dev/null | wc -l)
if [ "$COUNT" -gt 500 ]; then
echo "[ALERT] Possible SYN flood detected in $FILE: $COUNT SYN packets" | \
mail -s "tcpdump alert" security-team@example.com
fi
sudo tcpdump -i eth0 -w /var/log/tcpdump/cap.pcap -G 300 -W 12 -z /usr/local/bin/alert_on_rotate.sh
Quick one-liner to extract all unique source IPs seen in a live capture for 30 seconds:
sudo timeout 30 tcpdump -i eth0 -nn -q 2>/dev/null | \
awk '{print $3}' | cut -d. -f1-4 | sort -u > active_ips.txt
echo "[*] Unique source IPs saved to active_ips.txt"
Tips and Best Practices
- Always use
-nnin scripts to disable both host and port name resolution — this avoids slow, blocking DNS lookups during capture and produces consistent, parseable output. - Prefer writing to a file with
-wand analyzing later, rather than trying to eyeball live output for anything beyond a quick sanity check. - Use specific BPF filters (
host,net,port,and/or/not) to minimize captured volume — this reduces both file size and analysis time. - Combine
-s 0(or omit-s, which defaults to full-length capture in modern tcpdump) when you need full payloads for forensic analysis; use a small snaplen only when you only need headers, to save space. - Use
-Z <user>whenever running tcpdump as root, to drop privileges immediately after the capture socket is opened. - Rotate long-running captures with
-C/-Gplus-Wto avoid disks filling up. - Remember that tcpdump filter expressions with special shell characters (parentheses,
!) must be quoted to avoid shell interpretation. - For deep protocol decoding beyond tcpdump’s built-in summaries, save with
-wand open the resulting file in Wireshark/Tshark.
Troubleshooting
Problem: “tcpdump: eth0: You don’t have permission to capture on that device.” Solution: Run with sudo, or configure capabilities: sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump and ensure your user is in the appropriate group.
Problem: No packets captured despite traffic being present. Solution: Confirm the correct interface name with tcpdump -D or ip link show; check that promiscuous mode isn’t blocked by a virtual NIC/hypervisor setting; verify the BPF filter isn’t excluding everything.
Problem: “packets dropped by kernel” reported at end of capture. Solution: Increase the OS capture buffer with -B <KB>, apply a tighter capture filter to reduce load, or write directly to a fast disk with -w instead of printing to a slow terminal.
Problem: Captured file too large to open in Wireshark. Solution: Use rotation options (-C/-G/-W) during capture to keep files manageable, or split existing files after the fact with editcap / tcpdump -r big.pcap -w small.pcap -c N.
Problem: Filter expression causes a syntax error. Solution: Wrap complex expressions (with and/or/not/parentheses) in single quotes so the shell doesn’t interpret them; verify keyword order (tcp port 80 not port tcp 80).
Problem: DNS resolution makes output extremely slow. Solution: Add -n (no host name resolution) or -nn (no host or port resolution).
References
- Official tcpdump/libpcap website: https://www.tcpdump.org/
- tcpdump man page: https://www.tcpdump.org/manpages/tcpdump.1.html
- pcap-filter (BPF syntax) man page: https://www.tcpdump.org/manpages/pcap-filter.7.html
- Kali Linux Tools listing for tcpdump: https://www.kali.org/tools/tcpdump/
- tcpdump GitHub repository: https://github.com/the-tcpdump-group/tcpdump