Packet Analysis with Wireshark
The last four chapters gave you the theory: how frames are built, how TCP negotiates and tears down a session, how DNS resolves a name, how TLS wraps a conversation in ciphertext. That theory is what makes a capture readable instead of a wall of hex. This chapter is where it becomes a hands-on skill. You will open an unfamiliar PCAP, apply the right filters, follow a conversation end to end, and actually pull answers out of it rather than just staring at packets scrolling past. By the end, you should be able to sit down with a capture you have never seen and know exactly where to start looking.
The Wireshark Interface
Wireshark's main window is built around three panes, and understanding how they relate to each other is the first real skill in packet analysis.
The Three Panes
- Packet list (top). One row per captured frame: number, timestamp, source, destination, protocol, length, and a summary column that Wireshark generates from the highest-layer protocol it recognizes. This is where you scan for patterns, sort by column, and click into anything that looks interesting.
- Packet detail (middle). Shows the selected packet broken into its protocol layers as a collapsible tree: Frame, Ethernet, IP, TCP or UDP, and then whatever application protocol sits on top. Expanding each layer reveals field values, flags, and options that never appear in the packet list at all, like TCP window size or a specific HTTP header.
- Packet bytes (bottom). Shows the raw hex and ASCII for the packet, synchronized with whatever you have selected in the detail pane above it. Useful for confirming exactly how a value is encoded on the wire, and for spotting cleartext strings that Wireshark's dissectors did not surface as a named field, such as a credential embedded in a custom application protocol.
Capture Filter vs Display Filter
The distinction that trips up almost every beginner is capture filter versus display filter. The confusion is understandable, since both narrow down packets and both use a text box near the top of the window.
A capture filter is applied before any packet is captured, using Berkeley Packet Filter (BPF) syntax, the same syntax tcpdump uses: host 10.0.0.5, port 443, tcp and port 80. Anything that does not match a capture filter is discarded at the network interface and never written to the capture file at all, which means you cannot get it back later no matter what display filter you write.
A display filter, by contrast, is applied after capture, to packets already sitting in memory or in a saved PCAP file. It uses Wireshark's own filter language, which looks similar to BPF but is not the same syntax and is far more expressive, since it can reference any field that any dissector has parsed, not just the handful of fields BPF understands.
In practice, when you are handed a PCAP someone else already captured, you are always working with display filters, because the capture already happened and there is nothing left to discard. Beginners who type BPF syntax like port 443 into the display filter bar are often surprised when Wireshark rejects it or interprets it unexpectedly, since the display filter equivalent is tcp.port == 443.
Display Filters That Matter
A small set of display filters covers the overwhelming majority of real analyst work, and learning them fluently is worth more than memorizing the full filter grammar.
Host and Port Filters
The most basic is an address filter: ip.addr == 10.0.0.5 shows every packet where that address appears as either source or destination, which is almost always what you want when following one host's activity. Narrow it further with a port filter, tcp.port == 443, to isolate one conversation type, or combine both to pin down a specific host-to-service relationship.
Application-Layer Filters
These let you skip straight to protocol events instead of scrolling through every packet in a stream. http.request shows only HTTP request lines, far more useful than wading through TCP ACKs to find the handful of packets that actually carry a GET or POST.
dns.qry.name contains "evil" searches DNS query names for a substring, useful for spotting a suspicious domain fragment across an entire capture without knowing the exact FQDN in advance. tls.handshake.type == 1 isolates Client Hello messages, where you would look for SNI values before the rest of the session is encrypted.
Flag-Based Filters
These find specific TCP behaviors rather than specific hosts or ports. tcp.flags.syn==1 and tcp.flags.ack==0 isolates SYN packets with no ACK set, meaning connection attempts rather than responses, exactly what a port scan looks like: one source sending SYNs to many ports or many hosts with few or no completed handshakes.
tcp.flags.reset==1 finds resets, useful when you suspect a firewall or an overwhelmed service is tearing down connections abnormally often.
Combining Filters and Discovering New Ones
Filters chain with and, or, and parentheses the same way you would expect from boolean logic in any language. Getting comfortable combining them is what turns Wireshark from a packet viewer into an investigation tool.
ip.addr==10.0.0.5 and tcp.port==443 narrows to one host's HTTPS traffic. (ip.src==10.0.0.5 or ip.src==10.0.0.6) and tcp.flags.syn==1 isolates connection attempts from either of two suspect hosts. Negation uses ! or not, so !(arp or icmp) hides the broadcast chatter that clutters most captures and is rarely relevant to an investigation.
Wireshark's filter bar also autocompletes and color-codes as you type: green means valid syntax, red means it will not parse. Right-clicking any field in the packet detail pane and choosing "Apply as Filter" or "Prepare as Filter" is often faster than typing from memory, and it is a good way to learn the underlying field names for protocols you do not use every day.
| Filter | What It Finds |
|---|---|
ip.addr==x.x.x.x | All traffic to or from a specific host |
tcp.port==x | Traffic on a specific TCP port, either direction |
http.request | HTTP request lines only, skips responses and ACKs |
dns.qry.name contains "x" | DNS queries containing a substring in the name |
tls.handshake.type==1 | Client Hello messages, where SNI values live |
tcp.flags.syn==1 and tcp.flags.ack==0 | Connection attempts, a signature of port scanning |
tcp.flags.reset==1 | Resets, a sign of abnormal connection teardown |
tcp.analysis.retransmission | Packets Wireshark identified as retransmissions |
!(arp or icmp) | Hides broadcast/control-plane chatter |
Following a TCP Stream
Right-clicking any TCP packet and choosing Follow > TCP Stream is one of the highest-value moves in Wireshark, and it is easy to overlook when you are focused on filtering the packet list. Instead of showing individual segments, it reassembles the entire conversation, both directions, in the order the application layer actually sent and received the data, stripping away the TCP mechanics of sequence numbers, ACKs, and segmentation that obscure what was actually said.
What It Shows
The result is presented as a single scrollable transcript, conventionally colored red for one direction and blue for the other, so you can read a request and its matching response as continuous text rather than reconstructing it yourself from a dozen scattered packets. For an HTTP exchange, this means the full request line, headers, and body, followed immediately by the full response, headers, and body, exactly as an application would have assembled it.
Wireshark automatically applies a display filter for that specific stream when you close the window, so the packet list narrows to just the packets in that conversation.
Why It's Fast
This is often the fastest way to understand what actually happened in an exchange, faster than reading packet by packet, because most analysis questions are really questions about content, not about individual segments. Follow TCP Stream answers questions like these in seconds, where manually clicking through twenty packets and reassembling payload bytes in your head would take much longer and invite mistakes:
- Did the client send credentials in the clear?
- What exact URL was requested?
- What did the server actually return: an error page, a redirect, a file?
Where It Works, and Where It Breaks
The technique works on any cleartext TCP protocol, not just HTTP. FTP control channels, Telnet sessions, unencrypted SMTP, and plenty of legacy or misconfigured application protocols all read cleanly as a follow stream transcript.
For UDP-based protocols there is an equivalent Follow > UDP Stream, and Wireshark also offers Follow > TLS Stream, which will show decrypted content only if you have supplied the session keys or a private key, since TLS is specifically designed to prevent a passive observer from reading the stream without them.
One caveat worth internalizing early: stream reassembly depends on Wireshark seeing the full conversation. A capture that starts mid-session, drops packets due to capture loss, or only captured one direction of an asymmetric routing path will produce a partial or garbled follow stream. When the reconstructed text looks broken or out of order, check Statistics > Conversations for that stream to confirm you actually have both directions and no obvious gaps before concluding the application behaved strangely.
Spotting Anomalies in a Conversation
Recognizing normal traffic by sight is what makes abnormal traffic jump out, and that pattern recognition is built through repetition. There are still specific signals worth training yourself to notice deliberately.
Five Signals Worth Training Yourself to Notice
- Excessive retransmissions. Wireshark marks them automatically in black with red text, and its
tcp.analysis.retransmissionfilter will surface every one in a capture. A handful on a long-haul or wireless link is normal network behavior, but a dense cluster concentrated on one host or one service usually points to packet loss, an overloaded server, or a middlebox interfering with the connection. - Unexpected resets. A TCP RST is a normal way to end a connection when there is no listener on a port or when an application decides to abort abruptly. But a pattern of many RSTs immediately after SYN-ACK, especially spread across many destination ports from one source, is a classic signature of a host being scanned. RSTs appearing mid-conversation on connections that were previously healthy can indicate a firewall or IPS intervening, or an application crashing under load.
- Traffic on unusual ports. A service that should only ever speak on its well-known port suddenly showing up on a high, ephemeral-looking port, or a host making outbound connections to port 4444, 8080, or another commonly abused port with no legitimate business reason, warrants a closer look at the actual payload rather than trusting the port number. Attackers deliberately choose ports to blend in, and Wireshark's protocol dissectors will still correctly identify many protocols regardless of the port they run on, which is a useful cross-check.
- Cleartext credentials in the wrong protocol. A plaintext username and password on an FTP or Telnet stream is unsurprising, since those protocols were never designed with confidentiality. Seeing the same thing inside a protocol that is supposed to be encrypted, such as HTTP Basic Auth over plain port 80 where HTTPS should have been enforced, or credentials inside an HTTP POST body without TLS, is a real finding worth escalating immediately, not just a curiosity.
- Unusually large or frequent DNS queries. This signal is easy to miss because DNS traffic is so voluminous it becomes background noise. A single host issuing hundreds of DNS queries per minute, queries for long or high-entropy subdomain labels, or DNS responses far larger than a typical A or AAAA record can indicate DNS tunneling, a DGA-based malware family cycling through candidate domains, or data exfiltration encoded into query names. Statistics > DNS or a targeted
dnsfilter combined with sorting by query name length is usually enough to surface this pattern quickly.
A Repeatable PCAP Triage Workflow
Opening an unfamiliar capture and scrolling through the packet list from the top is the least efficient way to start, and it is exactly what beginners tend to do. A repeatable triage workflow gets you from an unknown file to a working hypothesis in a fraction of the time, and it starts at the statistics menu rather than the packet list.
- Check Statistics > Protocol Hierarchy first. It breaks down every protocol present in the capture as a percentage of total packets and bytes, nested by layer, so you immediately see the shape of the traffic: is this mostly HTTP, mostly TLS, a lot of DNS relative to its size, any protocols present that seem out of place for the environment the capture came from. A capture that is supposedly internal LAN traffic but shows a meaningful percentage of an unfamiliar or unexpected protocol is worth investigating before anything else.
- Check Statistics > Conversations and Endpoints next. Conversations gives you a sortable table of every unique communication pairing, by IP, TCP, or UDP, with packet counts, byte counts, and duration for each. Sorting by bytes or packets descending surfaces your top talkers immediately: the handful of conversations that dominate the capture. Endpoints gives the same idea from a single-host perspective rather than a pairwise one, useful for quickly answering "which hosts are even present in this capture" before you start filtering on any of them specifically.
- Drill into anomalies with targeted display filters. With top talkers and an overall protocol shape in hand, drill into anything that looked anomalous in either view. If Protocol Hierarchy showed unexpected DNS volume, filter on
dnsand sort by query name. If Conversations showed one host dominating byte count, filter to that host withip.addr==and check what protocol is carrying that volume. If a top talker pairing looks like a suspicious scan pattern, apply the SYN-without-ACK filter scoped to that host and count how many distinct destination ports it touched.
This sequence, overview first, then top talkers, then targeted drill-down, works because it moves from the broadest possible signal to the narrowest as fast as possible, instead of guessing where to look first. It also produces a natural audit trail: you can document exactly which statistics view surfaced the anomaly and which filter confirmed it, which matters when the triage needs to be written up or handed off.
Wireshark vs tshark vs tcpdump vs Zeek
All four tools touch packet data, but each earns its place at a different stage of an investigation, from live triage to unattended automation to long-term visibility.
Wireshark, tshark, and tcpdump
Wireshark's GUI is the right tool when you need to explore, when you do not yet know what you are looking for and need to pivot between statistics views, filters, and stream reconstruction interactively. That exploratory strength is also its limitation: it does not scale to automation, to processing hundreds of captures unattended, or to running the same check across a fleet of collected PCAPs without a human clicking through each one.
tshark is Wireshark's command-line sibling, built on the exact same dissection engine, which means any display filter you have already learned in the GUI works identically in tshark. It is the tool to reach for once you know what you are looking for and need to script it: extracting every DNS query name from a directory of captures, running the same anomaly filter against files pulled from an automated collection pipeline, or feeding filtered fields into another tool as CSV or JSON. What tshark trades away is interactive exploration; you are typically writing the filter and field extraction up front rather than discovering it by clicking around.
tcpdump sits a level below both. It is a capture tool first, a display tool second, using the same BPF capture filter syntax discussed earlier in this chapter, and it is available by default on nearly every Linux and Unix system without installing anything extra. Its own output formatting is far less rich than Wireshark's, and in practice a common pattern is capturing with tcpdump on a remote or resource-constrained host and then transferring the resulting PCAP file to a workstation for full analysis in Wireshark.
From Packets to Logs: The Zeek Preview
Wireshark, tshark, and tcpdump share one fundamental characteristic: they work with full packet captures, meaning every byte of every packet, which gives maximum fidelity but also means storage and processing cost scale directly with traffic volume.
Chapter 7 introduces Zeek, which takes a genuinely different approach: instead of storing raw packets, it observes traffic in real time and generates structured, protocol-aware log files, a connection log, an HTTP log, a DNS log, and more, each just the fields that matter for that protocol. That shift, from packets to logs, is what makes Zeek practical at a scale where retaining full PCAP for everything is not feasible. The two approaches are complementary rather than competing: Zeek logs tell you where to look, and a packet capture of that specific window is what you would open in Wireshark to confirm it.
| Tool | Best For | Trade-off |
|---|---|---|
| Wireshark (GUI) | Interactive exploration when you don't yet know what you're looking for | Does not scale to unattended automation |
| tshark | Scripting a known filter across many captures | No interactive discovery, filters written up front |
| tcpdump | Fast, lightweight capture on any Linux/Unix box | Minimal display formatting, usually paired with Wireshark for analysis |
| Zeek | Structured, protocol-aware logs at scale (Chapter 7) | Not full packet fidelity; a lead, not a replacement for PCAP |
Key Takeaways
- Wireshark's three panes, packet list, packet detail, and packet bytes, work together: scan the list, confirm in the detail tree, verify raw encoding in the bytes pane.
- Capture filters (BPF syntax) discard packets before they are ever written to disk and cannot be undone. Display filters (Wireshark's own syntax) narrow an already-captured file and can always be rewritten.
- A small core of display filters, address, port, protocol event, and TCP flag filters, chained with and/or, covers most real analyst work.
- Follow TCP Stream reconstructs a full two-way conversation as readable text and is often the fastest way to understand what actually happened in an exchange.
- Retransmissions, unexpected resets, traffic on unusual ports, cleartext credentials in the wrong protocol, and abnormal DNS query volume are the anomaly signals worth training yourself to spot.
- A repeatable triage workflow, Protocol Hierarchy for overview, Conversations and Endpoints for top talkers, then targeted filters to drill in, beats scrolling the packet list from the top.
Knowledge Check
Click an answer to reveal the explanation.
You want to capture only traffic to or from 10.0.0.5 on a live interface, and you type ip.addr == 10.0.0.5 into the capture filter field before starting the capture. Wireshark rejects it. Why?
host 10.0.0.5. The field==value style with double equals and dotted field names is display filter syntax, applied after capture, and is not valid in the capture filter field. This mismatch is one of the most common beginner mistakes.You are handed a PCAP and, using Statistics > Conversations, notice one internal host sent SYN packets with no ACK to over 400 distinct destination ports on the same external IP within a few seconds. What does this most likely indicate, and what filter would confirm it?
tcp.flags.syn==1 and tcp.flags.ack==0 scoped to that host pairing isolates exactly these connection attempts and lets you count the distinct ports touched to confirm the pattern.You need to check DNS query patterns across 300 PCAP files collected overnight from multiple sensors, looking for any host issuing an abnormal volume of queries. What is the most practical approach?