OpenSSL (server side, mutual TLS)OpenSSL CLI
错误信息
SSL routines:tls_process_client_certificate:peer did not return a certificate
也可能输出为
- error:0A0000C7:SSL routines::peer did not return a certificate
OpenSSL 3.x 记录的是“error:0A0000C7:SSL routines:tls_process_client_certificate:peer did not return a certificate:<source>”。nginx 不走这条路径:配置 ssl_verify_client on 时,它会完成握手,然后返回 HTTP 400“No required SSL certificate was sent”。
OpenSSL (server side, mutual TLS) — SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE
含义
这是双向 TLS 握手失败在服务器端留下的记录:服务器要求客户端证书(SSL_VERIFY_FAIL_IF_NO_PEER_CERT),而客户端没有发送。服务器随后发送告警并中止握手(TLS 1.3 中为 certificate_required,TLS 1.2 中为 handshake_failure),客户端看到的是一个告警错误。
原因
客户端没有配置证书
常见新的部署、轮换后没有同步到客户端的机密,或者没有拿到证书和密钥的库。
负载均衡器的健康检查和监控
常见健康检查工具连接时通常不带客户端证书;如果服务器对每个连接都要求客户端证书,它们就会源源不断地产生这样的日志行。
客户端找不到与服务器 CA 列表相符的证书
偶见浏览器和一些库只会提供由服务器公布的某个 CA 签发的证书;否则它们会发送空的证书消息。
修复方法
- 1.
配置客户端证书
把证书和密钥提供给客户端,并用 curl --cert/--key 测试。
bash # Test from the client side with a certificate curl --cert client.pem --key client.key https://mtls.example.com/ - 2.
在必要的地方把证书设为可选
同时还要响应健康检查或提供公开路径的服务器,可以以可选方式请求证书,再按 location 分别强制要求。
text # nginx: request but do not require a certificate on paths that must stay open (health checks) ssl_verify_client optional; location /internal/ { if ($ssl_client_verify != SUCCESS) { return 403; } } - 3.
检查服务器公布的 CA 名称
客户端证书的颁发者必须在服务器发送的列表中,否则自动选择证书的客户端不会提供任何证书。
bash # The CA list the server advertises must include the issuer of the client certificates openssl s_client -connect mtls.example.com:443 -servername mtls.example.com </dev/null 2>/dev/null \ | sed -n '/Acceptable client certificate CA names/,/^Requested/p'