Mensaje de error
SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48)
También se muestra como
- SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
- error:0A000418:SSL routines::tlsv1 alert unknown ca
nginx lo registra en el nivel info como «SSL_do_handshake() failed (SSL: error:0A000418:SSL routines::tlsv1 alert unknown ca:SSL alert number 48) while SSL handshaking, client: …». La CLI de openssl imprime «…:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:…». Los clientes OpenSSL envían esta alerta por igual ante cadenas que no son de confianza, autofirmadas o incompletas.
nginx error log / OpenSSL — TLS alert 48 (unknown_ca) received from the peer
Qué significa
El otro extremo de la conexión abortó el handshake con la alerta TLS 48 (unknown_ca): no pudo enlazar el certificado que recibió con una CA de su confianza. En el registro de un servidor (como aquí, de nginx) significa que un cliente rechazó el certificado del servidor. En un cliente significa que el servidor rechazó el certificado de cliente en TLS mutuo. El lado que registra la alerta nunca es el que tiene el problema: la causa está en el certificado que se envió al otro extremo.
Por qué ocurre
Registro del servidor: los clientes no confían en el certificado del servidor
frecuenteCertificados autofirmados o de una CA privada, un intermedio que falta o un certificado pensado para uso interno y expuesto a clientes públicos. Cada cliente que falla (curl, clientes de API, monitorización) deja una de estas líneas.
Lado del cliente: el servidor no confía en tu certificado de cliente
frecuenteEn TLS mutuo, el certificado de cliente procede de una CA que el servidor no está configurado para aceptar, o el cliente omite su intermedio.
Escáneres y sondeos
ocasionalLos escáneres que recorren todo Internet se conectan sin confiar en nada y abortan con esta alerta; las líneas aisladas procedentes de direcciones desconocidas son inofensivas.
Cómo solucionarlo
- 1.
Averiguar qué certificado se rechazó
Si la línea está en el registro de un servidor, prueba la cadena del servidor desde fuera; en un cliente con TLS mutuo, comprueba el certificado de cliente frente a la CA que espera el servidor.
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 una cadena completa y de confianza pública
Para los endpoints públicos, usa un certificado de una CA pública y configura la cadena completa. Para los endpoints internos, asegúrate de que todos los clientes tengan la raíz 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 mutuo: emitir los certificados de cliente desde la CA de confianza
Verifica el certificado de cliente frente a la CA configurada en el servidor (ssl_client_certificate en nginx) y envía el intermedio del cliente junto con su certificado.
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/
Errores 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