【发布时间】:2021-01-04 21:27:08
【问题描述】:
我在 Go 中编写了一个示例 gRPC 客户端和一个服务器,两者都配置为服务器身份验证的 TLS。
客户端 gRPC 调用成功,给我的印象是 TLS 配置正确,否则如果 TLS 握手失败,我希望客户端失败并且不发出 gRPC 请求(即不默认为明文)。
然而,当我将 Wireshark 连接到该网络以嗅探 TCP 数据包时,我得到的结果让我感到困惑。我没有看到任何带有 TLS 的数据包,例如我没有看到 TLS CLIENT HELLO 数据包。
这是因为我误解了我在 Wireshark 中看到的内容,还是我的 gRPC 客户端实际上在执行纯文本 gRPC?
客户端代码如下所示,注意grpc.withTransportCredentials,我认为这意味着它将使用 TLS 或失败,但绝不是纯文本:
// block the dial until connection is successful or 3 sec timeout
dialOptions := []grpc.DialOption{
grpc.WithBlock(),
grpc.WithTimeout(3 * time.Second),
}
// Load TLS Configuration
tlsCredentials, err := LoadTLSCredentials()
if err != nil {
log.Fatalf("Failed to load TLS credentials: %v", err)
}
dialOptions = append(dialOptions, grpc.WithTransportCredentials(tlsCredentials))
// Dial the gRPC server
log.Printf("Dialing %v", *address)
conn, err := grpc.Dial(*address, dialOptions...)
if err != nil {
log.Fatalf("Failed to connect to the server: %v", err)
}
defer conn.Close()
// then this application sets up a gRPC request, and logs the response to stdout,
// in my testing stdout shows the expected gRPC response, so I'd assume TLS is working.
func LoadTLSCredentials() (credentials.TransportCredentials, error) {
rootCA, err := ioutil.ReadFile("ca.cert")
if err != nil {
return nil, err
}
certPool := x509.NewCertPool()
if !certPool.AppendCertsFromPEM(rootCA) {
return nil, fmt.Errorf("Failed to add rootCA to x509 certificate pool")
}
config := &tls.Config{
MinVersion: tls.VersionTLS12,
RootCAs: certPool,
}
return credentials.NewTLS(config), nil
}
这是 Wireshark 的屏幕截图,显示没有 TLS 数据包 而我希望类似于以下内容的内容清楚地显示了一些 TLS 活动(不是我的应用程序,图片来自网络用于说明目的)
我在 Ubuntu 16.04 上运行 Wireshark v2.6.10。源 IP 和目标 IP 与我的 gRPC 客户端和服务器 IP 匹配(两者都是同一 docker 网络上的 docker 容器)。
这并不重要,但从我的客户端代码中可以看出,我在客户端上共享一个根 CA 证书(自签名)。我可以这样做,因为我同时部署了客户端和服务器。
【问题讨论】:
-
你的 grpc 服务器在监听 tls 吗?
-
是的,但我故意省略了该代码,因为我认为这并不重要。如果我的客户端配置了 TLS,如果 TLS 配置错误,我希望客户端会失败,而不是默认为纯文本。
-
非常简单:这是服务器上的内容:serverCert, err := tls.LoadX509KeyPair("service.pem","service.key") tlsConfig := &tls.Config{ MinVersion: tls.版本 TLS12,证书:[]tls.Certificate{serverCert}, }
-
您正在为 TLS 使用非标准端口,特别是通常用于纯 HTTP 的端口。您必须明确告诉 Wireshark 它应该尝试将流量解释为 TLS。
-
@SteffenUllrich 如何告诉 Wireshark 将流量明确解释为 TLS?请注意,我不需要 Wireshark 来解密 TLS 帧,只是为了通知我它们在那里。我认为您的建议类似于wiki.wireshark.org/…。