本文へスキップ
ecdsa.com
nginx error log / OpenSSLOpenSSL CLI

エラーメッセージ

SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48)

別の表記

  • SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
  • error:0A000418:SSL routines::tlsv1 alert unknown ca

nginx はこれを info レベルで「SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48) while SSL handshaking, client: …」と記録します。openssl CLI は「…:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:…」と出力します。OpenSSL のクライアントは、信頼されていないチェーン、自己署名のチェーン、不完全なチェーンのいずれに対しても、このアラートを送信します。

nginx error log / OpenSSL — TLS alert 48 (unknown_ca) received from the peer

このエラーの意味

接続の相手側が TLS アラート 48(unknown_ca)でハンドシェイクを中止しました。受け取った証明書を、自身が信頼する CA までチェーンでつなげられなかったということです。サーバーのログ(ここでは nginx のもの)では、クライアントがサーバーの証明書を拒否したことを意味します。クライアント側では、相互 TLS でサーバーがクライアント証明書を拒否したことを意味します。アラートを記録している側が、問題のある側であることはありません。原因は、ピアに送った証明書の側にあります。

発生する理由

修正方法

  1. 1.

    どの証明書が拒否されたかを特定する

    サーバーのログに出ている場合は、外部からサーバーのチェーンをテストしてください。相互 TLS を使うクライアントで出ている場合は、サーバーが想定する CA とクライアント証明書を照合してください。

    bash
    # In a SERVER log: a client rejected the server's certificate (e.g. missing intermediate)
    openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:|Verify return code'
    # On a CLIENT: the server rejected your client certificate (mutual TLS)
  2. 2.

    サーバー:公的に信頼される完全なチェーンを返す

    公開エンドポイントでは、パブリック CA の証明書を使い、完全なチェーンを設定してください。社内エンドポイントでは、すべてのクライアントが社内のルートを持っていることを確認してください。

    text
    # nginx: the chain clients need, leaf first
    ssl_certificate     /etc/nginx/tls/fullchain.pem;
    ssl_certificate_key /etc/nginx/tls/privkey.pem;
  3. 3.

    相互 TLS:信頼される CA からクライアント証明書を発行する

    サーバーに設定されている CA(nginx では ssl_client_certificate)でクライアント証明書を検証し、クライアントの中間証明書をその証明書と一緒に送信してください。

    bash
    # Mutual TLS: is the client certificate issued by the CA the server trusts?
    openssl verify -CAfile server-trusted-client-ca.pem -untrusted client-intermediate.pem client.pem
    # Send the client's intermediate too, if it has one
    cat client.pem client-intermediate.pem > client-chain.pem
    curl --cert client-chain.pem --key client.key https://mtls.example.com/

関連するエラー

署名エラーデータベースをすべて見る