Network analysis is one of those skills that looks simple from the outside and keeps revealing new depth the longer you work with it. You can spend an afternoon learning the basics of tcpdump and still be discovering useful filter combinations three years later. That’s the nature of it. The tools covered in this guide – ifconfig, netstat, ss, tcpdump, and Wireshark are not beginner placeholders you graduate away from. They are the actual production tools that network engineers, incident responders, and penetration testers use every day in real environments.

This guide goes beyond the command syntax. It explains the underlying mechanics: why promiscuous mode matters at the hardware level, how Berkeley Packet Filter bytecode works, why Wireshark’s display filter language is fundamentally different from tcpdump‘s capture filter syntax, and how to read what these tools actually show you. If your goal is to understand what is happening on a network, not just run command, you’re in the right place.

What’s Network Analysis

At its core, network analysis means intercepting data in transit across a digital network and making sense of it. This covers everything from checking whether a remote host is alive, to reconstructing the full session data from a TCP stream, to identifying C2 beacon patterns in encrypted traffic through timing analysis.

The tools divide roughly into two categories. Passive tools such as sniffers and protocol analyzers capture traffic without injecting anything onto the wire. Active tools such as ping, traceroute, nmap send packets and analyze the responses. Most real investigations use both. You might use ping to confirm a host is up, netstat to see what local connections already exist, then tcpdump or Wireshark to capture and decode the actual traffic flow.

Active vs Passive
Active vs Passive

Security professionals use network analysis for several overlapping purposes: troubleshooting connectivity problems, detecting malware by its network behavior, reconstructing attack chains from packet captures, and baselining what normal traffic looks like so anomalies become visible. Each of these is a different use case with different filtering strategies, but the underlying toolset is the same.

Command-Line Network Analysis Tools

ifconfig / ip

ifconfig (interface configuration) is the classic command for viewing and configuring network interfaces on Linux and Unix systems. On Kali Linux:

kali > ifconfig

The output gives you everything you need to understand an interface at a glance: the IPv4 address (inet), the subnet mask (netmask), the broadcast address, the IPv6 address (inet6), and the MAC address (ether). You also see the loopback interface (lo) at 127.0.0.1, which is the system talking to itself.

Worth knowing: ifconfig is technically deprecated on most modern Linux distributions. It is part of the net-tools package, which is no longer maintained and was removed from default installs on Debian, Ubuntu, RHEL 8+, and others. The modern equivalent is the ip command from the iproute2 package:

# Show all interfaces (equivalent to ifconfig -a)
ip addr show
# Show a specific interface
ip addr show dev eth0
# Show link-layer information
ip link show

The ip command is more consistent, supports newer networking features (namespaces, VLANs, tunnels), and is faster because it queries the kernel through NETLINK rather than parsing /proc filesystem text files. That said, ifconfig is still available on most penetration testing distributions and many embedded or legacy systems, so knowing both matters.

ping and ICMP

ping is the first diagnostic most people reach for when something isn’t working. It sends ICMP Echo Request packets to a target and waits for ICMP Echo Reply responses:

kali > ping thecybersecguru.com
# Or by IP address directly, which skips the DNS lookup
kali > ping 192.0.78.156

The output tells you round-trip time (RTT) for each packet, whether packets are being dropped, and the target’s IP address (if you pinged by hostname). What ping actually proves is that ICMP traffic can reach the target and return to you, not that any services are running, not that TCP is open, and not that the host isn’t running a firewall that blocks ICMP while allowing everything else.

Some hardened servers and firewalls drop ICMP altogether. A failed ping does not mean the host is down. It means ICMP is filtered. This distinction matters in penetration testing – a host that does not respond to ping may still have open web, SSH, or RDP ports.

# Set a specific count so ping doesn't run forever
kali > ping -c 4 192.168.50.50
# Flood ping (requires root) - useful for testing packet loss
kali > ping -f 192.168.50.50

netstat

netstat (network statistics) is a command-line tool that shows network connections, routing tables, interface statistics, and more. Despite being deprecated, it is still widely installed and muscle-memorized by a generation of engineers, so it stays relevant.

# Show all connections (listening and established)
kali > netstat -a
# Show only TCP connections
kali > netstat -at
# Show only UDP connections
kali > netstat -au
# Show only listening connections
kali > netstat -l
# Show with process names and PIDs (requires root for other users' processes)
kali > netstat -anp
# Numeric output - skip DNS resolution, much faster
kali > netstat -an

