gRPC 客户端不返回证书
Posted
技术标签:
【中文标题】gRPC 客户端不返回证书【英文标题】:gRPC client not returning certificate 【发布时间】:2021-07-05 18:28:51 【问题描述】:我正在尝试使用 c++ 构建具有相互身份验证的 gRPC 应用程序。当我在服务器上设置GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
选项时,客户端不会返回它的证书。服务器显示以下错误:
Handshake failed with fatal error SSL_ERROR_SSL: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate.
没有这个选项,只有服务器经过身份验证,通信正常。
证书链是一个自签名的根 CA,它签署了一个中间 CA,它签署了服务器和客户端证书。我使用以下命令并使用在客户端加载的相同证书测试了连接。
openssl s_client -connect localhost:50051 /
-cert client_cert.pem -key client_pkey.pem /
-CAfile ca-chain.pem /
-state -debug
这没有给我连接错误。 ca-chain.pem 文件包含根 CA 和中间 CA 的串联。
我尝试在 gRPC 上找到任何会导致此问题的内容,但我发现 C++ 的文档非常少...关于可能是什么问题的任何提示?这是我正在使用的代码示例。
客户端代码
/* Set the certificates */
grpc::SslCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = loadCertificate(ca-chain);
ssl_opts.pem_private_key = loadCertificate(client_pkey);
ssl_opts.pem_cert_chain = loadCertificate(client_cert);
/* Override hostname */
grpc::ChannelArguments args;
args.SetSslTargetNameOverride("server");
/* Create the channel */
std::shared_ptr<grpc::ChannelCredentials> creds = grpc::SslCredentials(ssl_opts);
ClientImpl client(grpc::CreateCustomChannel("localhost:50051", creds, args));
服务器代码
std::string server_address("0.0.0.0:50051");
ServerImpl service();
/* Set the certificates */
grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = x509_loadPEM(server_pkey).c_str(), x509_loadPEM(server_cert).c_str() ;
grpc::SslServerCredentialsOptions ssl_opts(GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
//grpc::SslServerCredentialsOptions ssl_opts;
ssl_opts.pem_root_certs = x509_loadPEM(ca_chain);
ssl_opts.pem_key_cert_pairs.push_back(pkcp);
std::shared_ptr<grpc::ServerCredentials> creds;
creds = grpc::SslServerCredentials(ssl_opts);
/* Start the server */
ServerBuilder builder;
builder.AddListeningPort(server_address, creds);
builder.RegisterService(&service);
m_server = builder.BuildAndStart();
更新
这是GRPC_TRACE
设置为transport_security,tsi 和GRPC_VERBOSITY
设置为debug
服务器端
I0705 15:46:59.119538389 11583 ssl_transport_security.cc:220] HANDSHAKE START - before SSL initialization - PINIT
I0705 15:46:59.119574620 11583 ssl_transport_security.cc:220] LOOP - before SSL initialization - PINIT
I0705 15:46:59.119583946 11583 ssl_transport_security.cc:220] LOOP - before SSL initialization - PINIT
I0705 15:46:59.119670552 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read client hello - TRCH
I0705 15:46:59.119686772 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write server hello - TWSH
I0705 15:46:59.119880739 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write certificate - TWSC
I0705 15:46:59.122456250 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write key exchange - TWSKE
I0705 15:46:59.122500516 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write certificate re - TWCR
I0705 15:46:59.122517841 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write server done - TWSD
I0705 15:46:59.124324895 11583 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write server done - TWSD
E0705 15:46:59.124354539 11583 ssl_transport_security.cc:1395] Handshake failed with fatal error SSL_ERROR_SSL: error:1417C0C7:SSL routines:tls_process_client_certificate:peer did not return a certificate.
D0705 15:46:59.124376983 11583 security_handshaker.cc:184] Security handshake failed: "created":"@1625514419.124366009","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":307,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"
D0705 15:46:59.124406454 11583 chttp2_server.cc:124] Handshaking failed: "created":"@1625514419.124366009","description":"Handshake failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":307,"tsi_code":10,"tsi_error":"TSI_PROTOCOL_FAILURE"
客户端
I0705 15:46:59.119384991 11756 ssl_transport_security.cc:220] HANDSHAKE START - before SSL initialization - PINIT
I0705 15:46:59.119435471 11756 ssl_transport_security.cc:220] LOOP - before SSL initialization - PINIT
I0705 15:46:59.119479876 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write client hello - TWCH
I0705 15:46:59.122745953 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write client hello - TWCH
I0705 15:46:59.122815300 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read server hello - TRSH
I0705 15:46:59.123253349 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read server certific - TRSC
I0705 15:46:59.123607078 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read server key exch - TRSKE
I0705 15:46:59.123813288 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read server certific - TRCR
I0705 15:46:59.123855701 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS read server done - TRSD
I0705 15:46:59.123881908 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write client certifi - TWCC
I0705 15:46:59.124188107 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write client key exc - TWCKE
I0705 15:46:59.124227044 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write change cipher - TWCCS
I0705 15:46:59.124253244 11756 ssl_transport_security.cc:220] LOOP - SSLv3/TLS write finished - TWFIN
D0705 15:46:59.124435035 11756 security_handshaker.cc:184] Security handshake failed: "created":"@1625514419.124412434","description":"Handshake read failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":397,"referenced_errors":["created":"@1625514419.124410133","description":"Socket closed","fd":9,"file":"src/core/lib/iomgr/tcp_posix.cc","file_line":781,"grpc_status":14,"target_address":"ipv6:[::1]:50051"]
I0705 15:46:59.124541128 11756 subchannel.cc:1033] Connect failed: "created":"@1625514419.124412434","description":"Handshake read failed","file":"src/core/lib/security/transport/security_handshaker.cc","file_line":397,"referenced_errors":["created":"@1625514419.124410133","description":"Socket closed","fd":9,"file":"src/core/lib/iomgr/tcp_posix.cc","file_line":781,"grpc_status":14,"target_address":"ipv6:[::1]:50051"]
【问题讨论】:
你试过trace logging吗? 用跟踪更新了帖子。目前正在调查。 【参考方案1】:gRPC 团队您好! 代码对我来说看起来不错。从错误消息来看,服务器似乎无法接收客户端的证书,而您显然已经在客户端代码中设置了它们。您的客户端证书是否可能存在一些格式问题,客户端堆栈无法识别这些问题?
为了确保不是客户端证书的问题,您可以简单地用服务器证书(以及私钥)替换客户端证书,看看它是否有效,因为它们都是由同一个 CA 签名的。
如果问题仍然存在,那么我们至少知道客户的证书是好的。我可能会在最后重现,看看是否能看到同样的错误。
【讨论】:
您好,我昨天通过监控TCP跟踪实际上解决了它。你是对的,这是一个格式问题。我理解的“客户端没有发送证书”实际上是“客户端发送了错误的证书”。错误是我的 loadCertificate() 函数。我会将此答案标记为已接受。以上是关于gRPC 客户端不返回证书的主要内容,如果未能解决你的问题,请参考以下文章
Akka-CQRS(10)- gRPC on SSL/TLS 安全连接