使用 Wireshark 分析 gRPC 消息
Wireshark 是一个开源网络协议分析器,可用于协议开发、网络故障排除和教育。 Wireshark 允许您分析通过网络传输的 gRPC 消息,并了解这些消息的二进制格式。
在这篇文章中,您将学习如何配置和使用 Wireshark gRPC 解剖器 和 Protocol Buffers (Protobuf) 解剖器,它们是特定于协议的组件,允许您使用 Wireshark 分析 gRPC 消息。
功能
gRPC 和 Protobuf 解剖器的主要功能如下
支持解剖(解码)以 协议缓冲区线格式 或 JSON 序列化的 gRPC 消息
支持解剖一元、服务器流、客户端流和双向流 RPC 调用的 gRPC 消息
通过允许您执行以下操作,增强了序列化协议缓冲区数据的解剖
- 加载相关的
.proto
文件 - 为
byte
或string
类型的协议缓冲区字段注册您自己的子解剖器
- 加载相关的
捕获 gRPC 流量
这篇文章的重点是分析捕获的 gRPC 消息。要了解如何在捕获文件中存储网络流量,请参阅 捕获实时网络数据,摘自 Wireshark 用户指南。
注意
目前,Wireshark 只能解析 纯文本 gRPC 消息。虽然 Wireshark 支持 TLS 解剖,但它需要每个会话的密钥。在撰写本文时,只有 Go gRPC 支持导出此类密钥。要了解如何使用 Go gRPC(以及其他语言,因为支持变得可用)导出密钥,请参阅 如何导出 gRPC 的 TLS 主密钥。示例
让我们逐步完成分析先前捕获的由 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
文件时,它会给出最有意义的解码。
您可以通过在 Wireshark 的首选项中设置 Protobuf 搜索路径 来告知 Wireshark 在哪里查找 .proto
文件。首选项可以通过 编辑 菜单下的 首选项 > 协议 > Protobuf 访问。
如果我们的示例应用程序的 .proto
文件位于 d:/protos/my_proto_files
目录,并且官方 Protobuf 库目录是 d:/protos/protobuf-3.4.1/include
,那么请将这两个路径添加为源目录,如下所示:


通过为应用程序的协议目录选择 加载所有文件 选项,您可以启用从 addressbook.proto
和 person_search_service.proto
文件预加载消息定义的功能。
加载捕获文件
从 Wireshark 的 示例捕获页面,下载以下通过运行应用程序并发出搜索请求创建的示例 gRPC 捕获文件:grpc_person_search_protobuf_with_image.pcapng。
从 文件 菜单中选择 打开 以在 Wireshark 中加载捕获文件。Wireshark 将按照顺序在窗口顶部的 数据包列表窗格 中显示捕获文件中的所有网络流量。
从数据包列表窗格中选择一个条目,Wireshark 将对其进行解码并在下方的窗格中显示其详细信息,如下所示:


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


设置端口流量类型
应用程序的服务端端口是 50051。客户端端口,对于每个 RPC 调用都不同,在示例捕获文件中是 51035。
您需要告诉 Wireshark 这些端口正在传输 HTTP2 流量。通过 解码为 对话框完成此操作,该对话框可从 分析 菜单访问(或右键单击数据包列表窗格中的条目)。您只需要注册服务端端口即可。


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


解码搜索请求消息
选择发送到端口 50051 的第一个 gRPC 消息,它对应于示例的服务请求消息。这就是 Wireshark 如何解析 gRPC 请求的。


通过检查 HTTP2 消息头 path
字段,您将看到应用程序服务的 URL (/tutorial.PersonSearchService
),后跟调用的 RPC 名称 (Search
)。
由 gRPC 库设置的 content-type
会通知 Wireshark HTTP2 消息内容是 gRPC 消息。通过检查示例 gRPC 请求的解码的 Protocol Buffers 消息,您可以看到搜索请求针对名称 “Jason” 和 “Lily”。
解码服务器流式响应
由于 Search
RPC 响应是服务器流式传输,因此可以将 Person
对象逐个返回给客户端。
选择在响应流中返回的第二个 Person
消息以查看其详细信息。


通过注册子解析器,您可以让 Wireshark 进一步解码 byte
或 string
类型的字段。例如,要了解如何为 portrait_image
字段注册 PNG 解码器,请参阅 Protobuf 字段子解析器。
gRPC 和 Protocol Buffers 支持的历史
以下是关于 Wireshark 版本与 gRPC 和 Protocol Buffers 支持相关的简要注释列表。
- v2.6.0:gRPC 和 Protobuf 解析器的第一个版本,不支持
.proto
文件或流式 RPC。 - v3.2.0:改进了基于
.proto
文件序列化协议缓冲区数据的解析,并支持流式 RPC。 - v3.3.0:改进和增强了
.proto
文件支持,例如在协议缓冲区字段值上进行捕获文件搜索。 - v3.4.0:Protocol Buffers Timestamp 时间显示为本地日期时间字符串。
了解更多
有兴趣了解更多吗?从 Wireshark 用户指南 开始。有关本帖中使用的示例以及包含 gRPC 消息的其他示例捕获文件的更多详细信息,请参阅 gRPC 解析器 和 Protocol Buffers 解析器 wiki 页面。