The output columns to understand: Proto is the protocol (tcp, udp), Local Address is the socket on your machine, Foreign Address is the remote socket, and State is the TCP connection state: LISTEN (waiting for incoming connections), ESTABLISHED (active connection), TIME_WAIT (recently closed, waiting for stale packets to clear), CLOSE_WAIT (remote side closed, local side hasn’t yet), and others.

Security use case: piping netstat to grep to find unexpected connections. If something is beaconing out to an unknown IP on port 443, netstat -anp will show you the PID and process name.

# Find if Apache is listening
kali > netstat -a | grep http
# Find all established connections to a suspicious IP
kali > netstat -an | grep 192.168.1.200
# Find processes listening on port 4444 (a common reverse shell port)
kali > netstat -anp | grep :4444

ss (Socket Statistics)

ss is the modern replacement for netstat, part of the iproute2 package. It queries the kernel directly through the NETLINK socket interface rather than parsing /proc/net/ text files, which makes it significantly faster – especially on servers with thousands of open connections where netstat can take several seconds while ss returns results almost instantly.

# Show all connections
ss -a
# Show TCP connections only, with process info
sudo ss -tnp
# Show listening sockets only
ss -l
# Show UDP sockets
ss -u
# Show sockets in ESTABLISHED state
ss -t state established
# Filter to a specific port
ss -tnp sport = :22

The output format differs slightly from netstat. ss shows Recv-Q and Send-Q (receive and send queue depths), which netstat also shows but in less granular form. When Recv-Q is consistently nonzero on an ESTABLISHED connection, the application is not reading fast enough. When Send-Q is high, the remote end is not acknowledging fast enough. These queue values are genuinely useful for diagnosing slow-but-connected services.

The ss -p flag includes the process name and PID in parentheses next to each socket, like users:(("nginx",pid=2145,fd=6)), which gives you both the process name and the file descriptor number – more detail than netstat.

Practical note: netstat is not going away tomorrow. It is still installed on many systems, still taught in certifications, and still functional. But if you are writing new scripts or working on a system where speed matters, learn ss. It is actively maintained and will still be there when net-tools is fully retired.

Network Sniffers

A network sniffer (sometimes called a packet analyzer, protocol analyzer, or packet capture tool) intercepts and records the raw packets traversing a network interface. The captured data includes every layer of the packet: link layer (Ethernet frames), network layer (IP headers), transport layer (TCP/UDP), and the application payload.

The range of tools capable of sniffing is wide: SolarWinds Deep Packet Inspection, tcpdump, WinDump, Wireshark, NetworkMiner, Capsa, tshark, Zeek, and more. This guide focuses on tcpdump for command-line work and Wireshark for GUI-based analysis, which together cover the overwhelming majority of real-world packet analysis work.

Promiscuous Mode Explained

Here is a detail that trips people up: a standard network interface card (NIC) in normal operation only delivers to the host the packets addressed to that NIC’s MAC address (plus broadcast and multicast packets). Everything else – traffic between other hosts on the same network segment – gets ignored at the hardware level.

For effective sniffing, the NIC needs to operate in promiscuous mode, where it passes every frame it receives on the wire up to the operating system, regardless of destination MAC address. This is what makes passive sniffing work on shared-media networks (like an unswitched Ethernet segment or a wireless network).

# Enable promiscuous mode manually
ip link set eth0 promisc on
# Verify it is enabled (look for PROMISC in the flags)
ip link show eth0

Both tcpdump and Wireshark enable promiscuous mode automatically by default when they start capturing.

Two important caveats here. First, promiscuous mode is detectable. A host on the same network can probe for promiscuous-mode adapters using specific packet tests. This is relevant for red team engagements where stealth matters. Second, on modern switched networks, a NIC in promiscuous mode only sees traffic from its own switch port anyway (plus broadcast/multicast). To capture all traffic on a switch, you need a SPAN (Switched Port Analyzer) port or mirror port configured on the switch, which forwards copies of all traffic to your capture port. Without that, you only capture your own traffic plus broadcast.

