Mensaje de error
state=error: certificate verify failed (hostname mismatch)
También se muestra como
- OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 peeraddr=127.0.0.1:8443 state=error: certificate verify failed (hostname mismatch)
Mensaje completo: «SSL_connect returned=1 errno=0 peeraddr=<ip>:<port> state=error: certificate verify failed (hostname mismatch)». El propio nombre de host no forma parte del mensaje; compara la URL con el certificado.
Ruby openssl (Net::HTTP verify_hostname, default true) — OpenSSL::SSL::SSLError from SSL_connect
Qué significa
La cadena es de confianza, pero el nombre de host al que se conectó Net::HTTP no aparece en los nombres alternativos del sujeto del certificado. Las versiones actuales de Ruby dejan que OpenSSL compruebe el nombre de host durante el handshake (verify_hostname), así que el problema aparece como un fallo de verificación del certificado; las versiones antiguas de Ruby lanzaban, después de conectarse, un error aparte: «hostname … does not match the server certificate».
Por qué ocurre
El certificado no cubre este nombre
frecuenteSubdominios, el dominio sin subdominio o hosts renombrados que faltan en la lista SAN.
Conexión por IP o por un alias interno
frecuenteClientes de bases de datos, de Redis o de API configurados con direcciones IP o nombres de contenedor.
El servidor devolvió su certificado predeterminado
ocasionalUn proxy que no conoce el nombre solicitado sirve el certificado de otro sitio.
Cómo solucionarlo
- 1.
Comparar la lista SAN con el host
El mensaje no incluye los nombres, así que imprímelos desde el certificado.
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -ext subjectAltName - 2.
Usar el nombre del certificado y fijar la dirección
Net::HTTP#ipaddr= se conecta a una IP concreta mientras que el SNI y la verificación usan el nombre de host.
ruby # Connect to a specific address but verify the certificate's name (Net::HTTP#ipaddr=) http = Net::HTTP.new("www.example.com", 443) http.ipaddr = "10.0.0.5" http.use_ssl = true http.get("/health") - 3.
Volver a emitir con todos los nombres en uso
Añade los nombres que faltan a subjectAltName.
bash openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \ -addext "subjectAltName=DNS:api.example.com,DNS:www.example.com"