Wireshark blog post: 2021-01-18 rework (#598)

* Wireshark blog post: 2021-01-18 rework + 01-20 edits

* Tweak about preloading of msg defs from .proto

Co-authored-by: huangqiangxiong <qiangxiong.huang@qq.com>

* More updates following review + new images

Co-authored-by: huangqiangxiong <qiangxiong.huang@qq.com>
This commit is contained in:
Patrice Chalin 2021-01-21 11:37:42 -05:00 committed by GitHub
parent ec08a198a2
commit 64ae35d58a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 128 additions and 85 deletions

View File

@ -1,21 +1,22 @@
---
draft: true
spelling: cSpell:ignore addressbook Huang pcapng Qiangxiong subdissectors tcpdump Wireshark
spelling: cSpell:ignore addressbook Chalin Huang pcapng Qiangxiong subdissectors tcpdump Wireshark
title: Analyzing gRPC messages using Wireshark
date: 2020-12-04
author:
name: Huang Qiangxiong
date: 2021-01-20
authors:
- name: Huang Qiangxiong
link: https://github.com/huangqiangxiong
- name: Patrice Chalin (editor)
link: https://github.com/chalin
---
[Wireshark](https://www.wireshark.org) is an open source network protocol
analyzer, which can be used for protocol development, network troubleshooting,
and education. Wireshark lets you analyze gRPC messages that are transferred
over the wire (network), and learn about the binary wire format of these
messages.
analyzer that can be used for protocol development, network troubleshooting, and
education. Wireshark lets you analyze gRPC messages that are transferred over
the network, and learn about the binary format of these messages.
In this post you'll learn how to configure and use the Wireshark [gRPC
dissector][] and the [Protocol Buffers (Protobuf) dissector][], which are
In this post, you'll learn how to configure and use the Wireshark [gRPC
dissector][] and the [Protocol Buffers (Protobuf) dissector][pbd], which are
protocol-specific components that allow you to analyze gRPC messages with
Wireshark.
@ -24,13 +25,13 @@ Wireshark.
The main features of the gRPC and Protobuf dissectors are the following:
- Support dissecting (decoding) gRPC messages serialized in the
protocol buffer wire format or as JSON
[protocol buffer wire format][] or as JSON
- Support dissecting gRPC messages of unary, server streaming, client streaming,
and bidirectional streaming RPC calls
- Enhanced dissection of serialized protocol buffers data by allowing
you do the following:
you to do the following:
- Load relevant `.proto` files
- Register your own subdissectors for protocol buffer fields of type `byte` or
`string`
@ -38,34 +39,34 @@ The main features of the gRPC and Protobuf dissectors are the following:
## Capturing gRPC traffic
This post focuses on the analysis of captured gRPC messages. To learn how to
store network traffic in _capture files_, see the [Capturing Live Network
Data][] section of the [Wireshark Users Guide][].
store network traffic in _capture files_, see [Capturing Live Network Data][]
from the [Wireshark Users Guide][].
{{< alert title="Note" color="info" >}}
Currently, only **plain text** gRPC messages can be parsed by Wireshark. While
Currently, Wireshark can only parse **plain text** gRPC messages. While
[Wireshark supports TLS dissection][], it requires per-session secret keys. As
of the time of writing, gRPC libraries do not support the exporting of such
keys.
of the time of writing, the only [Go gRPC][] supports the exporting such keys.
To learn how to export keys using Go gRPC -- and other languages as support
becomes available -- see [How to Export TLS Master keys of gRPC][].
[Go gRPC]: /docs/languages/go
[How to Export TLS Master keys of gRPC]: https://gitlab.com/wireshark/wireshark/-/wikis/How-to-Export-TLS-Master-keys-of-gRPC
[languages]: /docs/languages
[Wireshark supports TLS dissection]: https://gitlab.com/wireshark/wireshark/-/wikis/tls
{{</alert>}}
## Examples
## Example
There are some examples to show how to use the Wireshark Protobuf and gRPC
dissectors. You can get more details about these examples from [Wireshark
Protobuf wiki page](https://gitlab.com/wireshark/wireshark/-/wikis/Protobuf) and
[Wireshark gRPC wiki page](https://gitlab.com/wireshark/wireshark/-/wikis/gRPC)
on Wireshark official website.
Let's walk through the setup necessary to analyze previously-captured messages
that were generated by a slightly extended version of the _address book_ app
used in the [Protocol Buffers tutorials][].
### Sample .proto files
### Address book `.proto` files
These `.proto` files will be used in the following examples.
The content of `addressbook.proto`:
The app's main protocol file is `addressbook.proto`:
```protobuf
// This file comes from the official Protobuf example with a little modification.
syntax = "proto3";
package tutorial;
import "google/protobuf/timestamp.proto";
@ -96,14 +97,17 @@ message AddressBook {
}
```
According to the line `'import "google/protobuf/timestamp.proto"'`, the file
`addressbook.proto` depends on one of [Protocol Buffers Well-Known
Types](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf).
This file is identical to the [Protocol Buffers tutorial version][pb-ab.proto],
except for the additional `portrait_image` field.
The content of `person_search_service.proto`:
Note the `import` statement at the top of the file, it is used to import
`Timestamp`, which is one of many [Protocol Buffers Well-Known Types][].
Our variant of the app also defines a _person-search_ service that can be used
to search for address book entries based on selected `Person` attributes. The
service is defined in `person_search_service.proto`:
```protobuf
// A gRPC service that searches for persons based on certain attributes.
syntax = "proto3";
package tutorial;
import "addressbook.proto";
@ -119,63 +123,94 @@ service PersonSearchService {
}
```
The file `person_search_service.proto` relies on file `addressbook.proto`.
Because the service uses the `Person` type defined in `addressbook.proto`,
the address book `.proto` is imported at the start of the file.
### Protobuf Search Paths Settings
### Setting protobuf search paths
You can tell Wireshark where to find *.proto files by setting *'Protobuf Search
Paths'* at the Protobuf protocol preferences. If both the files
`addressbook.proto` and `person_search_service.proto` are in directory
`d:/protos/my_proto_files` and the real path of the dependent file
`"google/protobuf/timestamp.proto"` is
`d:/protos/protobuf-3.4.1/include/google/protobuf/timestamp.proto` (in Protobuf
official library directory `d:/protos/protobuf-3.4.1/include`). You should add
the `d:/protos/protobuf-3.4.1/include/` and `d:/protos/my_proto_files` paths
into *'Protobuf Search Paths'* table and make the *'Load all files'* option of
the `'d:/protos/my_proto_files'` record enabled for preloading the message
definitions from the `addressbook.proto` file:
![wireshark_protobuf_search_paths](/img/wireshark_protobuf_search_paths.png)
This preferences dialog can be found by menu
'Edit->Preferences->Protocols->ProtoBuf->Protobuf search paths'.
Wireshark gives the most meaningful decodings when it knows about the `.proto`
files used by the apps whose messages you are analyzing.
### gRPC Sample Capture files
You can tell Wireshark where to find `.proto` files by setting the **Protobuf
Search Paths** in the preferences accessible from the **Edit** menu under
**Preferences \> Protocols \> Protobuf**.
There are two gRPC sample capture files
[grpc_person_search_protobuf_with_image.pcapng](https://gitlab.com/wireshark/wireshark/-/wikis/uploads/f6fcdceb0248669c0b057bd15d45ab6f/grpc_person_search_protobuf_with_image.pcapng)
and
[grpc_person_search_json_with_image.pcapng](https://gitlab.com/wireshark/wireshark/-/wikis/uploads/88c03db83efb2e3253c88f853d40477b/grpc_person_search_json_with_image.pcapng)
on the [SampleCaptures
page](https://gitlab.com/wireshark/wireshark/-/wikis/SampleCaptures) of
Wireshark. The difference between the two captures is that the message of former
is serialized in Protobuf, and the latter is serialized in JSON.
If our example app's `.proto` files are in the `d:/protos/my_proto_files` directory,
and the official Protobuf library directory is
`d:/protos/protobuf-3.4.1/include`, then add these two paths as _source
directories_ like this:
To decode sample captures as gRPC message, you must decode the traffic on TCP
port 50051 and 50052 as HTTP2:
![wireshark_decode_as_dialog](/img/wireshark_decode_as_dialog.png)
![Protobuf-search-paths dialog](/img/wireshark_protobuf_search_paths.png)
This is a screenshot of the gRPC service request message of
[grpc_person_search_protobuf_with_image.pcapng](https://gitlab.com/wireshark/wireshark/-/wikis/uploads/f6fcdceb0248669c0b057bd15d45ab6f/grpc_person_search_protobuf_with_image.pcapng):
![wireshark_grpc_protobuf_search_request](/img/wireshark_grpc_protobuf_search_request.png)
That shows searching for the Person objects of Jason and Lily based on their
names.
By selecting the **Load all files** option for the app's protocol directory you
enable preloading of message definitions from the `addressbook.proto` and
`person_search_service.proto` files.
Since the `Search` operation is defined as the server streaming RPC mode, the
Person objects can be return back to client one after another:
![wireshark_grpc_protobuf_search_response](/img/wireshark_grpc_protobuf_search_response.png)
### Loading a capture file
You may have noticed that the `portrait_image` of bytes type is parsed as a
PNG data. It's because we register the PNG dissector in the `"protobuf_field"`
dissector table for parsing the value of field `portrait_image` as picture by
putting following Lua script `'protobuf_portrait_field.lua'` into the 'plugins'
subdirectory of 'Personal configuration' directory:
From the Wireshark [SampleCaptures page][], download the following sample gRPC
capture file created by running the app and issuing a search request:
[grpc_person_search_protobuf_with_image.pcapng][].
```lua
do
local protobuf_field_table = DissectorTable.get("protobuf_field")
local png_dissector = Dissector.get("png")
protobuf_field_table:add("tutorial.Person.portrait_image", png_dissector)
end
```
Select **Open** from the **File** menu to load the capture file in Wireshark.
Wireshark displays, in order, all of the network traffic from the capture file
in the **Packet-list pane** at the top of the window.
Select an entry from the packet-list pane and Wireshark will decode it and show
its details in the lower pane like this:
![Packet-list and packet-detail panes](/img/wireshark_after_file_load.png)
Select an entry from the details pane to see the byte sequence corresponding to
that entry:
![Packet bytes](/img/wireshark_packet_bytes.png)
### Setting port traffic type
The app's gRPC traffic was captured on port 50051. Before you can decode the
port's messages, you need to register the port as carrying HTTP2 traffic; do
this through the **Decode As** dialog, which you access from the **Analyze**
menu (or right-click on an entry from the packet-list pane):
![Decode-as dialog](/img/wireshark_decode_as_dialog.png)
Look at the packet-list pane and you'll see that Wireshark is now decoding HTTP2
and gRPC messages:
![Packets are decoded as HTTP2 and gRPC messages](/img/wireshark_http2_grpc.png)
### Decoding the search request message
Select the first gRPC message sent to port 50051, it corresponds to the sample's
service request message. This is how Wireshark dissects the gRPC request:
![Decoded search request](/img/wireshark_grpc_protobuf_search_request.png)
By examining the HTTP2 message header `path` field, you'll see the URL to the
app's service (`/tutorial.PersonSearchService`), followed by the name of the
invoked RPC (`Search`).
The `content-type`, which is set by the gRPC library, informs Wireshark that the
HTTP2 message content is a gRPC message. By examining the decoded Protocol
Buffers message of the sample gRPC request, you can see that the search request
is for the names "Jason" and "Lily".
### Decoding the server-streamed response
Since the `Search` RPC response is server-streaming, `Person` objects can be
returned to the client one after another.
The response port, which can differ for each RPC call, is 51035 in the sample
capture file. Select the second `Person` message returned in the response stream
to see its details:
![Decoded search response](/img/wireshark_grpc_protobuf_search_response.png)
By registering subdissectors, 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][].
## History of gRPC and Protocol Buffers support
@ -193,12 +228,20 @@ support of gRPC and Protocol Buffers:
## Learn more
- [Wireshark Users Guide][]
- [gRPC dissector][]
- [Protocol Buffers (Protobuf) dissector][]
Interested in learning more? Start with the [Wireshark Users Guide][]. For more
details concerning the example used in this post, as well as other sample
capture files containing gRPC messages, see the [gRPC dissector][] and [Protocol
Buffers dissector][pbd] wiki pages.
[Capturing Live Network Data]: https://www.wireshark.org/docs/wsug_html_chunked/ChapterCapture.html
[gRPC dissector]: https://gitlab.com/wireshark/wireshark/-/wikis/gRPC
[Protocol Buffers (Protobuf) dissector]: https://gitlab.com/wireshark/wireshark/-/wikis/Protobuf
[grpc_person_search_protobuf_with_image.pcapng]: https://gitlab.com/wireshark/wireshark/-/wikis/uploads/f6fcdceb0248669c0b057bd15d45ab6f/grpc_person_search_protobuf_with_image.pcapng
[pb-ab.proto]: https://github.com/protocolbuffers/protobuf/blob/master/examples/addressbook.proto
[protocol buffer wire format]: https://developers.google.com/protocol-buffers/docs/encoding
[pbd]: https://gitlab.com/wireshark/wireshark/-/wikis/Protobuf
[Protocol Buffers tutorials]: https://developers.google.com/protocol-buffers/docs/tutorials
[Protocol Buffers Well-Known Types]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf
[Protobuf field subdissectors]: https://gitlab.com/wireshark/wireshark/-/wikis/Protobuf#protobuf-field-subdissectors
[SampleCaptures page]: https://gitlab.com/wireshark/wireshark/-/wikis/SampleCaptures
[Timestamp]: https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp
[Wireshark Users Guide]: https://www.wireshark.org/docs/wsug_html_chunked/

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 21 KiB