For 802.11 wireless captures, there is a third mode worth knowing: monitor mode (rfmon mode). Promiscuous mode on a wireless interface only captures traffic for the network the adapter is associated with. Monitor mode allows capturing 802.11 management frames, control frames, and traffic from all networks on the current channel – useful for wireless auditing.

The pcap File Format

The standard file format for packet captures is .pcap (Packet Capture), originated by the libpcap project around 1987 as part of the original tcpdump. The format has a straightforward three-layer structure:

Global File Header: A fixed 24-byte header that opens the file. Contains a magic number (which identifies the file type and byte order), the libpcap format version (currently 2.4), the maximum captured packet length (the snapshot length or “snaplen”), and the link-layer type (which tells analysis tools whether to interpret packet data as Ethernet, Wi-Fi, etc.).

Per-Packet Header: For each captured packet, a 16-byte header carrying the timestamp (seconds and microseconds), the captured packet length, and the original packet length. When the captured length is less than the original length, the packet was truncated – useful to know during analysis.

Packet Data: The raw bytes of the packet itself, starting at the link layer as specified in the global header.

The .pcap format is universal. Snort, Suricata, Wireshark, tcpdump, aircrack-ng, and most security tools either read, write, or both for .pcap files. When you save a tcpdump capture with -w output.pcap, that file can be opened directly in Wireshark.

pcap vs pcapng

PCAPng (PCAP Next Generation) is the newer format, now the default in Wireshark. The key differences:

PCAPng supports multiple interfaces in a single capture file (the original .pcap format cannot mix interface types). It supports nanosecond timestamp precision vs. microsecond for classic pcap. It allows user comments and block-level annotations. It includes interface statistics blocks. And it handles the case where you capture on multiple interfaces simultaneously, increasingly common in modern network forensics.

For everyday use, .pcap is fine. For enterprise investigations, multi-interface captures, or situations where you need comment annotations on specific packets, .pcapng is worth using.

libpcap and WinPcap/Npcap

libpcap is the C library that provides the underlying packet capture functionality on Linux and macOS. tcpdump, Wireshark, Snort, and most other Unix-based tools use libpcap under the hood. The library handles putting the interface into promiscuous mode, calling into the kernel’s BPF subsystem to filter packets, and writing the pcap format.

On Windows, the equivalent is Npcap (the actively maintained successor to WinPcap, which was discontinued). Npcap is what Wireshark uses on Windows. Without one of these libraries, no sniffing tool can capture packets at the driver level.

tcpdump In Depth

tcpdump was first released in 1988, written by researchers at Lawrence Berkeley National Laboratory running BSD Unix. It remains the go-to tool for capturing and inspecting network traffic without a graphical interface. This matters more than it sounds: you often do not have GUI access on a remote server, a containerized system, a network appliance, or a system where running a heavyweight GUI would consume too many resources. tcpdump has near-zero overhead.

Start a basic capture:

kali > tcpdump

Packets start streaming immediately – mostly communication between your system and the default gateway, plus any other traffic on the interface. The output format is: timestamp / protocol / source > destination / TCP flags and header info.

To capture against a Windows host at 192.168.0.114, for instance, start a ping from a second terminal:

kali > ping 192.168.50.50

And watch tcpdump show the ICMP echo requests and replies in real time, including the protocol type and whether each packet is an echo request or echo reply.

How BPF Filtering Works Under the Hood

The filter language in tcpdump is BPF (Berkeley Packet Filter). What happens when you write a filter expression like host 192.168.0.114 and port 80 is not simple string matching against packet data. The expression gets compiled into BPF bytecode – a minimalist instruction set that runs directly in the kernel.

This architecture is intentional and important. BPF bytecode runs in a kernel-space virtual machine, which means packet filtering happens before packets cross the user-space boundary. Packets that do not match are discarded in the kernel. Only matching packets get copied to user space for tcpdump to display. This is why tcpdump can keep up with high-bandwidth interfaces without dropping packets, the filter runs as close to the wire as possible.

You can see the compiled BPF bytecode for any filter expression with the -d flag:

kali > tcpdump -d 'host 192.168.0.114 and port 80'

The output shows the BPF assembly instructions: load, jump-if-equal, return match, return drop. This is what the kernel actually executes per packet.

The BPF syntax used by tcpdump (and libpcap generally) is defined in the pcap-filter(7) man page. It is different from Wireshark’s display filter syntax – a confusion that trips up everyone at some point. tcpdump filters are capture filters, they decide what gets captured. Wireshark’s filters are display filters, they decide what gets shown from an already-captured dataset. The syntax is not compatible.

