tcpdump: A packet capture tool for network traffic analysis

tcpdump: A packet capture tool for network traffic analysis

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

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

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

Exit mobile version