Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Solución de problemas11 min de lectura

SSLCertVerificationError: Diagnóstico de fallos de verificación de certificados TLS en Python y clientes API

Una guía práctica para diagnosticar y solucionar SSLCertVerificationError, desde certificados caducados y paquetes de CA faltantes hasta discrepancias de nombre de host y proxies corporativos.

TL;DR

SSLCertVerificationError se produce cuando un cliente TLS no puede validar el certificado del servidor contra su almacén de CA de confianza, el nombre de host solicitado o el período de validez actual. El mensaje de error suele indicar el fallo específico, como un certificado caducado, un certificado autofirmado o la imposibilidad de obtener el certificado del emisor local. Este artículo explica el mecanismo de verificación, recorre un procedimiento de diagnóstico reproducible con openssl y Python, y muestra cómo solucionar cada tipo de fallo sin deshabilitar la verificación. También cubre las ventajas y desventajas de los paquetes de CA personalizados, la interceptación de proxies y cuándo escalar al operador del servidor.

Qué significa realmente SSLCertVerificationError

ssl.SSLCertVerificationError es la excepción de Python para un handshake TLS fallido causado por la validación de certificados. El cliente llegó al servidor, recibió su cadena de certificados y luego la rechazó porque una o más comprobaciones no pasaron. La excepción es una subclase de ssl.SSLError, por lo que el código que captura SSLError también la capturará.

El texto del error después de CERTIFICATE_VERIFY_FAILED es la parte importante. Los sufijos comunes incluyen certificate has expired, self-signed certificate, unable to get local issuer certificate, hostname mismatch y certificate is not yet valid. Cada uno apunta a una solución diferente, así que lea el sufijo antes de cambiar cualquier código.

Este error es distinto de una conexión rechazada o un tiempo de espera agotado. Si la conexión TCP nunca se completa, verá ConnectionError o TimeoutError en su lugar. Los errores de verificación significan que la ruta de red funcionó y la capa TLS tomó una decisión de confianza.

  • Caducado o aún no válido: la ventana de validez del certificado no incluye la hora actual.
  • Autofirmado o emisor no confiable: la cadena termina en un certificado en el que el cliente no confía.
  • No se puede obtener el certificado del emisor local: el servidor no envió un certificado intermedio, o el paquete de CA del cliente está incompleto.
  • Discrepancia de nombre de host: los nombres alternativos del sujeto del certificado no incluyen el host que solicitó.

Suposiciones y requisitos previos para el flujo de trabajo de diagnóstico

Los ejemplos a continuación asumen Python 3.8 o posterior, la biblioteca requests y la herramienta de línea de comandos openssl. También asumen que puede llegar al host de destino en el puerto 443. Si está trabajando dentro de un contenedor o ejecutor de CI, confirme que se permite TLS saliente antes de depurar certificados.

Para los endpoints RPC de blockchain, se aplican las mismas reglas de verificación. Un endpoint gestionado como los descritos en la guía de endpoints RPC multicadena debería presentar un certificado de confianza pública. Si no lo hace, trátelo como una señal para inspeccionar la configuración del endpoint en lugar de deshabilitar la verificación.

El modelo mental de verificación TLS

La verificación de certificados tiene cuatro comprobaciones independientes. Primero, el cliente construye una cadena desde el certificado hoja del servidor a través de los intermedios hasta una raíz en su almacén de confianza. Segundo, comprueba que cada certificado de la cadena esté dentro de su período de validez. Tercero, comprueba que los nombres alternativos del sujeto del certificado hoja coincidan con el nombre de host utilizado en la conexión. Cuarto, comprueba que el certificado hoja esté autorizado para la autenticación del servidor.

Un fallo en cualquier comprobación produce SSLCertVerificationError. El mensaje de error identifica qué comprobación falló, pero la causa subyacente puede estar en cualquiera de los dos lados. Un certificado caducado es un problema del servidor. Un paquete de CA desactualizado es un problema del cliente. Un proxy corporativo que termina TLS es un problema de política de red. Separar estos es el núcleo del diagnóstico.

Reproducir el error con un cliente Python mínimo

Comience con un script pequeño que realice una solicitud HTTPS e imprima la excepción completa. Esto aísla el fallo de la lógica de la aplicación y de los envoltorios de reintento.

import requests
from requests.exceptions import SSLError

url = "https://RPC_HOST"  # replace with the host you are debugging

try:
    response = requests.get(url, timeout=10)
    print("status", response.status_code)
except SSLError as exc:
    print(type(exc).__name__)
    print(exc)

Inspeccionar la cadena de certificados del servidor con openssl

El comando openssl s_client muestra exactamente lo que envía el servidor. Ejecútelo con -servername para que SNI se establezca correctamente, y con -showcerts para imprimir la cadena completa.

openssl s_client -connect RPC_HOST:443 -servername RPC_HOST -showcerts </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

Interpretar el resultado de la verificación

La salida del comando anterior le indica qué comprobación es probable que esté fallando. Compare las fechas notBefore y notAfter con la hora UTC actual. Compare las entradas subjectAltName con el nombre de host que solicitó. Compare el emisor con los certificados raíz en el almacén de confianza de su cliente.