Essential tcpdump Flags

FlagPurpose
-i eth0Capture on a specific interface (default: lowest-numbered)
-nDo not resolve hostnames – prevents slow DNS lookups
-nnDo not resolve hostnames or port names
-vVerbose output – decodes more header fields
-vvVery verbose – decodes all IP and TCP header fields, including user agent
-vvvMaximum verbosity
-APrint packet payload in ASCII
-XPrint packet payload in both hex and ASCII
-ePrint Ethernet MAC addresses
-c 100Stop after capturing 100 packets
-s 0Set snapshot length to unlimited (older versions default to 68 bytes, which truncates payloads)
-w output.capWrite raw packets to file instead of displaying them
-r input.capRead from a previously saved capture file
-lLine-buffered output – useful when piping to grep
-qQuiet/minimal output
-DList all available interfaces
-tSuppress timestamps

For real-world use, a common starting invocation is:

kali > tcpdump -i eth0 -nn -vv -s 0

This captures on eth0, skips DNS resolution, shows verbose headers, and captures full-length packets.

Filtering by IP Address

# Traffic to or from a specific host
kali > tcpdump host 192.168.50.50
# Traffic only FROM a specific host
kali > tcpdump src host 192.168.50.50
# Traffic only TO a specific host
kali > tcpdump dst host 192.168.50.50
# Entire subnet
kali > tcpdump net 192.168.0.0/24

Filtering by host is the most common starting point for any investigation. When you apply a host filter, tcpdump passes only packets where either the source or destination IP matches. You immediately cut out all the noise from other systems on the network.

When you start Apache on the Kali box and browse to it from the Windows host, you should see the three-way TCP handshake in the output. tcpdump represents the SYN flag as S, ACK as a ., and RST as R. So a complete handshake looks like:

SYN: S (client to server)
SYN-ACK: S. (server to client)
ACK: . (client to server)

This is the foundation of every TCP connection. When you do not see S. in response to S, the port is closed or filtered.

Filtering by Port

# Traffic on a specific port (any direction)
kali > tcpdump port 80
# Traffic TO a specific port
kali > tcpdump dst port 80
# Traffic FROM a specific port
kali > tcpdump src port 80
# Very verbose output for HTTP - decodes headers including user agent
kali > tcpdump -vv dst port 80
# Port range
kali > tcpdump portrange 8000-8080

The -vv dst port 80 combination is particularly useful. The very verbose flag causes tcpdump to decode IP and TCP headers and, for HTTP traffic, print the HTTP headers in the output. This lets you see HTTP method, URI, host header, and user agent string – enough to identify the browser and OS of the client.

Filtering by TCP Flags

This is where tcpdump gets genuinely powerful for security work. TCP flags sit at a specific byte offset in the TCP header, and BPF can match against individual bits.

# Only packets with SYN set
kali > tcpdump 'tcp[tcpflags] == tcp-syn'
# SYN set (and possibly other flags too - more permissive)
kali > tcpdump 'tcp[tcpflags] & tcp-syn != 0'
# Pure SYN (SYN set, ACK not set) - identifies new connection attempts
kali > tcpdump 'tcp[13] & 0x12 = 0x02'
# SYN-ACK (both SYN and ACK set) - identifies server responses
kali > tcpdump 'tcp[13] & 0x12 = 0x12'
# RST - identifies rejected connections
kali > tcpdump 'tcp[tcpflags] & tcp-rst != 0'
# FIN - identifies connection teardown
kali > tcpdump 'tcp[tcpflags] & tcp-fin != 0'

The tcp[13] notation is direct byte-offset access into the TCP header. Byte 13 (zero-indexed from the start of the TCP header) contains the TCP flags field. The bit values for each flag:

FlagBit value
FIN0x01
SYN0x02
RST0x04
PSH0x08
ACK0x10
URG0x20

Capturing only pure SYN packets (SYN set, ACK not set) is useful for detecting port scans. A scanner sending SYN packets to a range of ports will show up as a flood of SYN packets from one source IP with no corresponding handshakes completing.

Byte-Offset Filtering

The BPF byte-offset syntax gives you surgical control over what gets captured. The syntax is proto[offset:size], where offset is the byte position within the named protocol header, and size is 1, 2, or 4 bytes.

