Skip to content

Wireshark

tcpdump already showed up several times earlier in this course, filtering on TCP flags to catch a handshake or a teardown in the act. That's the right tool when you already know what you're looking for. Wireshark is what you reach for when you don't — a graphical front end over the same libpcap capture engine, built around letting you explore a capture rather than grep it.

Reading the three panes

A Wireshark window is built around three stacked panes, each showing the same capture at a different level of detail:

  • Packet list — one row per frame, in the order it was captured, with columns for time, source, destination, protocol, and a one-line info summary Wireshark generates automatically.
  • Packet details — the frame you've selected, broken into nested, collapsible sections: Frame, Ethernet II, Internet Protocol, Transmission Control Protocol, and whatever application-layer protocol Wireshark recognized on top. That nesting isn't arbitrary — it's the same layered structure the OSI model describes, made literally clickable: expand the TCP section and you're looking at the actual sequence number, acknowledgment number, and flags this course's TCP articles already covered as abstract concepts, now sitting in a real captured frame.
  • Packet bytes — the frame's raw hex and ASCII, with whichever field you have selected in the details pane highlighted in both.

Clicking through those three panes on a single packet is the fastest way to connect this course's layer-by-layer theory to something concrete: select the TCP header's flags field, and the exact two bytes encoding it light up in the raw hex directly below.

Capture filters and display filters are not the same language

This is the detail most people new to Wireshark get wrong first, because both look like a similar text box at the top of the window. They're not the same thing:

  • Capture filters use the same BPF syntax tcpdump does — tcp port 443, host 192.168.1.1 — applied before a packet is captured at all. A packet that doesn't match never gets recorded, and it's gone for good once the capture stops.
  • Display filters use Wireshark's own, considerably richer syntax, applied after capture, to a capture that's already sitting in memory or in a file — tcp.port == 443, http.request.method == "GET", ip.addr == 192.168.1.1. Nothing is discarded; the filter just controls what's currently shown.
tcp.flags.syn == 1 && tcp.flags.ack == 0

That expression — a display filter, using dotted field names rather than BPF's bare keywords — isolates only the initial SYN packets of every handshake in an already-captured file, the same category of packet the three-way handshake article filtered for directly at capture time with a BPF expression instead. Capturing broadly and filtering the display afterward, rather than filtering tightly at capture time, is usually the better default when you're not yet sure exactly what you're looking for — you can always narrow the display filter and try again without recapturing, but a too-narrow capture filter may have already discarded the one packet you needed.

Following a stream: seeing data the way the application does

A raw packet list shows one TCP segment per row — useful for looking at handshake mechanics, unhelpful for reading an actual request or response, which is usually split across several segments. Right-click any packet in a connection and choose Follow → TCP Stream, and Wireshark reassembles every segment in that one connection back into the two-sided conversation an application would actually see, client-to-server and server-to-client traffic shown separately and in order:

GET /api/status HTTP/1.1
Host: api.example.com
User-Agent: curl/8.5.0
Accept: */*

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 23

{"status":"ok"}

Over plain HTTP, this reads exactly like the request and response curl -v prints — same headers, same body, just reassembled from the underlying segments instead of shown by the client that sent them. Follow the same feature on an HTTPS connection instead, and the reassembled view shows only ciphertext, unreadable without the session's decryption keys — a direct, visible demonstration of exactly what encryption is supposed to hide, worth trying once specifically to see the difference for yourself.

Automatic protocol analysis: coloring and expert information

Wireshark ships with default coloring rules that flag categories of traffic without you writing a single filter — DNS traffic in one shade, a checksum error in another, and TCP problems specifically (retransmissions, duplicate ACKs, out-of-order segments) highlighted by the built-in "Bad TCP" rule, filterable directly with tcp.analysis.flags. Analyze → Expert Information goes a level further, collecting every warning, note, and error Wireshark's protocol dissectors generated across the whole capture into one summarized list — a retransmission count, a set of duplicate ACKs, a malformed packet — without you needing to spot each one manually while scrolling.

Diagnosing a slow connection: retransmissions, not the network being "slow"

A backend team reports that requests to a downstream service are intermittently slow — most complete quickly, but a noticeable fraction take several seconds longer than the rest, with nothing in the application's own logs explaining why. A capture on the client, filtered with the expert-analysis filter directly, tells a different story than "the network is slow":

tcp.analysis.retransmission
No.   Time      Source          Destination     Protocol  Length  Info
482   14.223011 10.0.5.20       203.0.113.44    TCP       66      [TCP Retransmission] 51230 → 443 [ACK] Seq=1461 Ack=1 Win=64240 Len=0
483   14.225188 10.0.5.20       203.0.113.44    TCP       1514    [TCP Retransmission] 51230 → 443 [PSH, ACK] Seq=1461 Ack=1 Win=64240 Len=1448

Filtering for tcp.analysis.retransmission surfaces every segment Wireshark's own analysis flagged as a retransmission — data the sender transmitted once, got no acknowledgment for within its expected window, and sent again. A handful of these scattered through an otherwise clean capture, concentrated around the same few connections, points at real packet loss on the path to that one downstream service — not a slow server and not a slow client, but segments actually being dropped somewhere between them, forcing TCP's own loss-recovery mechanism (the retransmission and timeout behavior the congestion control article covers from the sender's side) to kick in and add real, measurable delay before the connection recovers. That's a materially different fix than anything at the application layer — it points at the network path itself, and specifically at wherever between these two hosts is actually dropping packets, which is a question for the next hop's own metrics, not for the application's code.

Practice exercises

  1. Capture a short burst of your own browsing traffic, then use Follow → HTTP Stream (or TLS Stream, for an HTTPS site) on one connection and compare what each shows you.
  2. Write a display filter that shows only DNS queries, and a second one that shows only DNS responses containing more than one answer record.
  3. Given a capture with tcp.analysis.retransmission matches scattered across many different destination IPs rather than concentrated on one, explain why that pattern points somewhere different than a problem specific to one downstream service.

Every tool this module covered — from a simple ping through a full packet capture — answers questions about a network you can already reach in some form. The next module turns to the services that make reachability possible in the first place: how a name actually gets resolved step by step, how a DHCP lease is negotiated, and what NAT does to every packet crossing a home router's boundary.

Sources