La siguiente tabla es un procedimiento, no un conjunto de resultados medidos. Complete los valores observados de su propio entorno.

  • | Comprobación | Comando o campo | Cómo se ve un aprobado | Qué implica un fallo |
  • | Validez | salida de -dates | La hora actual está entre notBefore y notAfter | Certificado del servidor caducado o desfase de reloj |
  • | Nombre de host | subjectAltName | El host solicitado aparece en la lista | Certificado incorrecto implementado o nombre de host incorrecto utilizado |
  • | Cadena | salida de -showcerts | Hoja más intermedios, terminando en una raíz conocida | Intermedio faltante o raíz no confiable |
  • | Almacén de confianza | certifi.where() en Python | La ruta existe y el archivo es reciente | Paquete de CA desactualizado o faltante |

Solucionar problemas del paquete de CA del lado del cliente

Si el error es unable to get local issuer certificate y la cadena del servidor parece completa, el almacén de confianza del cliente es el probable culpable. requests de Python usa certifi por defecto, pero algunos entornos lo anulan con REQUESTS_CA_BUNDLE o SSL_CERT_FILE. Verifique qué paquete se está utilizando realmente antes de reemplazar nada.

En macOS, el instalador de python.org incluye un script Install Certificates.command que llena el paquete predeterminado. En contenedores Linux, el paquete ca-certificates proporciona el almacén del sistema. En ambos casos, actualizar el paquete es más seguro que fijar un solo certificado de servidor.

import certifi
import os

print("certifi bundle:", certifi.where())
print("REQUESTS_CA_BUNDLE:", os.environ.get("REQUESTS_CA_BUNDLE"))
print("SSL_CERT_FILE:", os.environ.get("SSL_CERT_FILE"))

Manejar proxies corporativos y raíces personalizadas

Muchas redes empresariales terminan TLS en un proxy y vuelven a firmar el tráfico con una raíz interna. En ese caso, el certificado del servidor es válido pero el cliente no confía en la raíz del proxy. La solución correcta es agregar la raíz corporativa al almacén de confianza del cliente, no deshabilitar la verificación.

Si debe usar un paquete personalizado para una aplicación, configure REQUESTS_CA_BUNDLE con un archivo combinado que contenga tanto las raíces públicas como la raíz corporativa. Mantenga ese archivo bajo gestión de configuración para que no se desvíe. Para la infraestructura que se comunica con endpoints RPC de blockchain, revise las opciones de nodo dedicado y servicio API para ver si una ruta de red privada evita por completo la interceptación del proxy.

Cuando el servidor es el culpable

Si el certificado está caducado, es autofirmado o le falta un intermedio, la solución corresponde al operador del servidor. Puede confirmar la falta de un intermedio comprobando si openssl s_client muestra solo el certificado hoja. Los navegadores a veces ocultan esto almacenando en caché los intermedios, por lo que un cliente Python puede fallar donde un navegador tiene éxito.

Para los proveedores RPC, los problemas de certificados son una señal operativa. Un endpoint gestionado debe ser monitoreado para detectar caducidad y completitud de la cadena. Si está evaluando proveedores, la guía de endpoints RPC y la página de precios de RPC describen qué esperar de un servicio de nivel de producción.

Por qué deshabilitar la verificación es el último recurso

Establecer verify=False en requests suprime la excepción pero también elimina la autenticación del servidor. Un atacante en la ruta de red puede entonces presentar cualquier certificado y leer o modificar el tráfico. Lo mismo se aplica a ssl._create_unverified_context() y a curl -k.

Si necesita probar un endpoint autofirmado durante el desarrollo, pase el archivo de certificado específico con verify="/path/to/cert.pem" en lugar de deshabilitar la verificación. Eso mantiene la decisión de confianza explícita y limitada a un host.

import requests

# Development only: trust one specific certificate file.
response = requests.get(
    "https://RPC_HOST",
    timeout=10,
    verify="/path/to/server-cert.pem",
)
print(response.status_code)

Verificar la solución y monitorear la recurrencia

Después de cambiar el paquete de CA o el certificado del servidor, vuelva a ejecutar el cliente mínimo y el comando openssl s_client. Una solicitud exitosa devuelve un estado HTTP sin SSLError. Una inspección de cadena exitosa muestra una hoja, los intermedios y un emisor que coincide con una raíz en su almacén de confianza.

La caducidad del certificado es predecible, así que monitórela. Una comprobación simple es analizar la fecha notAfter y alertar cuando esté dentro de los 30 días. Para los equipos que ejecutan muchos endpoints, centralice esta comprobación en lugar de confiar en que los desarrolladores individuales lo noten. El directorio de redes enumera las cadenas que OnFinality admite, lo cual es un punto de partida útil para el inventario.

Próximos pasos para decisiones de endpoints y proveedores

Una vez que la verificación funciona, la pregunta restante es qué endpoint usar. Eso es un problema de selección de proveedor y red, no un problema de TLS. Utilice la biblioteca OnFinality Learn para obtener orientación sobre protocolos e integración, y consulte a RPC Assistant para recomendaciones breves y directas sobre endpoints y redes.

Si está construyendo contra una cadena específica, comience con la guía de la red y luego confirme la cadena de certificados del endpoint con el procedimiento anterior. La verificación debería ser aburrida y automática; si no lo es, solucione la ruta de confianza antes de agregar complejidad a la aplicación.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar