Benjamin Sago / ogham / cairnrefinery / etc…

Waltzing with Wireshark

Wireshark is an open-source packet analyser that supports just under two thousand protocols, of which I use approximately seven. It lets you dissect the packets of ancient networks, collect all kinds of traffic statistics, and diagnose problems with various telephony-related systems. It even has a Lua scripting interface. I hardly use any of it.

Here’s what I use it for:

  • Finding out why I can’t connect to something on my LAN
  • Seeing what traffic I’m sending out over a public Wi-Fi hotspot
  • Seeing what traffic I’m receiving over a public Wi-Fi hotspot
  • Checking whether a suspicious program is phoning home
  • Using the packet tree panel to see what a protocol looks like

There are three aspects of the application that we’re going to change here. First, we’re going to change some of the default settings to make it look a little nicer. Next, we’ll change the colouring rules to make situations we care about easier to read. Lastly, we’ll set up some shortcuts to make our packets more accessible.

Change some default appearance settings

Here’s what Wireshark looks like by default, more or less:

A screenshot of Wireshark, out-of-the-box.
  • Firstly, I really recommend changing the font to one that takes up less horizontal space. The tables can get very wide, and using a smaller, thinner font lets Wireshark pack more data in. I’m using Iosevka.
  • The Time column can be made slimmer by setting the menu option View → Time Display Format → Millisecond. It’s precise enough for almost anything.
  • By right-clicking column headings, you can right-align or centre-align columns. I found that changing this setting helps certain columns by spacing the data out, making the table more readable. (And time should be right-aligned anyway, because it’s numeric.)
  • Finally, in the Layout settings page, you can put the packet tree and hex dump side-by-side instead of as two separate rows.

Put it all together, and you’ve got something like this:

A screenshot of Wireshark after tweaking its appearance.

Much nicer.

Create some nicer colours

By going to View → Coloring Rules, you’ll see the packet filters that Wireshark uses to assign each packet a colour. You’ll also see an Export button, which you may want to click on before we re-write the whole lot.

The downside of supporting thousands of protocols is that there are only a finite number of distinguishable colours that they can be mapped to. Some of the default entries in the list I would be very surprised to capture.

One of the protocols that gets coloured bright pink is IPX. Its full name is “Internetwork Packet Exchange”, but that doesn’t matter, because when I looked it up, Wikipedia told me:

It does not scale well to large networks such as the Internet

Cool. Next, another protocol called DCE/RPC has claimed a bright purple colour. Wikipedia again:

DCE has not seen much success in practical implementation

I’m sure there’s somebody out there who works with IPX and DCE daily. Do not write to me and complain; you already get to live a more interesting life than mine.

The rest is almost all stuff I don’t use. I don’t use SMB or anything NetBIOS. I can see why a packet analyser would have Cisco HSRP rules hard-coded, but I personally don’t need them. The more I read about SCTP, the more I would have liked it, but it’s not going to happen.

The last rule to be removed is the rule for port 80. With more and more network traffic being not just HTTP, but HTTP over TLS on port 443, Wireshark will highlight entire HTTP conversations in its “generic TCP stream” purple colour.

So what would I like to see? There are four main groups: errors, warnings, interesting protocols, and everything else.

Errors

eth.fcs.status=="Bad" || ip.checksum.status=="Bad" || tcp.checksum.status=="Bad" || udp.checksum.status=="Bad" || sctp.checksum.status=="Bad" || mstp.checksum.status=="Bad" || cdp.checksum.status=="Bad" || edp.checksum.status=="Bad" || wlan.fcs.status=="Bad" || stt.checksum.status=="Bad"

tcp.analysis.flags && !tcp.analysis.window_update

Packets with invalid checksums and TCP retransmissions have an orange background, because they usually indicate an unstable connection.

Warnings

icmp.type eq 3 || icmp.type eq 11 || icmpv6.type eq 1 || icmpv6.type eq 2 || icmpv6.type eq 3 || icmpv6.type eq 4

tcp.flags.reset eq 1

ICMP errors and TCP RST packets mean that while the connection is stable, an application is trying to do something that’s not working.

DNS

dns

dns.count.answers == 0 && dns.response_to

This is so common that it deserves highlighting. Because it’s so simple to parse DNS packets, we might as well mark responses with no results as warnings.

Address Resolution

arp || icmpv6.type eq 133 || icmpv6.type eq 134 || icmpv6.type eq 135 || icmpv6.type eq 136 || icmpv6.type eq 137

ARP is just as common. The IPv6 equivalent, Neighbour Discovery, is implemented using special kinds of ICMPv6 packets we can check for.

ICMP