# Filter by IP TTL less than 10 (many hops used - potential traceroute or TTL-exceeded scenario)
kali > tcpdump 'ip[8] < 10'
# Filter for ICMP echo requests only (type 8)
kali > tcpdump 'icmp[icmptype] = icmp-echo'
# Filter for ICMP echo replies only (type 0)
kali > tcpdump 'icmp[icmptype] = icmp-echoreply'
# Filter by IP protocol number in the IP header (byte 9)
kali > tcpdump 'ip[9] = 6' # TCP
kali > tcpdump 'ip[9] = 17' # UDP
kali > tcpdump 'ip[9] = 1' # ICMP
kali > tcpdump 'ip[9] = 50' # ESP (encrypted VPN traffic)

This level of specificity matters in incident response. If you are hunting for specific malware that uses unusual IP header values (TTL manipulation, specific protocol fields), byte-offset filtering lets you find it without pulling in terabytes of noise.

Combining Filters

tcpdump supports logical AND, OR, and NOT in filter expressions:

# AND - traffic between Windows host and port 80
kali > tcpdump host 192.168.0.114 and port 80
# OR - HTTP or HTTPS traffic
kali > tcpdump port 80 or port 443
# NOT - everything except traffic from a specific host
kali > tcpdump not host 192.168.0.114
# Complex combination
kali > tcpdump 'tcp and (port 80 or port 443) and not host 192.168.1.1'

Two syntax notes: && is equivalent to and, || is equivalent to or, and ! is equivalent to not. In shell commands, wrap complex filter expressions in single quotes to prevent the shell from misinterpreting characters like parentheses, !, and &.

Credential and Artifact Hunting

One of the more operationally useful tcpdump techniques for penetration testers and red teamers is filtering for cleartext credential material. Several legacy protocols still transmit credentials in plaintext: HTTP basic auth, FTP (port 21), SMTP (port 25), POP3 (port 110), IMAP (port 143), and Telnet (port 23).

# Search for credential strings across common plaintext protocols
kali > tcpdump port 80 or port 21 or port 25 or port 110 or port 143 or port 23 -lA | \
egrep -i 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|password='

The -l flag line-buffers the output (so grep receives complete lines), and -A prints the ASCII payload. The egrep pattern matches common parameter names used by web login forms. This is not a magic password sniffer. It only works against unencrypted traffic, but on internal networks where legacy protocols are in use, it surfaces real data fast.

User agent identification:

# Extract user agent strings from HTTP traffic
kali > tcpdump -vvAls0 | grep 'User-Agent:'
# Extract cookies
kali > tcpdump -vvAls0 | grep 'Set-Cookie\|Host:\|Cookie:'

Saving and Reading Capture Files

# Write raw packets to a file for later analysis
kali > tcpdump -w myoutput.pcap
# Read a capture file (output in the same format as live capture)
kali > tcpdump -r myoutput.pcap
# Read a file and apply a filter during reading
kali > tcpdump -r myoutput.pcap 'host 192.168.0.114 and port 443'
# Rotate capture files every 100MB with a timestamp in the filename
kali > tcpdump -w 'capture_%Y%m%d_%H%M%S.pcap' -G 3600 -C 100

The last example uses -G 3600 to rotate files every 3600 seconds (one hour) and -C 100 to roll to a new file every 100MB, whichever comes first. This is the pattern for long-term traffic logging.

Wireshark: The Gold Standard

Wireshark (formerly Ethereal) is the most widely used packet analyzer in the world. It wraps the same libpcap capture engine as tcpdump in a GUI that makes deep protocol analysis practical without memorizing hundreds of filter syntax rules.

Wireshark is built into Kali Linux. Launch it:

kali > wireshark &

Or through the application menu: Applications > 09-Sniffing and Spoofing > Wireshark.

When it opens, Wireshark asks which interface to listen on. If you are in a VM, select eth0. For a physical machine with wireless, select wlan0. A quick way to identify the right interface: look for the one with activity — the waveform displayed next to each interface shows packet rate in real time before you start capturing.

The Three Panes

Once a capture is running, Wireshark shows three panels:

