Wireshark is a free and open-source Network Protocol Analyser, used to capture and analyse network traffic.
It’s very useful to analyse how much traffic your networked game is generating during gameplay, see what endpoints are being hit and so on.
It’s available on Mac, Windows and various Linux distros. You can download it from here https://www.wireshark.org/download.html
You will also need to install ChmodBPF, included in the downloaded volume, in order to capture packets. You can also optionally add tshark, capinfos, editcap, and other command line utilities to the system PATH, by running the “Add Wireshark to the system path” package.
Network Interface selection
The first thing to do is select the network interface you’d like to use to analyse network traffic.
When you open Wireshark, it will detect all available interfaces in your current device, and list them in the main screen.
Wireshark will show a quick preview of the traffic going through each interface while not capturing, as shown below.
You can optionally use the dropdown on the right to filter wired, wireless, and external interfaces (the ones you see at the bottom, requiring extra tooling).
If you want to analyse traffic between applications running on the same device, you can select the loopback interface (normally called lo0 or something similar).
You can double click on an interface to start capturing, but before doing so, let’s make sure we have the right filters.
Defining filters
There are two types of filters, Capture and Display. As the names suggest, Capture filters are used to reduce the amount of packets captured by Wireshark. They are set before a Capture session starts, and cannot be modified afterwards. On the other hand, Display filters are used to filter the data shown in the interface, and can be modified also during and after the capture.
Wireshark offers a list of predefined filters saved in the bookmarks. They are useful both to get started with some of the most common scenarios, and also to familiarise yourself with the filters syntax.
For the display filters, you can check them out from Analyze - Display Filters.
While for Capture filters, they are under Capture - Capture Filters.
As you can see, the syntax is slightly different between the two filter types. For example, if you wanted to analyse HTTP traffic, you would use this as capture filter:
tcp port 80
Or the equivalent display filter:
tcp.port == 80
You can also filter by port ranges, for example:
portrange 5055-5058 or portrange 27000-27003
The list of possible expressions is very long. You can take a look under Analyze - Display Filter Expression for an exhaustive list of display filters options, which also allows you to build filters.
Taking a capture
For the sake of this tutorial, and to give a real example, let’s assume that I’m currently working on an online multiplayer game. A client, running on my local machine, is connected to a remote dedicated server hosting a match. In addition, the client makes RESTful calls to a remote backend, and has a websocket connection to receive live updates from the back. I want to capture all traffic generated from my game during a regular session, in order to analyze it later on and share it with the rest of the team.
To do so, I defined a new capture filter, called “Game Data”, with the following expression:
udp port [GAME_SERVER_PORT] and host [GAME_SERVER_IP_ADDR] || tcp port 443 and host [BACKEND_URL] || tcp port 443 and host [WEBSOCKET_URL]
The first bit captures all UDP traffic going through a specific GAME_SERVER_PORT port, where the host’s IP address is GAME_SERVER_IP_ADDR. The second portion captures all HTTPS traffic (both HTTPS 1.x and 2 use TCP), coming from and going to BACKEND_URL. Finally, the last portion of the filter captures the aforementioned Websocket traffic.
After setting the capture filter, select Capture - Start to start capturing packets.
After playing a full game session, I can then stop using Capture - Stop, and analyse the results. Since the amount of data will be significant, it’s handy to apply display filters to reduce the data shown at once.
You can then save the capture for later retrieval and for historical analysis, by going to File - Save as…
By default, Wireshark will capture packets in Promiscuous Mode, unless the network interface or OS does not allow it, or you disable it from Preferences - Capture - “Capture packets in Promiscuous Mode”. When enabled, all packets that the network interface can see will be included in the capture, rather than just the ones meant for your machine.
Conversations
Conversations allow you to group traffic going from/to certain addresses, helping you make sense of your capture data.
When opening the window, you can choose the adapter or protocol at the top, then you’ll see a list of conversations, including amount of data and packets in each direction, bitrate, the duration of the conversation and so on.
As an example, here’s how it looks like when I download a file:
From the Conversation Settings on the left, you can select “Name Resolution” to view resolved names, as opposed to raw addresses.
If you then right click on a conversation, Wireshark allows you to prepare a filter that will show the conversation in the main capture window, in whichever direction you want to analyse.
After applying the filter, you can select all packets from the main window, then select File - Export Packets Dissections. This lets you export the packet list, details and plain data in various formats, such as JSON, XML, plain text or C array. You can then reconstruct the downloaded data from there. You can also try and use File - Export Objects - HTTP, then Wireshark will scan through the capture data and look for files that can be reconstructed and downloaded.
An alternative way to follow conversation is by selecting a packet from the main window, then right click and selecting Follow. Depending on the packet, this will show you a list of protocol options, such as TCP Stream or TLS Stream. This will open a dialog window showing the data transferred as part of that conversation (red for client to server, blue in the opposite direction).
You can optionally change the data visualisation format at the bottom. It will also apply a display filter in the main window for the relevant packets.
Finally, another way to look for the start of conversations is to apply a filter for ARP (Address Resolution Protocol) packets. They are used to create the mapping of an IP address to the underlying Ethernet address, for this reason they are often found at the beginning of a conversation.
Encryption
As you might have noticed, much of your HTTP traffic will be impossible to read. That’s because most web traffic goes through TLS (Transport Layer Security). In order to make sense of it, you’ll need to decrypt it.
The exact way to do that changes depending on the way the data is transferred. If you’re using curl (as most game engines do), and for most browsers, it will involve setting the SSLKEYLOGFILE environment variable, then assigning that in Preferences - Protocols - TLS, in the (Pre)-Master-Secret log filename field.
You can learn more about how curl handles that here: https://everything.curl.dev/usingcurl/tls/sslkeylogfile.html
Keep in mind that decrypting certain data might not be allowed. For this reason, make sure to only do this when working with your own applications or games.
Name Resolution
In some cases, it can be handy to have Wireshark attempt to resolve addresses to make the capture more readable. You can do so from the Preferences - Name Resolution window.
In addition to the default resolution methods, you can define additional DNS Servers by using the Edit button shown. Note that, when resolving IP addresses, the actual DNS queries might be added to the capture.
Traffic Graphs
To make sense of your game traffic, it’s often handy to visualise it over the duration of the session, and then correlate it to what happens in-game.
You can easily do so by selecting Statistics - I/O Graphs.
At the bottom there will be a few preset filters, defined based on the protocols and data contained in your capture. You can define more filters using the Plus button, and change the Interval used to plot the graph.
This is particularly useful when preparing a game review, providing a visual representation of traffic, including eventual spikes. You can export this as PDF using the Save As… button below.
Running from the Command Line
While using the UI is convenient, there are cases where taking a capture via the command line is more practical, for example if you want to integrate network analysis into your automated testing pipeline, or you’re running it on a headless dedicated server.
To do so, you can use tshark, which comes installed with Wireshark. For convenience, make sure to have it added to your PATH during installation.
When running it without parameters, tshark will capture traffic from the first available network interface, and will print a summary of each packet to the standard output.
tshark
We can pick a network interface using the -i option, apply a capture filter using the -f option, and save the output to a capture filter with the -w option, as shown below:
tshark -i en0 -f "tcp port 80" -w ./captures/game_capture.pcap -a duration:600
The last parameter, -a, defines the duration (in seconds) after which the capture will stop. You can also stop the capture after the size reaches a certain limit, using for example -a filesize:1000 (in KB).
If you are unsure which network interfaces are available, you can have a list printed by doing:
tshark -D
Finally, you can read the content of a capture file by doing:
tshark -r /captures/game_capture.pcap
These are just a few practical examples, but nearly every feature offered by Wireshark is available through tshark. You can find the full list of parameters and features here: https://www.wireshark.org/docs/man-pages/tshark.html
Top comments (1)
I usually truncate to 128bytes or there abouts gets layer2 layer 3 headers which is enough for sequence numbers :P