エラーメッセージ
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 の場合、nginx はハンドシェイクを完了させ、代わりに 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'