RSS

使用 Wireshark 分析 gRPC 消息

Wireshark 是一款开源网络协议分析器,可用于协议开发、网络故障排除和教育。Wireshark 让您可以分析通过网络传输的 gRPC 消息,并了解这些消息的二进制格式。

在这篇文章中,您将学习如何配置和使用 Wireshark 的 gRPC 解析器Protocol Buffers (Protobuf) 解析器,这些都是特定于协议的组件,允许您使用 Wireshark 分析 gRPC 消息。

特性

gRPC 和 Protobuf 解析器的主要特性如下:

  • 支持解析(解码)以 protocol buffer 传输格式 序列化或作为 JSON 序列化的 gRPC 消息。

  • 支持解析一元、服务器流式、客户端流式和双向流式 RPC 调用中的 gRPC 消息。

  • 通过允许您执行以下操作,增强了对序列化 protocol buffers 数据的解析:

    • 加载相关 .proto 文件
    • bytestring 类型的 protocol buffer 字段注册您自己的子解析器

捕获 gRPC 流量

本文侧重于捕获的 gRPC 消息的分析。要了解如何将网络流量存储在 *捕获文件* 中,请参阅 Wireshark 用户指南 中的 捕获实时网络数据

示例

让我们来了解一下分析之前捕获的消息所需的设置,这些消息是由《Protocol Buffers 教程》中使用的 *地址簿* 应用程序的略微扩展版本生成的。

地址簿 .proto 文件

该应用程序的主要协议文件是 addressbook.proto

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;
}

此文件与 Protocol Buffers 教程版本 相同,只是增加了 portrait_image 字段。

请注意文件顶部的 import 语句,它用于导入 Timestamp,这是众多 Protocol Buffers 知名类型 之一。

我们的应用程序变体还定义了一个 *人员搜索* 服务,可用于根据选定的 Person 属性搜索地址簿条目。该服务在 person_search_service.proto 中定义:

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) {}
}

由于该服务使用了 addressbook.proto 中定义的 Person 类型,因此地址簿的 .proto 文件在文件开头被导入。

设置 Protobuf 搜索路径

当 Wireshark 了解您正在分析的应用程序所使用的 .proto 文件时,它会提供最有意义的解码。

您可以通过在 **Edit** 菜单下 **Preferences > Protocols > Protobuf** 中访问的首选项中设置 **Protobuf Search Paths** 来告诉 Wireshark 在哪里找到 .proto 文件。

如果我们的示例应用程序的 .proto 文件位于 d:/protos/my_proto_files 目录中,并且官方 Protobuf 库目录是 d:/protos/protobuf-3.4.1/include,那么像这样添加这两个路径作为 *源目录*:

Protobuf-search-paths dialog

通过为应用程序的协议目录选择 **Load all files** 选项,您可以预加载来自 addressbook.protoperson_search_service.proto 文件的消息定义。

加载捕获文件

从 Wireshark SampleCaptures 页面,下载通过运行应用程序并发出搜索请求创建的以下 gRPC 示例捕获文件:grpc_person_search_protobuf_with_image.pcapng

从 **File** 菜单中选择 **Open** 以在 Wireshark 中加载捕获文件。Wireshark 会在窗口顶部的 **Packet-list pane** 中按顺序显示捕获文件中的所有网络流量。

从数据包列表窗格中选择一个条目,Wireshark 将对其进行解码并在下部窗格中显示其详细信息,如下所示:

Packet-list and packet-detail panes

从详细信息窗格中选择一个条目,查看该条目对应的字节序列

Packet bytes

设置端口流量类型

应用程序的服务器端端口是 50051。客户端端口(每个 RPC 调用都不同)在示例捕获文件中是 51035。

您需要告诉 Wireshark 这些端口承载的是 HTTP2 流量。通过 **Decode As** 对话框进行此操作,您可以从 **Analyze** 菜单(或右键单击数据包列表窗格中的条目)访问该对话框。您只需注册服务器端端口:

Decode-as dialog

查看数据包列表窗格,您会看到 Wireshark 现在正在解码 HTTP2 和 gRPC 消息

Packets are decoded as HTTP2 and gRPC messages

解码搜索请求消息

选择发送到端口 50051 的第一个 gRPC 消息,它对应于示例的服务请求消息。这是 Wireshark 解析 gRPC 请求的方式:

Decoded search request

通过检查 HTTP2 消息头中的 path 字段,您将看到应用程序服务的 URL (/tutorial.PersonSearchService),后跟所调用 RPC 的名称 (Search)。

由 gRPC 库设置的 content-type 告知 Wireshark 该 HTTP2 消息内容是一个 gRPC 消息。通过检查示例 gRPC 请求的解码后的 Protocol Buffers 消息,您可以看到搜索请求是针对名称“Jason”和“Lily”的。

解码服务器流式响应

由于 Search RPC 响应是服务器流式的,因此 Person 对象可以一个接一个地返回给客户端。

选择响应流中返回的第二个 Person 消息以查看其详细信息:

Decoded search response

通过注册子解析器,您可以让 Wireshark 进一步解码 bytestring 类型的字段。例如,要了解如何为 portrait_image 字段注册 PNG 解码器,请参阅 Protobuf 字段子解析器

gRPC 和 Protocol Buffers 支持的历史

以下是 Wireshark 版本与 gRPC 和 Protocol Buffers 支持相关的简要注释列表:

  • v2.6.0:gRPC 和 Protobuf 解析器的首次发布,不支持 .proto 文件或流式 RPC。
  • v3.2.0:改进了基于 .proto 文件对序列化 protocol buffers 数据的解析,并支持流式 RPC。
  • v3.3.0:改进和增强了 .proto 文件支持,例如基于 protocol buffer 字段值进行捕获文件搜索。
  • v3.4.0:Protocol Buffers Timestamp 时间显示为本地日期时间字符串。

了解更多

有兴趣了解更多吗?从 Wireshark 用户指南 开始。有关本文中使用的示例以及其他包含 gRPC 消息的示例捕获文件的更多详细信息,请参阅 gRPC 解析器Protocol Buffers 解析器 Wiki 页面。