Wireshark[1] is an open source network protocol analyzer that is useful for protocol development, network troubleshooting, and education. By using Wireshark to analyze gRPC protocol, you can examine gRPC messages transmitted over the network and understand their binary format. In this post, youâll learn how to configure and utilize Wiresharkâs gRPC dissector[2] and Protocol Buffers (Protobuf) dissector[3], which are protocol-specific components that allow you to effectively analyze gRPC messages with Wireshark.
characteristic
The main features of gRPC and Protobuf dissectors are as follows:
- Support for parsing (decoding) gRPC messages serialized in the protocol buffer wire format [4] or JSON
- Support parsing gRPC unary messages, server streams, client streams, and bidirectional stream RPC calls
- Enhanced parsing of serialized protocol buffer data, allowing you to do the following:
- Load the relevant .proto files
- Register your own subdissector for a protocol buffer field of type bytes or string
Capturing gRPC traffic
This post focuses on analyzing captured gRPC messages. If you need to learn how to save network traffic in a capture file, see Capturing Live Network Data[6] in the Wireshark User Guide[5] .
NoteCurrently, Wireshark can only parse gRPC plain text messages. WhileWireshark supports TLS parsing[7], it requires per-session keys. At the time of this writing, Go gRPC supports exporting such keys. To learn how to export keys with Go gRPC, as well as support for other languages, seeHow to export gRPCâs TLS master key[8].
example
Letâs go through the necessary setup to analyze previously captured messages generated by a slightly extended version of the address book application used in the Protocol Buffers tutorial [9] .
Address book .proto file
The main protocol file for the application is addressbook.proto:
Code language: javascript
copy
syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phone = 4;
google.protobuf.Timestamp last_updated = 5;
bytes portrait_image = 6;
}
message AddressBook {
repeated Person people = 1;
}
This file is identical to the protocol buffer tutorial version [10] , except for the additional portrait_image field.
Note the import statement at the top of the file, which imports Timestamp, one of many well-known protocol buffer types [11] .
Our application variant also defines a person-search service that can be used to search for address book entries based on selected Person attributes. The service definition is in person_search_service.proto:
Code language: javascript
copy
syntax = "proto3";
package tutorial;
import "addressbook.proto";
message PersonSearchRequest {
repeated string name = 1;
repeated int32 id = 2;
repeated string phoneNumber = 3;
}
service PersonSearchService {
rpc Search (PersonSearchRequest) returns (stream Person) {}
}
Because the service uses the Person type defined in addressbook.proto, addressbook.proto is imported at the beginning of the file.
Set protobuf search path
Wireshark will give the most meaningful decodes when it knows the .proto files used by the application you are analyzing.
You can tell Wireshark where to find .proto files by setting the Protobuf search path in the Edit menu under preferences > Protocols > Protobuf.
If the .proto file of our sample application is in the d:/protos/my_proto_files directory, and the official directory of the Protobuf library is d:/protos/protobuf-3.4.1/include, then add these two paths as source directories as follows:
You can pre-load the message definitions from the addressbook.proto and person_search_service.proto files by selecting the âLoad all filesâ option for the applicationâs protocol directory.
Loading a capture file
From the Wireshark SampleCaptures page [12] , download the following sample gRPC capture file created by running the application and issuing a search request: grpc_person_search_protobuf_with_image.pcapng [13] .
Select âOpenâ from the âFileâ menu to load the capture file in Wireshark. Wireshark displays all network traffic in the capture file in order in the packet list pane at the top of the window.
Select an entry in the Packet-list panel and Wireshark will decode it and display its details in the lower panel, as shown below:
Select an entry from the details pane to view the byte sequence that corresponds to the entry:
Set the port traffic type
The server side port of the app is 50051. The client side port is different for each RPC call and is 51035 in the example capture file.
You need to tell Wireshark that these ports are carrying HTTP2 traffic. You do this via the Decode As dialog, which you can access from the Analyze menu (or by right-clicking an entry in the packet list pane). You only need to register the server-side port:
Take a look at the packet list pane and youâll see that Wireshark is now decoding HTTP2 and gRPC messages:
Decoding the search request message
Select the first gRPC message sent to port 50051, which corresponds to the service request message of the example. Here is Wiresharkâs analysis of the gRPC request:
By inspecting the HTTP2 message header path field, you will see the URL of the application service (/tutorial.PersonSearchService) followed by the name of the RPC being called (Search).
The content-type is set by the gRPC library, which informs Wireshark that the content of the HTTP2 message is a gRPC message. By inspecting the decoded protocol buffer message of a sample gRPC request, we can see that the search request is for the names âJasonâ and âLilyâ.
Decode server streaming response
Since the Search RPC response is a server stream, Person objects can be returned to the client one by one.
Select the second Person message returned in the response flow to view its details:
By registering a subdissector, you can have Wireshark further decode fields of type byte or string. For example, to learn how to register a PNG decoder for the portrait_image field, see Protobuf Field Subdissectors [14] .
History of supporting gRPC and Protocol Buffers
Here is a list of Wiresharkâs version notes for supporting gRPC and Protocol Buffers:
- v2.6.0: First version of gRPC and Protobuf dissectors, no support for .proto files or streaming RPCs.
- v3.2.0: Improved parsing of serialized protocol buffer data based on .proto files, and support for streaming RPC.
- v3.3.0: Improved and enhanced .proto file support, such as capture file searches for protocol buffer field values.
- v3.4.0: Protocol Buffers timestamps [15] are now displayed as locale date-time strings.
Summary
Wireshark is an open-source network protocol analyzer ideal for protocol development, network troubleshooting, and education. This post elaborates on using Wireshark to analyze gRPC protocols by utilizing its gRPC and Protocol Buffers (Protobuf) dissectors. It covers how to decode gRPC messages, including unary and stream messages, by setting up the Protobuf search path and loading relevant .proto files for enhanced analysis. The guide explains capturing gRPC traffic, setting the appropriate port traffic types, and decoding gRPC messages. An example of analyzing captured gRPC traffic from an address book application is provided, demonstrating how Wireshark deciphers service request messages and streaming responses. Historical support updates for gRPC and Protobuf in Wireshark versions are also discussed, highlighting enhancements like improved parsing and support for .proto files.