Packet List Pane (top): Every captured packet in chronological order. Color-coded by protocol type — you can customize the colors, and defaults are generally useful: green for TCP, light blue for UDP, dark blue for DNS, and so on. Columns show: packet number, timestamp, source IP, destination IP, protocol, packet length, and a one-line summary. Clicking a row selects that packet and populates the other two panes.

Packet Details Pane (middle): The selected packet decoded in a tree structure, layer by layer. You can expand each layer: Frame (the raw capture metadata), Ethernet II (link-layer headers), Internet Protocol (IP headers with every field labeled), Transmission Control Protocol (TCP headers, flags, sequence numbers, window size), and then the application layer (HTTP, DNS, TLS, whatever the protocol is). This pane is where you spend most of your analysis time — clicking a field highlights the corresponding bytes in the third pane and shows a one-line description of what that field means.

Packet Bytes Pane (bottom): The raw payload of the selected packet in hexadecimal on the left and ASCII on the right. When you click a field in the Packet Details Pane, the corresponding bytes are highlighted here. When analyzing malware C2 traffic or hunting for specific payload patterns, this pane is where you verify what you think you are seeing.

Capture Filters vs Display Filters

This distinction matters and confuses a lot of people. There are two distinct filtering systems in Wireshark, with incompatible syntax:

Capture filters (BPF syntax, same as tcpdump) are applied before packets are stored. They reduce the volume of data written to disk. Set them in the Capture Options dialog before starting a capture. You cannot change them once a capture is running. Use these when you already know what you want and have a high-traffic environment.

Display filters (Wireshark’s own syntax) are applied to an already-captured dataset. They show or hide packets without deleting them. You can change them freely at any time during analysis. Use these for interactive investigation — try different filters, narrow down, pivot to related traffic.

The syntax differences:

TaskCapture Filter (BPF)Display Filter
By IPhost 192.168.1.1ip.addr == 192.168.1.1
By portport 80tcp.port == 80
Protocoltcptcp
Source IPsrc host 192.168.1.1ip.src == 192.168.1.1
Destination portdst port 443tcp.dstport == 443
Contains string(BPF byte-offset syntax required)tcp contains "facebook"

Creating Filters in Wireshark

Protocol Filters

The simplest filter is a protocol name:

tcp
udp
http
dns
smtp
ftp
tls
icmp
arp

Type the protocol in the filter bar, watch it turn green (valid syntax), and press Enter. Wireshark hides all packets except those that contain that protocol. This is usually the first filter to apply — cut the noise down to the protocol you care about before narrowing further.

IP Address Filters

# Traffic to or from either direction
ip.addr == 192.168.1.107
# Only traffic FROM this IP
ip.src == 192.168.1.107
# Only traffic TO this IP
ip.dst == 192.168.1.107
# Entire subnet
ip.addr == 192.168.1.0/24
# Exclude an IP
!(ip.addr == 192.168.1.1)

Note the double equals sign (==). A single = is not valid in Wireshark display filter syntax. This trips up people accustomed to shell syntax.

Port and Direction Filters

# Traffic on port 80 (either direction)
tcp.port == 80
# Traffic TO port 80
tcp.dstport == 80
# Traffic FROM port 443
tcp.srcport == 443
# Multiple ports using the set syntax (Wireshark 4.0+)
tcp.port in {80, 443, 8080}
# UDP DNS
udp.port == 53

Content Filters

When you need to find traffic containing a specific string in the payload, use the contains operator:

# Find packets with "facebook" anywhere in the TCP payload
tcp contains facebook
# HTTP requests containing a specific URI
http.request.uri contains "login"
# Find DNS queries for a specific domain
dns.qry.name contains "malware"

For regular expression matching, use the matches operator (also written as ~):

# HTTP GET requests for .ru domains
http matches "https?.*?\.ru"
# Any packet matching a suspicious URL pattern
http.request.uri matches "\.php\?id=[0-9]+"

The matches operator uses PCRE (Perl-Compatible Regular Expressions) syntax. In tshark, you need to escape the inner quotes when using matches from the command line.

contains and matches cannot be used on atomic fields (numbers, IP addresses). They work on string and byte-sequence fields.

The Expression Builder

If you are not sure what field to filter on, the Expression builder (the dropdown to the right of the filter bar) provides a searchable list of every protocol and every field available for filtering — thousands of entries. Select a protocol, expand it to find the specific field, select a relation operator, and enter a value. Wireshark builds the filter expression for you.

