gRPC流式连接Envoy报错:Cannot check peer: missing selected ALPN property
我用C++开发了一对无证书的gRPC流式服务端与客户端,原本运行正常。现在想把Envoy作为服务端网关,实现客户端与Envoy间通过带证书的gRPC连接,Envoy与服务端间为无加密连接,但部署后始终报错:
StreamData rpc failed: failed to connect to all addresses; last error: UNKNOWN: ipv4:172.16.0.3:1444: Cannot check peer: missing selected ALPN property.
我的机器是CentOS 7,OpenSSL版本为OpenSSL 1.1.1k 25 Mar 2021,相关代码与Envoy配置参考对应issue内容。
这个错误核心是gRPC TLS连接的ALPN协商异常——gRPC基于HTTP/2,要求TLS握手时必须协商出h2协议,否则会触发该错误,可从以下方向排查修复:
1. 修正客户端gRPC TLS配置
确保客户端创建gRPC通道时,显式指定ALPN协议列表包含h2。C++代码示例:
grpc::SslCredentialsOptions ssl_opts; // 加载客户端证书、根证书等必要配置 ssl_opts.alpn_protos = {"h2"}; auto creds = grpc::SslCredentials(ssl_opts); auto channel = grpc::CreateChannel("envoy地址:端口", creds);
若未显式设置ALPN列表,gRPC可能不会自动添加h2,导致与Envoy握手协商失败。
2. 调整Envoy监听配置
在Envoy的监听配置中,需确保TLS上下文开启ALPN并指定支持h2协议,关键配置片段:
listeners: - name: listener_0 address: socket_address: { address: 0.0.0.0, port_value: 1444 } filter_chains: - transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext common_tls_context: tls_params: alpn_protocols: ["h2"] # 必须明确指定h2 tls_certificates: - certificate_chain: { filename: "/path/to/server.crt" } private_key: { filename: "/path/to/server.key" } # 其余HTTP连接管理器、路由配置保持正常设置
3. 确认gRPC与OpenSSL版本兼容性
你的OpenSSL 1.1.1k本身支持ALPN,但需确保gRPC编译时链接的是该版本。CentOS7默认自带OpenSSL 1.0.2(对应libssl.so.10),若gRPC链接的是旧版本会导致ALPN功能异常。可通过以下命令检查:
ldd /path/to/你的grpc客户端二进制文件 | grep ssl
若显示旧版本,需重新编译gRPC并指定链接OpenSSL 1.1.1k:
cmake -DgRPC_SSL_PROVIDER=package -DOPENSSL_ROOT_DIR=/path/to/openssl-1.1.1k .. make -j$(nproc)
4. 验证Envoy到服务端的链路
虽然是无加密连接,仍需确认Envoy集群配置正确指向服务端gRPC端口,且服务端正常监听。可在Envoy机器上用grpcurl测试:
grpcurl -plaintext 服务端IP:端口 list
若服务端能返回正常服务列表,说明该链路无问题,故障仍聚焦在客户端-Envoy的TLS/ALPN环节。
内容的提问来源于stack exchange,提问作者Yves

