Está parchando servidores, la canalización está verde y entonces—de la nada—cert verify failed aparece como una auditoría sorpresa.
apt no puede descargar paquetes, curl se niega a comunicarse, las descargas de Docker mueren y los registros de la aplicación parecen una maldición medieval:
“unknown authority”, “unable to get local issuer certificate”, “self-signed certificate in certificate chain”.
Ubuntu 24.04 no es especialmente frágil aquí. Es honesto. Verifica TLS correctamente y no fingirá que su cadena de certificados está bien cuando no lo está.
La solución raramente es “desactivar la verificación.” La solución es: reparar los almacenes de confianza y servir las cadenas intermedias correctas. Hágalo una vez, hágalo bien y siga adelante.
Guía rápida de diagnóstico
Cuando falla la verificación TLS, la gente tiende a agitarse: reinstalar paquetes al azar, cambiar variables de entorno, culpar a Ubuntu, culpar a “la red”.
No lo haga. Está depurando un problema de cadena de confianza. Trátelo como un incidente de producción: aislar, reproducir y determinar qué almacén de confianza se está usando.
Primero: reproducir con una herramienta conocida
- Si la falla está en una aplicación, reproduzca con
openssl s_client(verdad fundamental) ycurl -v(comportamiento del cliente). - Capture: nombre de host, puerto, SNI, proxy/no-proxy, y si el host con fallo está en un contenedor/VM.
Segundo: decida si es “cadena del servidor” o “almacén de confianza del cliente”
- Si
openssl s_clientmuestra intermediarios faltantes, arregle primero el servidor. Esa es la reparación limpia. - Si la cadena del servidor está bien pero los clientes aún fallan, su almacén de confianza del cliente está obsoleto o se está pasando por alto (bundle CA personalizado, enlace simbólico roto, imagen antigua, almacén Java raro).
Tercero: verifique si hay interceptación
- Si el emisor del certificado es su empresa, un proxy está terminando TLS. Añada la CA raíz corporativa al almacén de confianza del SO (y posiblemente a los almacenes específicos de aplicaciones).
- Si el sujeto del certificado no coincide con el nombre de host, no está alcanzando el servidor que cree que alcanza (proxy, portal cautivo, secuestro DNS, VIP equivocado).
Cuarto: delimite el alcance del fallo
- ¿Falla solo en un host? Eso es almacén de confianza local, reloj o configuración de proxy.
- ¿Falla en toda la flota? Eso es una rotación de CA, un cambio de política de proxy o una cadena de servidor rota desplegada ampliamente.
- ¿Falla solo en contenedores? Eso es deriva del bundle CA en la imagen (o diferencias Alpine vs Debian en confianza).
Una idea parafraseada de W. Edwards Deming que la gente de operaciones vuelve a aprender de la forma difícil: Sin datos, solo eres otra persona con una opinión
(idea parafraseada).
Recoja la evidencia del apretón de manos antes de “arreglar” nada.
Qué significa realmente “cert verify failed” en Ubuntu 24.04
“Cert verify failed” no es un solo error. Es una familia de fallos que todos terminan en el mismo límite: el cliente no pudo construir una ruta de confianza desde el certificado presentado por el servidor hasta una CA raíz de confianza.
Eso puede ocurrir por unas cuantas razones concretas:
- Faltan certificados intermedios en el servidor (lo más común en producción).
- El almacén de confianza del cliente no incluye la CA raíz (común con PKI privadas o inspección TLS corporativa).
- Hora del sistema incorrecta (certificado aún no válido / expirado).
- Desajuste de nombre de host (conectando al servicio equivocado, SNI incorrecto o problemas de DNS/Proxy).
- La aplicación usa su propio bundle CA e ignora el almacén del SO (hola Java; también algunos entornos Python, Node y aplicaciones en contenedores).
- Empaquetado del bundle CA roto (raro, pero ocurre tras actualizaciones parciales, ediciones manuales o accidentes con capas de imagen).
- Política de revocación/CRL/OCSP en clientes estrictos (menos común en las configuraciones por defecto de Ubuntu, pero frecuente en herramientas empresariales).
Ubuntu 24.04 usa OpenSSL 3 en el sistema base y provee ca-certificates que contiene el conjunto de CA de Mozilla como un bundle.
La mayoría de las herramientas de línea de comandos consultan eso, a menos que estén vinculadas a otra cosa.
El objetivo no es “hacer que el error desaparezca.” El objetivo es que la cadena de certificados sea correcta y que el ancla de confianza sea explícita.
Si hace eso, el error desaparece como efecto secundario. Esa es la dirección causal correcta.
Chiste #1: Desactivar la verificación TLS en producción es como quitar el detector de humo porque no deja de pitar. El pitido estaba cumpliendo su función.
Hechos e historia que explican el desorden actual
Un poco de contexto hace que las fallas de hoy parezcan menos aleatorias. Aquí hay algunos hechos concretos y realmente útiles:
- Los bundles de CA en Linux siguen en gran parte el programa raíz de Mozilla. El paquete
ca-certificateses esencialmente un envoltorio amigable para distribuciones alrededor de esa lista de confianza. - Los certificados intermedios no se almacenan en caché de forma universal. Algunos clientes almacenan en caché intermediarios, otros no, y las cachés expiran. Un servidor que “funciona en mi portátil” aún puede estar roto.
- Los cambios tempranos de cadena de Let’s Encrypt quemaron a mucha gente. Las refirmas cruzadas y problemas de selección de cadena causaron fallos intermitentes en clientes antiguos y servidores mal configurados.
- SNI (Server Name Indication) se volvió obligatorio en la práctica. Sin SNI, puede obtener el certificado equivocado de un endpoint multiinquilino y fallar la verificación de nombre de host.
- OpenSSL 3 endureció el ecosistema. No “rompió TLS”; hizo que comportamientos débiles, ambiguos o mal configurados fueran más visibles y menos tolerados.
- La interceptación TLS corporativa es más antigua que la mayoría de las plataformas de contenedores. Es anterior a Kubernetes, Docker e incluso a algunos proveedores cloud; simplemente se volvió más dolorosa cuando todo pasó a HTTPS.
- Java históricamente llevaba su propio almacén de confianza. Muchas aplicaciones empresariales aún lo hacen, por eso sigue ocurriendo “funciona con curl, falla en la app”.
- La construcción de rutas puede diferir por biblioteca. GnuTLS vs OpenSSL vs NSS pueden tener éxito o fallar de manera distinta sobre la misma cadena, según cómo gestionen los intermediarios.
- No existe una “ubicación estándar” que todos los programas respeten. Linux tiene convenciones, pero cada pila puede anularlas, y muchas lo hacen.
Almacenes de confianza en Ubuntu 24.04: quién usa qué
Antes de ejecutar comandos, tenga claro un modelo mental: “el almacén CA del SO” no es un único archivo. Es un conjunto de fuentes compiladas en archivos bundle,
y diferentes herramientas eligen distintos puntos de entrada.
Archivos y directorios clave
/etc/ssl/certs/ca-certificates.crt— el bundle PEM principal (predeterminado común para herramientas basadas en OpenSSL)./etc/ssl/certs/— enlaces simbólicos hasheados y certificados individuales usados por búsquedas de OpenSSL./usr/local/share/ca-certificates/— donde colocar CAs locales (.crt) para añadirlas al almacén del sistema./etc/ca-certificates.conf— qué CAs están habilitadas/deshabilitadas al generar bundles./var/lib/ca-certificates/— contenido generado/gestionado (no editar a mano).
Quién usa qué (típico)
- curl: usualmente usa la ruta/bundle de OpenSSL; respeta
SSL_CERT_FILE/SSL_CERT_DIR. - apt: usa la pila OpenSSL/gnutls del sistema según cómo esté compilado; en Ubuntu normalmente confía en el sistema vía
ca-certificates. - Python requests: usa
certifipor defecto en muchos virtualenvs a menos que se configure para usar el almacén del sistema. - Java: usa
cacertsen el JRE a menos que se configure explícitamente de otra manera. - Docker: usa la confianza del SO para llamadas a registros, pero también tiene directorios de certificados por registro.
Traducción a lenguaje operador: si solo una aplicación falla, no siga reinstalando ca-certificates. Probablemente está parcheando el almacén de confianza equivocado.
Tareas prácticas (comandos, salidas, decisiones)
A continuación hay tareas prácticas que puede ejecutar en Ubuntu 24.04. Cada una incluye: un comando, qué significa la salida típica y la decisión que debe tomar a continuación.
Están escritas para incidentes reales: servidores, runners de CI, contenedores y redes corporativas.
Tarea 1: Confirmar la hora del sistema (aburrido, pero primero)
cr0x@server:~$ timedatectl
Local time: Mon 2025-12-30 11:22:43 UTC
Universal time: Mon 2025-12-30 11:22:43 UTC
RTC time: Mon 2025-12-30 11:22:43
Time zone: Etc/UTC (UTC, +0000)
System clock synchronized: yes
NTP service: active
RTC in local TZ: no
Significado: Si el reloj no está sincronizado, puede obtener errores “certificate not yet valid” o “expired” incluso con cadenas perfectas.
Decisión: Si System clock synchronized es no, arregle NTP primero. No toque certificados hasta que la hora sea correcta.
Tarea 2: Reproducir con curl y capturar el fallo exacto de verificación
cr0x@server:~$ curl -Iv https://repo.example.internal/
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
curl: (60) SSL certificate problem: unable to get local issuer certificate
Significado: El cliente no pudo construir una cadena hasta una raíz de confianza. Esto a menudo significa intermediarios faltantes (lado servidor) o raíz faltante (lado cliente).
Decisión: Pase a openssl s_client para ver qué presentó realmente el servidor.
Tarea 3: Inspeccionar la cadena del servidor con OpenSSL (verdad fundamental)
cr0x@server:~$ openssl s_client -connect repo.example.internal:443 -servername repo.example.internal -showcerts -verify_return_error </dev/null
depth=0 CN = repo.example.internal
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = repo.example.internal
verify error:num=21:unable to verify the first certificate
verify return:1
Verification error: unable to verify the first certificate
---
Certificate chain
0 s:CN = repo.example.internal
i:CN = Example Issuing CA 01
-----BEGIN CERTIFICATE-----
...leaf...
-----END CERTIFICATE-----
---
Significado: El servidor presentó solo el certificado leaf. No se envió intermediario. Los clientes que no tengan el intermediario en caché fallarán.
Decisión: Arregle el servidor para presentar la cadena completa (leaf + intermediario(s)). Esta es la solución preferida.
Tarea 4: Comprobar qué bundle CA está usando curl
cr0x@server:~$ curl -v https://example.com/ 2>&1 | grep -E "CAfile|CApath"
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
Significado: curl está usando el bundle del sistema y el directorio hasheado.
Decisión: Si su CA corporativa no es confiable, necesita añadirla vía /usr/local/share/ca-certificates y ejecutar update-ca-certificates.
Tarea 5: Verificar que el bundle CA del SO existe y no está obviamente roto
cr0x@server:~$ ls -l /etc/ssl/certs/ca-certificates.crt
-rw-r--r-- 1 root root 223541 Dec 30 10:58 /etc/ssl/certs/ca-certificates.crt
Significado: El bundle existe y tiene un tamaño no trivial.
Decisión: Si falta o es diminuto (unos pocos bytes), sospeche un estado de paquete roto o una ejecución de gestión de configuración defectuosa. Reinstale ca-certificates.
Tarea 6: Reinstalar y regenerar certificados CA limpiamente
cr0x@server:~$ sudo apt-get update
Hit:1 http://archive.ubuntu.com/ubuntu noble InRelease
Reading package lists... Done
cr0x@server:~$ sudo apt-get install --reinstall -y ca-certificates
Reading package lists... Done
Building dependency tree... Done
0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 0 not upgraded.
Setting up ca-certificates (20240203) ...
Updating certificates in /etc/ssl/certs...
0 added, 0 removed; done.
Significado: El paquete está presente; se ejecutó la regeneración del bundle.
Decisión: Si aparecen errores durante “Updating certificates”, deténgase y léalos. Permisos, disco lleno o archivos rotos en el directorio de CAs locales pueden bloquear la actualización.
Tarea 7: Verificar CAs locales y si fueron importadas
cr0x@server:~$ ls -l /usr/local/share/ca-certificates
total 8
-rw-r--r-- 1 root root 2048 Dec 30 10:57 corp-proxy-root-ca.crt
-rw-r--r-- 1 root root 1876 Dec 30 10:57 corp-issuing-ca.crt
Significado: Archivos CA locales existen en el directorio correcto y son .crt.
Decisión: Si sus archivos CA son .pem o tienen extensiones raras, renómbrelos a .crt y ejecute update-ca-certificates.
Tarea 8: Importar CAs locales al almacén de confianza de Ubuntu
cr0x@server:~$ sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
2 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
Significado: Sus dos CAs locales fueron añadidas y hasheadas en /etc/ssl/certs.
Decisión: Vuelva a probar la herramienta que fallaba. Si aún falla, probablemente esté tratando con un problema de cadena intermedia en el servidor o una app que usa otro almacén de confianza.
Tarea 9: Verificar una cadena contra el bundle del sistema explícitamente
cr0x@server:~$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /tmp/server-leaf.pem
CN = repo.example.internal
error 20 at 0 depth lookup: unable to get local issuer certificate
error /tmp/server-leaf.pem: verification failed
Significado: El leaf por sí solo no puede verificarse porque OpenSSL no encuentra su certificado emisor (intermedio) en el almacén de confianza.
Decisión: Si el intermedio no debe ser un ancla de confianza, no lo añada al almacén solo para “hacer que funcione”. Arregle la cadena del servidor en su lugar.
Tarea 10: Obtener y verificar la cadena completa desde el servidor
cr0x@server:~$ openssl s_client -connect repo.example.internal:443 -servername repo.example.internal -showcerts </dev/null | sed -n '/BEGIN CERTIFICATE/,/END CERTIFICATE/p' > /tmp/chain.pem
cr0x@server:~$ openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt -untrusted /tmp/chain.pem /tmp/chain.pem
/tmp/chain.pem: OK
Significado: Una vez disponibles los intermediarios, la verificación tiene éxito.
Decisión: Si openssl verify tiene éxito pero su app falla, es probable que la app use otro bundle CA (certifi de Python, cacerts de Java, bundle embebido).
Tarea 11: Diagnosticar fallos HTTPS de apt con salida dirigida
cr0x@server:~$ sudo apt-get update -o Debug::Acquire::https=true
Ign:1 https://repo.example.internal noble InRelease
Err:1 https://repo.example.internal noble InRelease
Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown.
Reading package lists... Done
W: Failed to fetch https://repo.example.internal/dists/noble/InRelease Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown.
Significado: apt no puede validar la cadena del repositorio.
Decisión: O el servidor del repositorio no envía intermediarios o su almacén del sistema no incluye la raíz corporativa. No use [trusted=yes] como parche salvo en emergencias temporales.
Tarea 12: Comprobar si un proxy está en juego para apt y curl
cr0x@server:~$ env | grep -iE 'http_proxy|https_proxy|no_proxy'
https_proxy=http://proxy.corp.internal:3128
no_proxy=localhost,127.0.0.1,.corp.internal
Significado: Las peticiones pueden pasar por un proxy, posiblemente haciendo interceptación TLS.
Decisión: Si el proxy intercepta, instale su CA raíz en el almacén de confianza del sistema. Si quería acceso directo, corrija el entorno y la configuración de apt.
Tarea 13: Confirmar que el certificado recibido coincide con el hostname (SNI correcto)
cr0x@server:~$ openssl s_client -connect 10.20.30.40:443 -servername repo.example.internal </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer
subject=CN = repo.example.internal
issuer=CN = Example Issuing CA 01
Significado: Con SNI enviado, obtuvo el certificado esperado.
Decisión: Si el sujeto es incorrecto sin SNI, su cliente/herramienta podría no estar enviando SNI (raro hoy, pero aún posible en pilas embebidas). Use herramientas con SNI o corrija el endpoint.
Tarea 14: Identificar si Python está usando certifi en lugar de las CAs del sistema
cr0x@server:~$ python3 -c "import ssl; print(ssl.get_default_verify_paths())"
DefaultVerifyPaths(cafile='/etc/ssl/certs/ca-certificates.crt', capath='/etc/ssl/certs', openssl_cafile_env='SSL_CERT_FILE', openssl_cafile='/usr/lib/ssl/cert.pem', openssl_capath_env='SSL_CERT_DIR', openssl_capath='/usr/lib/ssl/certs')
cr0x@server:~$ python3 -c "import requests; import certifi; print(certifi.where())"
/usr/lib/python3/dist-packages/certifi/cacert.pem
Significado: El módulo SSL usa por defecto el almacén del SO, pero requests puede preferir el bundle de certifi según el empaquetado y el entorno.
Decisión: Si su CA corporativa solo está en el almacén del SO, configure su app para usarlo (o actualice el bundle certifi en ese entorno, o provea una ruta CA adecuada).
Tarea 15: Comprobar el almacén de confianza Java si solo fallan apps JVM
cr0x@server:~$ sudo keytool -list -keystore /etc/ssl/certs/java/cacerts -storepass changeit | head
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 141 entries
Significado: Java tiene su propio almacén de CA.
Decisión: Si las raíces corporativas no están presentes, impórtelas en cacerts de Java (o apunte la JVM al bundle del SO). Arreglar solo la confianza del SO no lo salvará aquí.
Tarea 16: Ruta de confianza del registro Docker (si fallan pulls de imágenes)
cr0x@server:~$ sudo ls -l /etc/docker/certs.d
total 4
drwxr-xr-x 2 root root 4096 Dec 30 11:01 registry.corp.internal:5000
cr0x@server:~$ sudo ls -l /etc/docker/certs.d/registry.corp.internal:5000
total 4
-rw-r--r-- 1 root root 2048 Dec 30 11:01 ca.crt
Significado: Docker tiene anclas de confianza por registro; puede funcionar aunque la confianza del SO esté incompleta (o viceversa).
Decisión: Elija un modelo. En entornos corporativos, prefiero añadir la raíz corporativa a la confianza del SO y mantener las anulaciones de Docker mínimas y documentadas.
Cadenas intermedias: el asesino silencioso
La mayoría de los incidentes “cert verify failed” que parecen misteriosos son solo intermediarios faltantes. Los servidores deben presentar una cadena
que permita a los clientes enlazar el certificado leaf hasta una raíz de confianza. Normalmente la raíz no se envía; los clientes ya la tienen.
Los intermediarios deben ser enviados por el servidor.
Cómo falla esto en la práctica
Una mala configuración común es instalar solo el certificado leaf en el endpoint TLS. Los navegadores pueden aún tener éxito porque:
(a) almacenaron en caché el intermediario desde otro sitio, (b) lo obtuvieron vía AIA (Authority Information Access), o (c) son más tolerantes.
Mientras tanto, los clientes sin interfaz en producción fallan porque no buscan intermediarios o están bloqueados para búsquedas salientes.
Qué hacer en su lugar
- En el lado del servidor, configure el servicio TLS con el archivo de cadena completa (leaf + intermediario(s), en orden correcto).
- Confirme con
openssl s_client -showcertsque el intermediario realmente se está sirviendo. - Prefiera arreglar el servidor. Añadir intermediarios como anclas de confianza en clientes es deuda operativa disfrazada de “arreglo rápido”.
Chiste #2: Las cadenas de certificados son como organigramas—si omites a los mandos medios, nada se aprueba y todos culpan al becario.
Proxies corporativos e interceptación TLS
En muchas empresas, el HTTPS saliente se intercepta: el proxy termina TLS, inspecciona el tráfico y luego lo vuelve a cifrar hacia el destino.
El emisor del certificado del servidor se convierte en “Corporate Proxy Root CA” (o similar), y los clientes fallarán a menos que esa raíz sea confiable.
Cómo confirmar la interceptación
Ejecute openssl s_client a un sitio público desde el host afectado e inspeccione el emisor. Si no es una CA pública esperada,
no está hablando directamente con Internet. Está hablando con su empresa.
Cómo arreglarlo correctamente
- Consiga la CA raíz corporativa (y cualquier intermediario emisor usado por el proxy) en formato PEM.
- Instálela en
/usr/local/share/ca-certificatesy ejecuteupdate-ca-certificates. - Después, audite los almacenes de confianza específicos de aplicaciones (Java, certifi de Python, embebidos). Decida si estandarizar en la confianza del SO o mantener almacenes por app.
Qué no hacer
- No desactive la verificación en apt/curl globalmente.
- No esparza flags “insecure” por scripts de CI y lo dé por resuelto.
- No importe certificados leaf como raíces confiables. Eso no es confianza; es rendición.
Tres microhistorias corporativas desde las trincheras
1) El incidente causado por una suposición equivocada: “El balanceador se encarga de la cadena”
Una empresa mediana ejecutaba repositorios internos detrás de un load balancer gestionado. Un equipo renovó el certificado leaf,
lo subió, vio que los navegadores funcionaban y siguió adelante. A la mañana siguiente, las ventanas de parcheo empezaron a fallar en varios hosts Ubuntu:
apt no podía obtener actualizaciones. “Cert verify failed” en todas partes.
La suposición era simple y errónea: creían que el balanceador servía automáticamente la cadena intermedia correcta.
No lo hacía. Solo servía el leaf. La razón por la que “funcionaba en navegadores” fue intermediarios en caché y, en algunas redes,
obtención AIA oportunista. Los clientes sin interfaz en producción no buscaban intermediarios. Los runners de CI en redes restringidas tampoco.
La depuración tomó más tiempo del necesario porque todos empezaron reinstalando ca-certificates en los clientes.
Eso no cambió nada. La falla estaba en el servidor. Una vez que alguien ejecutó openssl s_client -showcerts y vio una cadena de longitud uno,
la solución quedó clara: configurar el load balancer con un fullchain adecuado.
La lección duradera no fue “usar fullchain” (eso ya lo sabía todo el mundo). Fue: no confíe en nada que no haya verificado desde la perspectiva del cliente que falla.
El mismo endpoint puede verse bien desde un portátil y roto desde un servidor con bloqueo.
2) La optimización que salió mal: “Incrustar bundles CA en el contenedor para velocidad”
Otra organización intentó acelerar builds de contenedores fijando una capa base de imagen que contenía certificados CA y sin tocarla nunca.
La lógica era ordenada: los bundles CA cambian despacio y actualizarlos “desperdicia tiempo de build.” El equipo de plataforma incluso estandarizó una ruta,
y los equipos de aplicaciones debían confiar en ella.
Meses después, una política de proxy corporativo se desplegó. La interceptación HTTPS saliente se volvió obligatoria para ciertas subredes, y el proxy usó una nueva raíz.
Los hosts se actualizaron con la raíz corporativa vía gestión de configuración. Los contenedores no. De repente, los contenedores no pudieron llamar APIs externas,
no pudieron descargar dependencias y algunos ni siquiera pudieron enviar logs.
El patrón del outage fue picante: servicios funcionaban en hosts físicos pero fallaban en Kubernetes. Los desarrolladores culparon a Kubernetes.
Los SRE culparon a “cambios de red”. No era ninguno. Era un bundle CA a nivel de imagen que se había fosilizado.
La resolución fue pragmática: las imágenes base empezaron a reconstruir bundles CA según un calendario, y las imágenes de aplicación dejaron de sobrescribir rutas de confianza.
La “optimización” ahorró segundos por build y costó días en tiempo de incidentes. Un intercambio muy caro.
3) La práctica aburrida pero correcta que salvó el día: “Una canalización de confianza, una fuente de verdad”
Una firma de servicios financieros tenía el enfoque opuesto: aburrimiento implacable. Todas las CAs corporativas vivían en un repositorio versionado,
distribuidas por gestión de configuración e instaladas en los almacenes de confianza del SO con un conjunto pequeño de procedimientos estándar.
También tenían una verificación diaria simple: ejecutar una sonda de verificación TLS desde hosts representativos (incluyendo contenedores) hacia endpoints críticos.
Cuando un CA intermedio rotó en un servicio interno, algunos hosts empezaron a fallar la verificación. La sonda lo captó rápido.
El on-call no necesitó conocimiento tribal. El runbook decía: comprobar longitud de la cadena servida; comparar emisor; confirmar estado del almacén local; arreglar la cadena del servidor.
Eso fue lo que hicieron.
La solución fue del lado del servidor: un archivo fullchain en el servidor faltaba un intermediario tras un cambio en la automatización de renovación de certificados.
Porque tenían una canalización centralizada de confianza, nadie intentó “arreglar clientes” importando intermediarios como raíces.
El radio de impacto se mantuvo pequeño y el incidente fue corto.
No fue glamoroso. Fue correcto. En producción, “aburrido” es un elogio.
Errores comunes: síntoma → causa raíz → solución
1) curl falla, el navegador funciona
Síntoma: curl: (60) unable to get local issuer certificate; los navegadores cargan bien.
Causa raíz: Servidor sin cadena intermedia; el navegador guardó el intermediario en caché o lo obtuvo vía AIA.
Solución: Configure el servidor/load balancer con fullchain (leaf + intermediario(s)). Valide con openssl s_client -showcerts.
2) apt update falla solo en algunos hosts
Síntoma: Errores HTTPS de apt en un subconjunto de la flota; otros bien.
Causa raíz: Deriva: algunos hosts no recibieron actualizaciones de CA, tienen estado ca-certificates roto, o tienen variables de proxy equivocadas.
Solución: Verifique hora, reinstale ca-certificates, ejecute update-ca-certificates y compare variables/config de proxy entre hosts.
3) “certificate signed by unknown authority” solo en contenedores
Síntoma: curl en host funciona; curl en contenedor falla; pulls de Docker fallan en el clúster.
Causa raíz: La imagen del contenedor tiene un bundle CA obsoleto o usa un almacén de confianza distinto al host.
Solución: Asegure que el bundle CA se actualiza dentro de la imagen; evite fijar la capa CA para siempre; instale la raíz corporativa durante el build o monte la confianza del SO según corresponda.
4) App Java falla, curl tiene éxito
Síntoma: Los logs JVM muestran PKIX path building failed; curl al mismo endpoint funciona.
Causa raíz: El almacén de confianza de Java carece de la raíz corporativa o no usa el almacén del SO.
Solución: Importe la CA corporativa en cacerts de Java o configure la JVM para usar el bundle del SO.
5) “self-signed certificate in certificate chain” tras despliegue de proxy
Síntoma: De repente fallos generalizados; el emisor parece una CA corporativa; la cadena incluye “self-signed”.
Causa raíz: Interceptación TLS con una raíz corporativa no confiada en los clientes (o raíz equivocada distribuida).
Solución: Instale la CA raíz corporativa correcta en la confianza del SO (y en los almacenes de apps). Confirme que el emisor coincide con la raíz esperada.
6) La verificación falla después de “limpiar archivos de certificados”
Síntoma: Errores de update-ca-certificates; bundle ausente; herramientas fallan por completo.
Causa raíz: Alguien editó archivos generados en /etc/ssl/certs o borró enlaces hasheados.
Solución: Reinstale ca-certificates, vuelva a ejecutar update-ca-certificates y deje de gestionar rutas generadas con scripts improvisados.
7) Solo un dominio falla, todo lo demás funciona
Síntoma: Un servicio interno da error; otros OK.
Causa raíz: Ese servicio sirve cadena equivocada, certificado equivocado o mapeo SNI incorrecto en el LB.
Solución: Use openssl s_client -servername para confirmar el certificado correcto; arregle la configuración del servidor.
8) Fallos esporádicos que “se curan solos”
Síntoma: Un mismo cliente a veces tiene éxito y a veces falla, sin cambios de configuración.
Causa raíz: Múltiples backends detrás de un VIP; algunos sirven la cadena correcta, otros no. O múltiples proxies con políticas de certificados distintas.
Solución: Alcance cada backend directamente; compare cadenas servidas; estandarice la configuración TLS entre miembros del pool.
Listas de verificación / plan paso a paso
Plan paso a paso para un host Ubuntu 24.04 con fallo
-
Confirmar hora y red básica (
timedatectl, resolución DNS, ruta/vars de proxy). Arregle la hora primero. -
Reproducir con curl usando
-Ivy capture el error exacto. Si es desajuste de hostname, pare y arregle endpoint/SNI. -
Ejecutar inspección de cadena OpenSSL con
-showcerts -verify_return_error -servername. Determine si faltan intermediarios. - Si faltan intermediarios, arregle el servidor/LB para servir fullchain. Reteste desde el mismo host.
-
Si el emisor es corporativo/proxy, instale la raíz corporativa en
/usr/local/share/ca-certificatesy ejecuteupdate-ca-certificates. - Si solo una app falla, identifique su almacén de confianza (certifi Python, cacerts Java, bundle en contenedor, ruta CA embebida).
- Endurezca: elimine flags temporales inseguros, documente el método de distribución de CAs y añada una sonda básica para detectar futuras rotaciones.
Lista de verificación para arreglar la cadena en el servidor (cómo es “correcto”)
- El certificado leaf coincide con el hostname (SAN incluye el nombre DNS).
- El leaf está firmado por una CA intermedia (no auto-firmado, salvo que se use una raíz privada intencionalmente).
- El servidor presenta leaf + intermediario(s) en el orden correcto.
- La CA raíz no se sirve (usualmente innecesario y a veces desaconsejado).
- La verificación tiene éxito desde un cliente limpio usando el almacén de confianza del SO.
Lista de verificación para higiene de confianza en clientes (cómo evitar reincidencias)
- Las raíces corporativas se distribuyen vía gestión de configuración, no copiadas a mano.
- El almacén del SO se actualiza con
update-ca-certificatestras cambios. - Los contenedores reconstruyen bundles CA según un calendario o durante el build de forma fiable.
- Los equipos de app saben si deben usar la confianza del SO o un almacén específico de la app.
- Las sondas validan endpoints críticos diariamente desde entornos representativos (host + contenedor + runner CI).
Preguntas frecuentes
1) ¿Reinstalar ca-certificates siempre arregla el problema?
No. Arregla la generación de bundles locales rotos y paquetes obsoletos, pero no arreglará un servidor que no envía intermediarios.
Use openssl s_client -showcerts para decidir si el problema es la cadena del servidor o la confianza del cliente.
2) ¿Debo añadir el certificado intermedio al almacén de confianza del cliente?
Usualmente no. Los intermediarios no son anclas de confianza; forman parte de la cadena que el servidor debería enviar.
Añadir intermediarios a los almacenes de confianza “funciona”, pero extiende una mala configuración del servidor a cada cliente y contenedor que posea.
3) ¿Por qué funciona en mi portátil pero falla en los servidores?
Intermediarios en caché, almacenes de confianza distintos, proxies diferentes o comportamiento distinto de DNS/SNI.
Los servidores suelen ser más estrictos y más aislados, y por eso fallan primero.
4) ¿Dónde coloco una CA raíz corporativa en Ubuntu 24.04?
Coloque un certificado codificado en PEM en /usr/local/share/ca-certificates/ con extensión .crt, luego ejecute sudo update-ca-certificates.
Verifique que se incluya comprobando herramientas como curl nuevamente.
5) apt falla con errores de certificado. ¿Puedo usar [trusted=yes] en sources.list?
Eso elude las comprobaciones de firma para ese repositorio, no la verificación TLS de forma robusta, y es una degradación de seguridad en cualquier caso.
Arregle la confianza CA o la cadena del servidor. Considere atajos inseguros solo para escenarios de rotura temporal de emergencia y elimínelos rápido.
6) Mi app Python falla pero curl del sistema funciona. ¿Por qué?
Muchos entornos Python usan el bundle certifi en lugar del almacén de confianza del SO.
Confirme con python3 -c "import certifi; print(certifi.where())" y decida si apuntar requests a las CAs del sistema o actualizar el bundle.
7) ¿Cómo detecto si un proxy está interceptando TLS?
Inspeccione el emisor de un certificado al conectar a un sitio público conocido.
Si el emisor es una CA interna corporativa, está siendo interceptado. Eso no es automáticamente malo; solo implica un requisito de distribución de confianza.
8) ¿Necesito reiniciar servicios tras actualizar CAs?
A menudo sí para procesos de larga ejecución. Muchos programas leen bundles CA al arrancar y los mantienen en memoria.
Para demonios del sistema y servidores de aplicaciones, planifique un reinicio o un despliegue rolling tras actualizaciones de CA.
9) ¿Cuál es la diferencia entre “unable to get local issuer certificate” y “self-signed certificate”?
“Unable to get local issuer” suele significar intermediario faltante o raíz confiable ausente.
“Self-signed” a menudo indica que la cadena incluye un certificado que no es confiable como raíz, o que está golpeando un certificado de proxy/mitm sin confiar su raíz.
10) ¿Cómo prevengo este tipo de outage?
Arregle cadenas de servidor correctamente, centralice la distribución de CAs, evite bundles CA congelados en imágenes y añada una sonda TLS diaria a endpoints críticos.
El secreto es coherencia, no heroísmo.
Conclusión: siguientes pasos que realmente funcionan
Ubuntu 24.04 no está siendo difícil cuando muestra “cert verify failed.” Está siendo preciso.
La solución duradera más rápida casi siempre es una de dos cosas: servir la cadena intermedia correcta en el servidor, o instalar la CA raíz correcta en el cliente.
Cualquier otra cosa es un desvío que se convierte en política, y la política se convierte en dolor.
Pasos siguientes que rinden:
- Ejecute la guía rápida de diagnóstico en un host que falle y capture la salida de la cadena OpenSSL.
- Arregle fullchain en el servidor siempre que controle el endpoint; trátelo como la remediación primaria.
- Estandarice la instalación de CAs corporativas vía
/usr/local/share/ca-certificates+update-ca-certificates. - Audite almacenes de confianza específicos de apps (Java, certifi Python, contenedores) y elija un enfoque estándar.
- Añada una sonda simple que verifique TLS desde entornos representativos para detectar la próxima rotura antes que los usuarios.
Haga la cadena correcta una vez. El usted del futuro estará un poco menos cansado, que es lo más parecido a un desfile de victoria que tiene operaciones.