Wireshark Operator Reference

OperatorMeaning
==Equal to
!=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to
containsProtocol or field contains a value
matches or ~Field matches a PCRE regular expression
inField value is a member of a set {val1, val2, val3}
&& or andLogical AND
|| or orLogical OR
! or notLogical NOT

Common Pitfalls with Negation

Before Wireshark 3.6, negation with != on IP address fields had unintuitive behavior. The filter:

ip.addr != 10.43.54.65

did NOT mean “exclude all traffic involving this IP.” It meant “show packets where the source is not this IP AND the destination is not this IP.” A packet from 10.43.54.65 to another host would pass the filter because the destination was not 10.43.54.65. The correct way to exclude an IP was:

!(ip.addr == 10.43.54.65)

Wireshark 3.6 changed the != interpretation for fields that can appear on either side of a packet (like ip.addr), bringing it in line with what most users expected. But if you are working with captures in an older Wireshark version or writing filters that need to be backward compatible, use the !( ... == ...) form explicitly.

Following Streams

Individual packets in isolation are often not useful. What you want is the reconstructed conversation — the full HTTP request and response, the FTP command and data exchange, the SMTP session from EHLO to ..

Wireshark’s Follow Stream feature reconstructs and displays the full application-layer conversation from a sequence of related packets.

To use it: click any packet belonging to the conversation you want to follow, then right-click and select Follow > TCP Stream (or UDP Stream, or HTTP Stream, or TLS Stream for encrypted traffic where you have the session keys).

This opens a window showing the complete session content in ASCII, with client-to-server traffic in one color and server-to-client in another. At the bottom of the window, statistics show the byte counts for each direction.

What Follow Stream reveals that packet-by-packet analysis cannot: the full HTTP headers and body, the file that was downloaded, the commands typed in a Telnet session, the credentials passed in an FTP login sequence, the JSON payload from an API call. For incident response — reconstructing what an attacker did after initial access, for example — this is often the most direct path to the answer.

You can also follow streams on the command line using tshark:

# Follow TCP stream number 0 and output as ASCII
tshark -r capture.pcap -z follow,tcp,ascii,0
# Follow the first HTTP stream
tshark -r capture.pcap -z follow,http,ascii,0

The filter Wireshark applies when you follow a stream — something like tcp.stream eq 3 — is just a display filter you can use directly to focus on that conversation. Note this number and use it to return to that stream if you close the follow window.

Statistics in Wireshark

The Statistics menu provides analytical summaries of an entire capture that go well beyond per-packet inspection.

Protocol Hierarchy (Statistics > Protocol Hierarchy): Shows every protocol present in the capture as a percentage of total packets and bytes. This is the fastest way to understand what a capture contains: if 40% of traffic is TLS, 30% is DNS, 20% is QUIC, and you were expecting only HTTP, something is unusual. Use this as a sanity check when you first open a capture file.

Conversations (Statistics > Conversations): Lists every unique pair of communicating hosts, with byte counts, packet counts, and duration for each conversation. The IP tab shows IP-level conversations, the TCP tab adds port information. Sorting by bytes descending quickly surfaces the highest-bandwidth connections — useful when looking for data exfiltration.

Endpoints (Statistics > Endpoints): Lists every unique host that appears in the capture, with traffic statistics. This is where you identify unknown IP addresses that should not be present on the network.

IO Graphs (Statistics > I/O Graph): Plots packet rate or byte rate over time. Beaconing malware shows up here as regular spikes at consistent intervals — a visual pattern that is hard to spot in the packet list but obvious on a time-series graph.

Flow Graph (Statistics > Flow Graph): Shows a sequence diagram of packet exchanges between endpoints, which is excellent for visualizing multi-step protocol exchanges like TCP handshakes, TLS negotiation, or DNS resolution sequences.

IPv4 Statistics > All Addresses (Statistics > IPv4 Statistics > All Addresses): Every IP address in the capture with packet counts and byte totals — useful for building a quick inventory of hosts seen in a capture.

For baselining purposes, run statistics against a known-good capture of normal traffic. Store the Protocol Hierarchy percentages and Endpoint list. When you capture the same network later and run the same statistics, deviations become visible — new protocols, new endpoints, unusual traffic volumes.

tshark: Wireshark on the Command Line

