# tcpdump and tshark: Packet Capture in CLI

LLMS index: [llms.txt](/en/llms.txt)

---

When debugging network issues in Linux infrastructure, `ping` and `curl` are not enough. Sometimes you need to see what is actually traveling over the wire. tcpdump is the standard tool for capturing packets from the CLI. tshark is its sibling from the Wireshark suite, convenient for scripting.

## Quick Start with tcpdump

Check that packets are reaching the host:

```bash
tcpdump -i eth0 host 10.0.0.5
```

The utility puts the interface into promiscuous mode and prints one line per packet passing through. By default it works with the first interface it finds, but specifying explicitly is better.

For a quick test without DNS resolution (to avoid timeout when there is no network):

```bash
tcpdump -i eth0 -nn host 10.0.0.5
```

`-nn` prevents resolving both hostnames and ports.

## Key Flags

| Flag | Purpose |
|------|---------|
| `-i iface` | Interface |
| `-c N` | Capture N packets and exit |
| `-n` | Do not resolve hostnames |
| `-nn` | Do not resolve hostnames and ports |
| `-v`, `-vv`, `-vvv` | Increase output verbosity |
| `-w file` | Write raw dump to file (pcap) |
| `-r file` | Read dump from file |
| `-X` | Show hex + ASCII packet body |
| `-s N` | Truncate each packet to N bytes (0 = full) |
| `-C` | Rotate output file when it reaches N MB |

The `-v` flags are useful for debugging: the first level shows TTL and ID, the second shows flags and window size, the third adds ACK and displays the full IP header.

```bash
# Capture 100 packets on port 443, verbosity -vv
tcpdump -i eth0 -nn -c 100 -vv port 443
```

## BPF Filters

tcpdump uses Berkeley Packet Filter. The syntax reads left to right.

```bash
# TCP only on port 80 or 443
tcpdump -i eth0 -nn tcp port 80 or port 443

# Host as source OR destination
tcpdump -i eth0 -nn host 192.168.1.10

# Do not show SSH (cut the noise)
tcpdump -i eth0 -nn not port 22

# TCP packets with SYN flag (connection start)
tcpdump -i eth0 -nn 'tcp[tcpflags] == tcp-syn'

# Packets larger than 1000 bytes
tcpdump -i eth0 -nn 'ip[2:2] > 1000'

# ICMP ping (type 8 code 0)
tcpdump -i eth0 -nn 'icmp[icmptype] == 8'
```

Filters combine with `and`, `or`, `not`. Quotes are needed when the expression contains spaces or special characters.

> [!WARNING]
> Do not run `tcpdump -i any` in production without restricting by host or port. You will get a flood of traffic and waste disk space for no reason.

## Writing to File and Reading

Capturing to a file is mandatory practice. A live sniffer dumps data dozens of lines per second; analyzing in the terminal is impossible.

```bash
# Write 10,000 packets to a file
tcpdump -i eth0 -nn -w /tmp/capture.pcap -c 10000

# Read from file (interactive)
tcpdump -r /tmp/capture.pcap

# Read with a filter
tcpdump -r /tmp/capture.pcap -nn 'tcp port 443'
```

The pcap format is binary. The `-C` option limits file size:

```bash
tcpdump -i eth0 -nn -w /tmp/capture -C 10 -W 5
```

This creates files `/tmp/capture-0`, `/tmp/capture-1` ... up to 5 files, each up to 10 MB. `-W` sets the number of files.

## tshark as a tty-free Alternative

tshark is the command-line part of Wireshark. It produces structured output convenient for parsing in scripts:

```bash
# Installation
apt install tshark   # Debian/Ubuntu
yum install wireshark-cli   # RHEL/CentOS

# Capture with field output
tshark -i eth0 -f 'host 10.0.0.5' -c 100 -T fields -e ip.src -e ip.dst -e tcp.port
```

`-T fields -e` extracts specific fields from each packet:

```bash
# HTTP requests: method and host
tshark -i eth0 'tcp port 80' -Y http.request -T fields -e http.host -e http.request.method -e http.request.uri
```

Reading pcap files with tshark is more convenient than with tcpdump:

```bash
# Show protocol hierarchy statistics
tshark -r /tmp/capture.pcap -z io,phs -q
```

tshark does not support `-C` rotation like tcpdump, but it handles live filters better (full Wireshark dissector engine).

## Reading Dumps in Wireshark

A pcap created by tcpdump opens in Wireshark without conversion:

```bash
# Transfer file to local machine
scp user@server:/tmp/capture.pcap /tmp/

# Or start a web server on the remote host
python3 -m http.server 8080 --directory /tmp
```

In Wireshark Apply as display filter you enter the same BPF syntax: `tcp.port == 443 && ip.src == 10.0.0.1`.

> [!TIP]
> If the file is large (>100 MB), do not open it entirely. Use `tcpdump -r` with a pre-filter to extract the needed slice: `tcpdump -r big.pcap -nn 'host 10.0.0.5' -w small.pcap`.

## Common Mistakes

- Forgot `-c` — the process hangs, capturing traffic indefinitely. Add the limit immediately.
- No permissions — you need root or `sudo tcpdump`. In modern distributions you can grant capabilities: `setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump`.
- `-w` does not work with `-l` (line-buffering) simultaneously. If you need progress — write to file and read in parallel via `tail -f`.
- File was written but reads empty — possibly there was no traffic matching the filter. Check `tcpdump -i eth0 -nn` without a filter.
