Mensagem de erro
SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48)
Também aparece como
- SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
- error:0A000418:SSL routines::tlsv1 alert unknown ca
O nginx o registra no nível info como “SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48) while SSL handshaking, client: …”. A CLI do openssl imprime “…:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:…”. Clientes OpenSSL enviam esse mesmo alerta para cadeias não confiáveis, autoassinadas e incompletas.
nginx error log / OpenSSL — TLS alert 48 (unknown_ca) received from the peer
O que significa
O outro lado da conexão abortou o handshake com o alerta TLS 48 (unknown_ca): não conseguiu ligar o certificado que recebeu a uma CA em que confia. No log de um servidor (como aqui, do nginx), isso significa que um cliente recusou o certificado do servidor. Em um cliente, significa que o servidor recusou o certificado de cliente no TLS mútuo. O lado que registra o alerta nunca é o lado que tem o problema: a causa está no certificado enviado ao peer.
Por que acontece
Log do servidor: os clientes não confiam no certificado do servidor
comumCertificados autoassinados ou de uma CA privada, um intermediário ausente ou um certificado destinado a uso interno exposto a clientes públicos. Cada cliente que falha (curl, clientes de API, monitoramento) deixa uma linha dessas.
Lado do cliente: o servidor não confia no seu certificado de cliente
comumNo TLS mútuo, o certificado de cliente vem de uma CA que o servidor não está configurado para aceitar, ou o cliente deixa de enviar o próprio intermediário.
Scanners e sondagens
ocasionalScanners que varrem toda a internet se conectam sem confiar em nada e abortam com esse alerta; linhas isoladas vindas de endereços desconhecidos são inofensivas.
Como corrigir
- 1.
Descobrir qual certificado foi rejeitado
Se o alerta está no log do servidor, teste a cadeia do servidor de fora; em um cliente com TLS mútuo, verifique o certificado de cliente com a CA que o servidor espera.
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.
Servidor: servir uma cadeia completa e publicamente confiável
Para endpoints públicos, use um certificado de uma CA pública e configure a cadeia completa. Para endpoints internos, garanta que todos os clientes tenham a raiz interna.
text # nginx: the chain clients need, leaf first ssl_certificate /etc/nginx/tls/fullchain.pem; ssl_certificate_key /etc/nginx/tls/privkey.pem; - 3.
TLS mútuo: emitir os certificados de cliente pela CA confiável
Verifique o certificado de cliente com a CA configurada no servidor (ssl_client_certificate no nginx) e envie o intermediário do cliente junto com o certificado dele.
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/
Erros relacionados
SSL routines:ssl3_read_bytes:ssl/tls alert bad certificateOpenSSLSSL routines:ssl3_read_bytes:tlsv13 alert certificate requiredOpenSSL (client side)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)remote error: tls: unknown certificate authorityGo crypto/tls