tcpdump
Linux tcpdump — Complete Learning Notes & Output Guide
tcpdumpis the premier command-line packet analyzer for Linux and Unix-like systems. Powered by thelibpcaplibrary, it captures, filters, and decodes raw network frames from Layer 2 (Data Link) through Layer 7 (Application) directly at the kernel network interface boundary using in-kernel Berkeley Packet Filters (BPF).
1. What is tcpdump?
tcpdump attaches to network interfaces via Linux AF_PACKET raw sockets. When packets traverse the network device driver, the kernel's BPF engine evaluates filtering expressions immediately—copying only matching packets to user space while discarding non-matching frames with minimal overhead.
It answers critical networking and infrastructure questions:
- Are packets physically arriving at the host interface, or are they being blocked upstream?
- Why is a TCP 3-way handshake failing (e.g., silent drops vs. active
RSTrejections)? - What is the exact payload, latency, and status code of DNS, DHCP, or ICMP traffic?
- Is traffic failing due to Path MTU Discovery (PMTUD) black holes or packet fragmentation?
- Which client IP is generating connection floods or malformed headers?
2. Installation & Availability
tcpdump is available across standard distribution package repositories:
Debian / Ubuntu
sudo apt update
sudo apt install tcpdump
RHEL / Rocky / AlmaLinux / CentOS
sudo dnf install tcpdump
Arch Linux
sudo pacman -S tcpdump
Verify installation:
tcpdump --version
3. Basic Syntax & Core Option Flags
sudo tcpdump [options] [BPF_filter_expression]
Essential Command Flags
| Flag | Purpose | Operational Significance |
|---|---|---|
-i <iface> |
Listen on a specific interface (e.g., eth0, lo, any). |
any captures traffic across all active interfaces simultaneously. |
-n |
Do not resolve host addresses to domain names. | Prevents DNS latency and extra network traffic during capture. |
-nn |
Do not resolve host addresses or port names (e.g., :80 instead of http). |
Mandatory in production to avoid reverse-DNS lookup delays. |
**-v / -vv / -vvv** |
Increase output verbosity (decodes IP TTL, ID, options, TCP flags). | -vv prints full protocol headers and options. |
-c <count> |
Exit after capturing $N$ matching packets. | Prevents runaway terminal scrolling and buffer saturation. |
-s <snaplen> |
Packet capture slice length in bytes (-s 0 captures full packet). |
Modern tcpdump defaults to 262144 bytes (full frame). |
-w <file.pcap> |
Write raw packet data to a file instead of parsing to stdout. | Produces standard PCAP files viewable in Wireshark. |
-r <file.pcap> |
Read and parse packets from a saved PCAP file. | Allows offline analysis with different BPF filters. |
-e |
Print Layer 2 link-level headers (source/destination MAC addresses, VLAN tags). | Essential for debugging ARP, VLAN trunking, and L2 switches. |
**-X / -XX** |
Print packet payload in both Hex and ASCII (-XX includes link header). |
Inspects unencrypted application payloads (HTTP, DNS, SMTP). |
-S |
Print absolute TCP sequence numbers instead of relative numbers. | Necessary for correlating packet traces with application logs. |
-q |
Quiet/Quick output; prints brief protocol information. | Reduces line length on high-volume traffic streams. |
-tttt |
Print timestamps in human-readable YYYY-MM-DD HH:MM:SS.frac format. |
Critical for correlating packet captures with system logs. |
Standard Production Command Recipes
# 1. Capture live traffic without DNS/port resolution on eth0
sudo tcpdump -nn -i eth0
# 2. Capture full packets on port 443 with human-readable timestamps
sudo tcpdump -nn -tttt -i eth0 port 443
# 3. Capture all traffic across all interfaces and write to a PCAP file
sudo tcpdump -nn -i any -s 0 -w /tmp/capture.pcap
# 4. Inspect raw packet payloads (Hex + ASCII) for port 80
sudo tcpdump -nn -X -i eth0 port 80
4. Anatomy of Default TCP Output
Capturing a standard TCP connection flow with -nn:
sudo tcpdump -nn -i eth0 port 5432
Raw Output Example (TCP Data Transfer)
07:22:15.102345 IP 192.168.1.50.54210 > 10.0.0.5.5432: Flags [P.], seq 1420:1870, ack 8912, win 502, options [nop,nop,TS val 1420512 ecr 8912401], length 450
07:22:15.103120 IP 10.0.0.5.5432 > 192.168.1.50.54210: Flags [.], ack 1870, win 1024, options [nop,nop,TS val 8912410 ecr 1420512], length 0
5. Breakdown of Every Output Heading & Field
+--------------+----+--------------------+---+--------------------+------------+----------------+----------+---------+--------------------+------------+
| Timestamp | Net| Source IP.Port | > | Destination IP.Port| Flags | Sequence Range | Ack Num | Window | TCP Options | Payload Len|
+--------------+----+--------------------+---+--------------------+------------+----------------+----------+---------+--------------------+------------+
| 07:22:15.102 | IP | 192.168.1.50.54210 | > | 10.0.0.5.5432 | Flags [P.] | seq 1420:1870 | ack 8912 | win 502 | options [nop,...] | length 450 |
+--------------+----+--------------------+---+--------------------+------------+----------------+----------+---------+--------------------+------------+
5.1 Timestamp (07:22:15.102345)
- Format:
HH:MM:SS.frac(microsecond or nanosecond resolution). - Meaning: The exact time the kernel network subsystem timestamped the packet upon driver receipt or transmit enqueue.
5.2 Network Protocol (IP)
- Values:
IP(IPv4),IP6(IPv6),ARP,RARP.
5.3 Source & Destination (192.168.1.50.54210 > 10.0.0.5.5432)
- Format:
<Source_IP>.<Source_Port> > <Dest_IP>.<Dest_Port> - Meaning: Direction of frame transit indicated by the
>arrow. In this case, client ephemeral port54210is sending data to PostgreSQL port5432.
5.4 Flags [P.] (TCP Control Flags)
TCP header control bits are enclosed inside square brackets:
| Flag Symbol | TCP Flag Name | Meaning & Diagnostic Role |
|---|---|---|
[S] |
SYN | Connection synchronization request (first step of 3-way handshake). |
[S.] |
SYN-ACK | Server acknowledgment and reciprocal sync (second step of handshake). |
[.] |
ACK | Acknowledgment packet carrying no control flags. |
**[P] / [P.]** |
PUSH | Push flag set; instruct the receiving OS to push data to the application immediately. |
**[F] / [F.]** |
FIN | Clean connection teardown initiation from the sender. |
**[R] / [R.]** |
RST | Connection reset; packet rejected, port closed, or connection abruptly aborted. |
[U] |
URG | Urgent pointer field is significant. |
[E] |
ECE | ECN-Echo (Explicit Congestion Notification). |
[W] |
CWR | Congestion Window Reduced. |
5.5 seq 1420:1870 (Sequence Number Range)
- Format:
first_byte_seq:last_byte_seq - Meaning: Byte offset indexes within the TCP stream.
1420:1870means this packet carries 450 bytes of payload starting at byte 1420 up to byte 1869. - Relative vs. Absolute: By default,
tcpdumptracks relative offsets starting at1for readability. Use-Sto view the raw 32-bit random hardware sequence numbers.
5.6 ack 8912 (Acknowledgment Number)
- Meaning: The next expected sequence number the sender expects to receive from the remote peer. Confirms all bytes up to
8911have been received.
5.7 win 502 (TCP Window Size)
- Meaning: The current receive window buffer space (in bytes or window-scaled units) available on the sender.
- Troubleshooting Significance: If this drops to
win 0(ZeroWindow), the host is out of socket buffer memory and cannot accept more data, halting transmission.
5.8 options [...] (TCP Options)
nop: No-Operation (padding to align headers on 32-bit/4-byte boundaries).TS val ... ecr ...: TCP Timestamps:valis the sender timestamp;ecr(echo reply) is the latest timestamp received from the remote peer (used to calculate Round Trip Time).mss <size>: Maximum Segment Size announced during the SYN handshake.sackOK: Selective Acknowledgment supported.wscale <factor>: Window scale multiplier.
5.9 length 450 (Payload Length)
- Meaning: The size of the Layer 4 application payload in bytes (excluding IP and TCP header overhead). A pure ACK packet has
length 0.
6. Anatomy of UDP, ICMP, & ARP Output
UDP DNS Query Example
07:30:01.124510 IP 192.168.1.50.48912 > 1.1.1.1.53: 45210+ A? api.github.com. (32)
07:30:01.145120 IP 1.1.1.1.53 > 192.168.1.50.48912: 45210 1/0/0 A 140.82.121.4 (48)
45210+: DNS Transaction ID. The+indicates the Recursion Desired flag is set.A? api.github.com.: Record type requested (AIPv4 record) and the queried FQDN.1/0/0: Number of Answer records (1), Authority records (0), and Additional records (0).A 140.82.121.4: The resolved IP returned by the nameserver.
ICMP Ping & Unreachable Example
07:31:05.102340 IP 192.168.1.50 > 8.8.8.8: ICMP echo request, id 1420, seq 1, length 64
07:31:05.118940 IP 8.8.8.8 > 192.168.1.50: ICMP echo reply, id 1420, seq 1, length 64
07:31:06.102450 IP 192.168.1.1 > 192.168.1.50: ICMP 10.200.1.5 unreachable - host unreachable, length 36
- Shows ICMP types (
echo request,echo reply,destination unreachable).
Layer 2 ARP Request/Reply Example (-e)
07:32:00.102450 52:54:00:12:34:56 > ff:ff:ff:ff:ff:ff, ethertype ARP (0x0806), length 42: Request who-has 192.168.1.1 tell 192.168.1.50, length 28
07:32:00.103110 00:1c:73:a1:b2:00 > 52:54:00:12:34:56, ethertype ARP (0x0806), length 60: Reply 192.168.1.1 is-at 00:1c:73:a1:b2:00, length 46
- Shows hardware source and destination MACs, EtherType (
0x0806), and the IP-to-MAC resolution handshake.
7. BPF (Berkeley Packet Filter) Expressions Cheat Sheet
BPF expressions filter traffic in the kernel before copying data to user space.
sudo tcpdump [options] '<expression>'
1. Primitive Qualifiers
| Qualifier Type | Keywords | Examples |
|---|---|---|
| Type | host, net, port, portrange |
host 192.168.1.1, net 10.0.0.0/16, port 443, portrange 8000-8080 |
| Direction | src, dst, src or dst, src and dst |
src host 10.0.0.5, dst port 53 |
| Protocol | ip, ip6, arp, ether, tcp, udp, icmp |
ip proto \tcp, ether proto 0x8100 (VLAN) |
2. Logical Operators
- Concatenation:
and(or&&) - Alternation:
or(or||) - Negation:
not(or!)
# Capture traffic between host A and host B excluding SSH
sudo tcpdump -nn host 192.168.1.50 and host 10.0.0.5 and not port 22
3. Advanced Byte-Level BPF Slicing
You can inspect raw packet header offsets using proto[offset:size]:
# Capture only TCP SYN packets (Flags byte at offset 13; SYN bit is 0x02)
sudo tcpdump -nn "tcp[tcpflags] & (tcp-syn) != 0 and tcp[tcpflags] & (tcp-ack) == 0"
# Capture only TCP RST packets
sudo tcpdump -nn "tcp[tcpflags] & (tcp-rst) != 0"
# Capture ICMP Destination Unreachable packets (ICMP Type byte at offset 0 == 3)
sudo tcpdump -nn "icmp[0] == 3"
# Capture IP packets with TTL <= 5 (Traceroute packets)
sudo tcpdump -nn "ip[8] <= 5"
8. PCAP Capture, Buffer Handling, & Ring Rotation
On high-throughput production servers, capturing to a single continuous file can fill the filesystem or crash user space due to memory consumption. Use ring buffer rotation:
sudo tcpdump -nn -i eth0 -s 0 -w /var/log/capture_%Y-%m-%d_%H:%M:%S.pcap \
-G 3600 \
-C 500 \
-W 10
Flags Explained:
-w <template>: Destination path. Acceptsstrftimeformat codes when-Gis enabled.-G 3600: Rotate the capture file every 3600 seconds (1 hour).-C 500: Rotate the file if it reaches 500 Megabytes ($500 \times 10^6$ bytes) before the time interval expires.-W 10: Maintain a rolling window of at most 10 files, deleting the oldest upon the 11th rotation.
9. Real-World Troubleshooting Scenarios
Scenario A: Diagnosing Handshake Rejections (Connection Refused)
A microservice logs Connection refused when connecting to 10.0.0.5:5432.
Capture the handshake attempt:
sudo tcpdump -nn -i any host 10.0.0.5 and port 5432
Output:
14:10:01.100120 IP 192.168.1.50.41200 > 10.0.0.5.5432: Flags [S], seq 104250, win 64240, length 0
14:10:01.100450 IP 10.0.0.5.5432 > 192.168.1.50.41200: Flags [R.], seq 0, ack 104251, win 0, length 0
Diagnosis:
- The client sent a
SYN(Flags [S]). - The server responded immediately with
RST-ACK(Flags [R.]). - Root Cause: The target server is reachable, and intermediate firewalls are permitting traffic; however, no process is listening on port 5432 on the destination host, or the database service crashed.
Scenario B: Diagnosing Path MTU Discovery Black Holes
Users can load small web pages, but downloading large files or completing TLS handshakes hangs indefinitely.
Trace ICMP Fragmentation Needed messages:
sudo tcpdump -nn -i eth0 "icmp[0] == 3 and icmp[1] == 4"
Or inspect outgoing DF (Don't Fragment) packets:
sudo tcpdump -nnvv -i eth0 "ip[6] & 0x40 != 0"
Output:
15:02:12.102340 IP 192.168.1.1 > 192.168.1.50: ICMP 10.0.0.5 unreachable - need to frag (mtu 1420), length 556
Diagnosis: An intermediate VPN tunnel or overlay network has an MTU of 1420 bytes. The sender is transmitting 1500-byte frames with the DF (Don't Fragment) bit set. The intermediate router drops the frame and emits an ICMP "need to frag" message. If an aggressive upstream firewall blocks this ICMP message, the connection suffers a PMTUD Black Hole and hangs.
Scenario C: Investigating Packet Drops by tcpdump vs. Kernel
When stopping tcpdump with Ctrl-C, it prints an exit summary:
^C
125042 packets captured
125042 packets received by filter
14210 packets dropped by kernel
Breakdown of the 3 Counters:
packets captured: Total packets processed and emitted to stdout or written to the PCAP file.packets received by filter: Total packets that matched the BPF filter expression and were queued for user space.packets dropped by kernel: Packet loss in the capture pipeline. The packets matched the filter, but the kernel socket buffer allocated totcpdump(AF_PACKETsocket ring buffer) overflowed beforetcpdumpcould read them into user space.
How to Prevent Drops by Kernel:
- Increase the socket receive buffer size with
-B:
sudo tcpdump -i eth0 -B 4096 -w /tmp/large.pcap
(-B 4096 allocates a 4 MB buffer instead of the default 2 MB).
2. Avoid decoding packets to stdout (use -w to write directly to a fast NVMe/tmpfs volume).
3. Do not run packet dissection flags (-X, -vv) on live traffic processing tens of thousands of packets per second.
10. Important Interview Questions & Answers
Q: How does Berkeley Packet Filter (BPF) prevent performance degradation when filtering traffic on high-throughput interfaces?
Answer: BPF runs inside the Linux kernel execution context. When a network driver receives a packet, the BPF bytecode program is evaluated directly in-kernel via the JIT (Just-In-Time) compiler against the packet descriptor. If the packet does not match the expression (e.g., traffic is port 80, but filter specifies port 443), the kernel immediately discards the frame from the capture path. The packet is never copied across the kernel-user space memory boundary into tcpdump's socket buffer, avoiding costly context switches and memory copies.
Q: Why does tcpdump sometimes display outgoing TCP packets with lengths of 16KB to 64KB, exceeding the physical interface MTU (1500 bytes)?
Answer: This occurs because of TCP Segmentation Offload (TSO) or Generic Segmentation Offload (GSO). To conserve host CPU cycles, the Linux network stack constructs large multi-segment buffers (up to 64 KB) and hands them directly to the physical Network Interface Card (NIC). The NIC hardware ASIC is responsible for slicing the large segment into standard 1500-byte wire frames. Because tcpdump captures outgoing packets via an AF_PACKET socket before the buffer reaches the NIC hardware driver, it sees the unsegmented 64 KB memory buffer.
Q: What is Promiscuous Mode, and does tcpdump always enable it?
Answer: By default, a NIC only passes frames to the OS if the destination MAC matches the interface's own MAC, the broadcast MAC (ff:ff:ff:ff:ff:ff), or a joined multicast group. Promiscuous Mode instructs the physical NIC controller to disable hardware MAC filtering, passing all frames observed on the physical medium up to the operating system. tcpdump enables promiscuous mode by default upon launch and disables it upon termination. You can explicitly prevent this using the -p flag (tcpdump -p -i eth0), which is necessary when capturing on heavily loaded shared ports to avoid capturing neighbors' unicast traffic.