tshark is the command-line version of Wireshark. It uses Wireshark’s dissectors and display filter language, but runs without a GUI. This makes it useful for remote server analysis (where you cannot run a GUI efficiently), scripting, and batch processing of large capture files.

# Capture 100 packets on eth0, display verbose output
tshark -i eth0 -c 100 -V
# Read a capture file and apply a display filter
tshark -r capture.pcap -Y "ip.addr == 192.168.1.100 and tcp.port == 80"
# Extract specific fields in tab-delimited format
tshark -r capture.pcap -T fields -e ip.src -e ip.dst -e tcp.dstport
# Apply a capture filter (BPF syntax) during live capture
tshark -i eth0 -f "port 443"
# Save filtered output to a new file
tshark -r full_capture.pcap -Y "http" -w http_only.pcap
# Show protocol statistics
tshark -r capture.pcap -z io,phs -q
# Follow TCP stream 0
tshark -r capture.pcap -z follow,tcp,ascii,0 -q

The key distinction: -f takes a BPF capture filter (same syntax as tcpdump), while -Y takes a Wireshark display filter. They are not interchangeable.

Display filters in tshark are more powerful than capture filters but run after packets are already in memory, so on high-traffic live captures, using -Y alone can cause packet loss. For live captures with heavy traffic, apply a broad BPF capture filter with -f first, then use -Y to further refine the display.

For scripting and automation, the -T fields -e field.name pattern is invaluable. It produces structured, parseable output that can be piped to awk, sort, uniq, or fed into Python for further analysis.

Practical Exercises

Work through these in a lab environment with two machines — a Kali Linux box and any other system (a Windows VM works fine). The goal is not just to run the commands but to understand what each output is telling you.

Exercise 1: Filter only your own traffic with tcpdump

Find your IP address with ip addr show. Then run:

tcpdump -nn -i eth0 host YOUR_IP_HERE

Browse to a few sites in a browser and watch what appears. You should see DNS queries (UDP port 53) first, then TCP SYN packets, then SYN-ACK responses, then data transfer. Try to identify the three-way handshake sequence for each new connection.

Exercise 2: Capture and filter traffic from a specific website

Open a browser and navigate to thecybersecguru.com. At the same time, run Wireshark and apply the display filter:

ip.addr == <ip address of thecybersecguru.com>

You can find the IP by pinging the domain first. Follow the TCP stream for one of the connections. Read the raw HTTP request and response.

Exercise 3: Hunt for a string in live traffic

Navigate to a non-HTTPS web page (harder to find these days, but any http:// URL works). In Wireshark, apply:

tcp contains "hacker"

Or choose another word you expect to see on the page. If you find packets, check the Packet Bytes Pane and confirm the word appears in the ASCII view.

Exercise 4: Enumerate all connections to your system with netstat and ss

netstat -an | grep ESTABLISHED
ss -tnp state established

Compare the output. Note the format differences and the additional detail (ss shows the file descriptor number). Look at which processes have established connections and whether any are unexpected.

Exercise 5: tcpdump credential hunt against a test HTTP server

If you have an Apache server running (systemctl start apache2), configure a basic auth protected directory and then attempt to log in from a browser. Capture with:

tcpdump -lA port 80 | egrep -i 'Authorization:|username|password'

HTTP Basic Auth credentials are Base64-encoded (not encrypted). You can decode them with echo 'base64string' | base64 -d.

Exercise 6: Wireshark stream statistics

Open a capture file in Wireshark (or use a live capture). Navigate to Statistics > Conversations > TCP tab. Sort by bytes descending. The top entry is your highest-bandwidth connection. Right-click it and select “Follow Stream” to see what was transferred.

Final Thoughts

The tools covered here are not steps on the way to something more sophisticated. They are the destination. tcpdump and Wireshark are what gets used in production incident response, in enterprise security operations centers, in penetration testing engagements, and in forensic investigations. The engineers who are most effective with these tools are not the ones who know the most flags — they are the ones who understand TCP enough to know what they are looking for before they start filtering.

Start with the exercises above. Then look at real captures from CTF challenges or public pcap repositories. The Wireshark sample captures page hosts dozens of captures across every protocol, including some that contain actual malware traffic. There is no better way to build the pattern recognition that makes network analysis genuinely useful than working with real packets.

This post first appeared at - The CyberSec Guru