icmp || icmpv6

ICMP packets that get to this point aren’t going to be errors, but they still need highlighting to distinguish them from “normal” traffic.

Routing

hsrp || eigrp || ospf || bgp || cdp || vrrp || carp || gvrp || igmp || ismp

Packets using these protocols get highlighted because they’re just the network checking itself out, rather than being sent by an application using the network.

HTTP and HTTPS

http || http2

ssl && not (ssl.record.content_type == 23)

Thanks to TLS, the majority of Web traffic will be encrypted binary data rather than plain text — and highlighting all HTTPS packets that aren’t of the “Application Data” variety means it just highlights the start of the connection. I took out the rule that matches port 80 because it also highlighted the TCP handshake.

SSH

ssh.protocol || ssh.message_code

The same thing occurs with SSH: almost all the traffic will be encrypted and won’t do you any good to sniff, so instead, only highlight the negotiation at the start of the connection.

Broadcast

eth[0] & 1

Anything sent to everyone is bound to be worth reading.

TCP SYN and FIN

tcp.flags & 0x02 || tcp.flags.fin == 1

All the rest is just ordinary data traffic, but by highlighting the SYNs and FINs that book-end TCP connections, it’s easier to tell the difference between multiple connections and a single very chatty one!

Specify which packets to display

You might read the way we de-highlight HTTPS or SSH packets and worry: won’t this make important information fade into the background? The answer is yes, but if you want an easy way to filter packets by protocol, there’s an easier way to get that easy way.

By going to Preferences → Filter Buttons, you can define shortcuts that live to the right of the filter text box:

A screenshot of Wireshark with some filter buttons.

These can be as simple as you like, such as arp or icmp or ssh. Sure, you can type these filters out, but I prefer to click. (The “Certs” one is just ssl || ocsp.)

Lastly, I find it helpful to disable all the network interfaces I know I’m never going to use by going to Capture Options → Manage Interfaces. The only two I capture on are en0, my Wi-Fi, and lo0, loopback. Hiding the dozen or so other interfaces means I don’t need to scan through the list each time.

More Fun

There’s a lot you can do with Wireshark. Here are a couple more links if you’re interested in customising it further:

  • Custom profiles is a big one. All our customisations so far have just affected the “Default” profiles, but you can create different sets of colours, filters, and settings and switch between them depending on what kind of analysis you’re doing. The post My Favorite Wireshark Customizations (Part 1) demonstrates how to create a special view for 802.11 traffic, with custom columns and colours for Wi-Fi packets that wouldn’t make sense for Ethernet packets.
  • Decrypting TLS traffic is another useful feature. It’s a little tricky to do this when using a cipher suite with forward secrecy, as the private key is no longer sufficient to decrypt the traffic, so you have to do a little dance where the browser logs the keys it uses and Wireshark reads the log. The post Decrypting TLS Browser Traffic With Wireshark, The Easy Way lists the steps to set it up in Windows.
  • The Expert Information window is not just for experts. It provides a high-level overview of the captured packets, including which it classifies as “errors” and “warnings”. These classes aren’t exactly the same as I’m using above, but it can still let you know if you’re getting an above-average number of them. You can even use the “error” status in filters. It’s available by going to Analyze → Expert Information or clicking the button at the left end of the status bar.

But my favourite tip is being able to stream another server’s packets, live.

You could do this by SSHing onto the machine, using tcpdump to capture packets for a spell and save them to a file, then transferring the file to your local machine to open it in Wireshark. But not only do you have to know when to stop, it’s also not very exciting. You don’t get to see the bits fly by!

Fortunately, there’s another way: run tcpdump over SSH and pipe the results directly into Wireshark using your shell. This has its own drawback: the act of sending packets over SSH will add more packets to the stream, meaning it’ll have to send those, and so on! So we have to be smart, and capture all packets except the SSH packets being sent back to us.

OpenSSH sets the SSH_CLIENT environment variable, which we can use to obtain the IP address we’re connecting from, and then filter based on that. Here’s the shell script I have on my servers:

$ cat ~/bin/packet-capture.sh
#!/bin/sh
if [ -z "$SSH_CLIENT" ]; then
  echo "[Not SSHing? Just run tcpdump manually]"
  exit 1
else
  CLIENT="${SSH_CLIENT%% *}"
  sudo tcpdump -U -s0 "not (port 22 and host $CLIENT)" -w -
fi

And here’s how I use it:

$ ssh me@my-server '~/bin/packet-capture.sh' | wireshark -k -i -

This will continue running until Wireshark is closed, and the shell kills the ssh process; tcpdump has no way to know that you’ve hit the Stop button on the toolbar.