有了 Protobuf 基础 的前提,根据官网给出的 Quick Start (Go) 可以很容易的使用 gRPC,了解客户端远程调用服务端函数并返回结果的过程。
本文将使用 Wireshark 抓包查看 gRPC 通信流程,了解基础 gRPC 的请求和返回。
资源下载
你可以下载抓包文件用 Wireshark 直接查看,免去手动抓包,请确认本机的 Wireshark 版本至少应该是 3.6.0+
- 未加密的抓包示例文件 gRPC-helloworld.pcapng
在 Client 中打印 Protobuf 内容
greeter_client/main.go
import (
"encoding/hex"
"google.golang.org/protobuf/proto"
)
func main() {
// ...
p := &pb.HelloRequest{Name: *name}
b, err := proto.Marshal(p)
if err != nil {
log.Fatal("proto marshal failed!")
}
fmt.Println(hex.EncodeToString(b))
}
在官网示例的基础上,修改客户端示例代码,打印将要发送数据的 HEX 格式。
这个就是要发送的数据:0a05776f726c64
使用 Wireshark 抓包未加密的请求
直接打开抓包文件,会看到协议都显示为 TCP,初识 gRPC,一时不知道从何处着手。
进一步了解到 gRPC 基于 HTTP2 协议发送数据,为了让 Wireshark 能自动解析出数据,我们可以在 Wireshark 中点击 “Analyze” - “Decode As...”
在弹出的页面设置指定端口的数据类型为 HTTP2,保存后可以看到 Wireshark 已经正确识别 HTTP2 请求及 gRPC 通信。
上图 13 号配置可以看到调用了远端的 SayHello
方法,也可以看到 HTTP2 协议协商阶段的 SETTINGS,同样我们可以在面板的右下角看到 0a05776f726c64
正是我们之前打印的 HEX 数据,这也从另一个角度说明了 Protobuf 发送的数据虽然看起来编码 “加密” 了,但其实它的字符串数据还是按照原本的内容在传递,未加密的情况下同样不够安全。
另一处值的注意的是左下角,Message 处显示的是 .proto
文件来解析消息,而 Wireshark 此处不知道。
进一步配置 Wireshark 使其可以解析,点击 “Wireshark” - “Proferences...”,在弹出的页面左侧列表的 “Protocols” 下找到 “Protobuf”
我填写的目录,第一个是包含官方示例 helloworld.proto
文件的的路径(/Users/dong/proto-path),另一个是 protoc 工具安装后,它自带的一些 .proto
文件存储路径(/usr/local/include),这个路径下存储着 google/protobuf/*
,如果程序中用到了 Protobuf 内置定义的一些数据类型,则 Wireshark 会到这里查找。
保存后,可见 Unknown 部分已经可以解析出数据类型并正确展示字段值。
使用 Wireshark 解析 TLS gRPC 数据(暂未成功解密)
大概说一下流程吧,因为最近尝试并没有成功在 Wireshark 解密在上篇文章 《gRPC 使用自签名证书开启 TLS 加密》 加密的 TLS 数据。
这里提供一些看起来靠谱资料:How-to-Export-TLS-Master-keys-of-gRPC
文章说,在 Golang 中,可以使用 keyLogWriter(修改 Golang 客户端代码)的特性将数据导出到 /tmp/ssl-keylog.txt,而后在 wireshark 的 TLS 面板加载这个文件。
(Pre)-Master-Secret log filename' (tls.keylog_file)
这里有 Wireshark 介绍 TLS 解析的各项配置:https://wiki.wireshark.org/tls
另外就是通过 keyLogWriter 写入 log 文件的内容格式如下:
另外值得参考的文章
感觉流程上并不复杂,可能有哪些地方我没注意到或者理解错误,近期暂不打算继续花费大量时间深入研究。
等过段时间学习证书、SSL/TLS 相关知识时候再回头尝试。
总结和遗留问题
使用 Wirshark 抓包,了解到 gRPC 基于 HTTP2 协议设计,继承了 HTTP2 的优点。
在配置 Proto 文件后可以解析出 Protobuf 传输的数据。
另外在学习过程中想要测试 gRPC TLS 的加密和解密,目前能加密,不能解密,应该是为对 TLS 和 Wireshark 的了解还不够,Debug 能力不足导致的。