Перейти к содержимому
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: …». CLI-утилита openssl выводит «…: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

    Для публичных эндпоинтов используйте сертификат от публичного 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, указанному в настройках сервера (ssl_client_certificate в nginx), и отправляйте промежуточный сертификат клиента вместе с его сертификатом.

    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/

Связанные ошибки

Открыть всю базу ошибок подписей