gRPC 客户端不返回证书

如何解决gRPC 客户端不返回证书

我正在尝试使用 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,tsiGRPC_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","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_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","target_address":"ipv6:[::1]:50051"}]}

解决方法

gRPC 团队您好! 代码对我来说看起来不错。从错误消息来看,服务器似乎无法接收客户端的证书,而您显然已经在客户端代码中设置了它们。您的客户端证书是否可能存在一些客户端堆栈无法识别的格式问题?

为了确保这不是客户端证书的问题,您可以简单地将客户端证书替换为服务器的证书(以及私钥),然后看看它是否有效,因为它们都由同一个 CA 签名。

如果问题仍然存在,那么我们至少知道客户的证书是好的。我可能会在我的最后重现,看看我是否能看到同样的错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?