Networking & Diagnostics11 min read

    How to install and use tcpdump?

    By AmirReliability & Network Engineering
    Share

    tcpdump is a command-line packet analyzer built on top of libpcap. It captures the raw packets that pass through a network interface and prints them — or writes them to a .pcap file — so you can answer questions like "is my server actually receiving this request?", "which side closed the connection?", or "why is TLS failing on port 443?".

    It is small, scriptable, available on every modern Unix, and the standard tool reached for whenever a higher-level diagnostic (curl, ping, application logs) does not give a clear answer.

    This guide walks through installation on Linux, macOS, and Windows, the flags you will actually use day-to-day, the BPF filter syntax, and a handful of recipes for common server-side investigations.


    Installation

    Debian / Ubuntu

    sudo apt update
    sudo apt install -y tcpdump
    

    RHEL / CentOS / AlmaLinux / Rocky / Fedora

    # RHEL 8/9, AlmaLinux, Rocky, Fedora
    sudo dnf install -y tcpdump
    
    # Older CentOS / RHEL 7
    sudo yum install -y tcpdump
    

    Arch Linux

    sudo pacman -S tcpdump
    

    Alpine

    sudo apk add tcpdump
    

    Verify the install

    tcpdump --version
    

    You should see the tcpdump and libpcap versions printed.

    macOS

    macOS ships tcpdump out of the box, but the bundled version trails upstream. To get the latest release, install via Homebrew:

    brew install tcpdump
    

    Then either run /opt/homebrew/bin/tcpdump directly or make sure /opt/homebrew/bin (Apple Silicon) or /usr/local/bin (Intel) is ahead of /usr/sbin in your PATH.

    On macOS you will also need to capture as root (sudo tcpdump …) — the same as on Linux.

    Windows

    tcpdump does not run natively on Windows. You have three realistic options:

    1. Wireshark + tshark (recommended). Install Wireshark, which bundles Npcap (the modern packet-capture driver) and the command-line tool tshark. tshark accepts the same BPF filter syntax as tcpdump and is the closest equivalent on Windows.
      # Capture on the first interface, write to file
      tshark -i 1 -w C:\captures\out.pcapng
      
      # Capture HTTP traffic to/from a specific host
      tshark -i 1 -f "host 10.0.0.5 and tcp port 80"
      
    2. WSL2. Install tcpdump inside an Ubuntu/Debian WSL distribution. Note that in WSL2 you are capturing on the virtualized WSL network adapter, not the Windows host's physical NIC, so this is best for capturing traffic generated by Linux processes inside WSL — not arbitrary Windows traffic.
    3. WinDump (legacy, not recommended). A historical Windows port of tcpdump. The last release dates from 2006 and depends on the deprecated WinPcap driver. Avoid for new work.

    For server-grade capture on Windows, prefer tshark.


    Permissions

    Packet capture requires raw socket access, which on every supported platform means root (or Administrator on Windows).

    On Linux you can grant the binary the necessary capability so an unprivileged user can capture, instead of using sudo everywhere:

    sudo setcap cap_net_raw,cap_net_admin=eip $(which tcpdump)
    

    This is convenient on shared boxes but be aware it broadens who can capture traffic.


    Listing interfaces

    Before capturing, find the interface you want to listen on:

    sudo tcpdump -D
    

    You will see something like:

    1.eth0 [Up, Running]
    2.lo [Up, Running, Loopback]
    3.any (Pseudo-device that captures on all interfaces) [Up, Running]
    

    The pseudo-interface any is useful when you do not yet know which NIC the traffic is on.


    A first capture

    sudo tcpdump -i eth0
    

    That prints every packet seen on eth0 until you press Ctrl+C. On a busy server this is unreadable — almost every real-world invocation adds filters and flags to narrow it down.


    The flags you will actually use

    Flag Meaning
    -i <iface> Interface to listen on. Use any for all interfaces.
    -n Do not resolve IPs to hostnames. Always use this unless you specifically want DNS lookups.
    -nn Also do not resolve port numbers to service names.
    -c <count> Stop after capturing count packets.
    -w <file> Write raw packets to a .pcap file instead of decoding to stdout.
    -r <file> Read packets back from a .pcap file.
    -s <snaplen> Snapshot length per packet. -s 0 means "full packet" (the modern default).
    -v / -vv / -vvv Increase verbosity of the decoded output.
    -A Print packet payload in ASCII. Useful for plain-text protocols (HTTP, SMTP, IMAP).
    -X Print packet payload in hex + ASCII.
    -e Print the link-layer (Ethernet) header, including MAC addresses.
    -tttt Use absolute, human-readable timestamps.
    -q Quick output — one line per packet, less detail.
    -G <secs> Rotate the output file every secs seconds (used with -w).
    -W <count> Limit the number of rotated files (-G/-C).
    -C <MB> Rotate the output file when it reaches MB megabytes.
    -Z <user> Drop privileges to <user> after opening the interface.

    A safe, readable default for most investigations:

    sudo tcpdump -i any -nn -tttt -s 0
    

    BPF filters: the part that matters

    tcpdump accepts a Berkeley Packet Filter (BPF) expression as its last argument. The kernel applies the filter before the packet reaches userspace, so filtering is cheap even on busy interfaces.

    Filter by host

    # Anything to or from 10.0.0.5
    sudo tcpdump -i any -nn host 10.0.0.5
    
    # Only traffic FROM that host
    sudo tcpdump -i any -nn src host 10.0.0.5
    
    # Only traffic TO that host
    sudo tcpdump -i any -nn dst host 10.0.0.5
    

    Filter by port

    # Anything to or from port 443 (TLS)
    sudo tcpdump -i any -nn port 443
    
    # Only HTTP server traffic (incoming requests)
    sudo tcpdump -i any -nn dst port 80
    
    # Port range
    sudo tcpdump -i any -nn portrange 8000-8100
    

    Filter by protocol

    sudo tcpdump -i any -nn icmp           # pings
    sudo tcpdump -i any -nn udp            # all UDP
    sudo tcpdump -i any -nn 'tcp and port 22'   # SSH
    sudo tcpdump -i any -nn arp            # ARP requests/replies
    

    Filter by network

    sudo tcpdump -i any -nn net 10.0.0.0/24
    sudo tcpdump -i any -nn 'src net 192.168.1.0/24 and dst port 443'
    

    Combining with and / or / not

    # DB traffic, but ignore the monitoring agent's IP
    sudo tcpdump -i any -nn 'tcp port 5432 and not host 10.0.0.99'
    
    # DNS in either direction over UDP or TCP
    sudo tcpdump -i any -nn 'port 53 and (udp or tcp)'
    

    Always quote a filter expression when it contains spaces, parentheses, or shell metacharacters.

    TCP flag filters (advanced)

    To catch only TCP SYN packets (handy when a service is silently dropping connections):

    sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-syn != 0 and not tcp[tcpflags] & tcp-ack != 0'
    

    Or only RSTs (often the fingerprint of a misbehaving service or firewall):

    sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0'
    

    Saving and reading captures

    For anything non-trivial, write to a file and analyze later — printing to a terminal can drop packets on a busy host.

    # Capture HTTPS traffic to a customer's IP, full packet, into a file
    sudo tcpdump -i any -nn -s 0 -w /tmp/customer.pcap 'host 203.0.113.10 and tcp port 443'
    

    Read it back without re-capturing:

    tcpdump -nn -r /tmp/customer.pcap
    
    # Or apply an additional filter while reading
    tcpdump -nn -r /tmp/customer.pcap 'src host 203.0.113.10'
    

    Open it in Wireshark on your laptop for a richer view:

    scp server:/tmp/customer.pcap .
    wireshark customer.pcap
    

    Rotating large captures

    For long-running diagnostics, rotate so you do not fill the disk:

    # Rotate every 60 seconds, keep at most 10 files
    sudo tcpdump -i any -nn -s 0 -w /var/log/cap-%Y%m%d-%H%M%S.pcap -G 60 -W 10
    
    # Or rotate by size — every 100 MB, keep 5 files
    sudo tcpdump -i any -nn -s 0 -w /var/log/cap.pcap -C 100 -W 5
    

    %Y%m%d-%H%M%S is a strftime pattern; tcpdump expands it for each rotated file.


    Practical recipes

    Is the server even seeing the request?

    sudo tcpdump -i any -nn 'host 198.51.100.7 and tcp port 443'
    

    If you see SYNs but no SYN/ACK, the firewall or the listening service is dropping them.

    Watch a TLS handshake without the encrypted bits

    sudo tcpdump -i any -nn -X 'tcp port 443' | head -200
    

    You will see ClientHello / ServerHello in the payload header bytes — enough to confirm a handshake is being attempted.

    See raw HTTP requests/responses

    sudo tcpdump -i any -nn -A -s 0 'tcp port 80'
    

    Useful for plain HTTP. Useless for HTTPS — that traffic is encrypted.

    Capture DNS queries from the server

    sudo tcpdump -i any -nn 'port 53'
    

    Combined with -vv you get the queried name and reply for each transaction.

    Confirm an IP is reaching the box on a specific port

    sudo tcpdump -i any -nn -c 20 'src host 198.51.100.7 and dst port 22'
    

    -c 20 stops after 20 matching packets — a quick smoke test.

    Diagnose connection resets

    sudo tcpdump -i any -nn 'tcp[tcpflags] & tcp-rst != 0'
    

    Identifies who is sending RSTs — useful when an application reports "connection reset by peer" but does not say which side.


    Reading the output

    A typical line looks like:

    14:02:11.183204 IP 10.0.0.5.52344 > 10.0.0.10.443: Flags [S], seq 2746183, win 64240, options [mss 1460,sackOK,TS val 1234 ecr 0,nop,wscale 7], length 0
    

    Broken down:

    • 14:02:11.183204 — timestamp.
    • IP 10.0.0.5.52344 > 10.0.0.10.443 — source IP.port to destination IP.port.
    • Flags [S] — TCP flags. S = SYN, . = ACK only, P = PSH, F = FIN, R = RST.
    • seq 2746183 — sequence number.
    • win 64240 — receive window size.
    • length 0 — payload length (0 for a SYN).

    A complete TCP handshake will appear as [S][S.][.], then payload exchange, then [F.] / [F.] / [.] to close (or [R] if it was reset).


    Operational tips

    • Always include -nn. DNS lookups during capture turn a fast, focused trace into a slow, noisy one.
    • Always filter. An unfiltered tcpdump on a production interface can drop packets and adds CPU load. Be specific about hosts/ports.
    • Mind the disk. -w plus a busy interface fills disks quickly. Use -C / -G / -W for long captures.
    • Sensitive data is in there. Capture files contain real payloads — credentials, cookies, PII. Treat .pcap files as production secrets and delete them when done.
    • Drop privileges. tcpdump -Z nobody runs as nobody after opening the socket, limiting damage if the parser ever has a bug.
    • One terminal per filter. When debugging two flows at once, run two tcpdump instances in two terminals with different filters rather than one giant filter — easier to read.
    • Switch to tshark / Wireshark for deep dives. tcpdump is for triage. Once you have a .pcap, Wireshark gives you protocol decoders, flow graphs, and Follow-Stream — far more useful for reading application-level conversations.

    Troubleshooting

    • tcpdump: <iface>: You don't have permission to capture on that device — run with sudo, or grant capabilities once with setcap cap_net_raw,cap_net_admin=eip $(which tcpdump).
    • No packets at all, but you know the server is being hit — you may be on the wrong interface (try -i any), or the traffic is being rerouted through a tunnel/bridge with a different name (ip link show).
    • Lots of unknown or truncated output — your snaplen is too small. Use -s 0.
    • Dropped packets reported on exit — the interface is too busy for live decoding. Switch to -w file.pcap and analyze offline.
    • tcpdump decodes as Unknown for a known protocol — likely a non-standard port. Tell tcpdump explicitly, e.g. tcpdump -i any -nn 'tcp port 8443' -X.

    Summary

    tcpdump is one of the highest-leverage tools a server admin can have on hand. The minimum viable mental model is small:

    1. Pick an interface (-i any if unsure).
    2. Add -nn to suppress name resolution.
    3. Write a BPF filter that narrows to the host/port/protocol you care about.
    4. Either watch live, or -w to a .pcap and open it in Wireshark.

    From there, the recipes above cover most real incidents: confirming a request reaches the box, diagnosing TLS or DNS, hunting RSTs, and snapshotting traffic for offline analysis.