← Volver al blog

El día que un certificado SSL caducado tumbó la web de un cliente sin avisar

Daniel García·

Ilustración del artículo: El día que un certificado SSL caducado tumbó la web de un cliente sin avisar

Un cliente que vende maquinaria agrícola de segunda mano me llamó un martes a las nueve de la mañana. Su web mostraba “La conexión no es privada” en rojo, con el típico aviso de Chrome que asusta a cualquiera que no sepa de esto. Pensó que le habían hackeado. No le habían hackeado nada: el certificado SSL llevaba caducado desde las 03:17 de esa misma madrugada, y nos enteramos por él, no por nuestro propio sistema.

Un certificado SSL caduca cuando el proceso de renovación automática falla en silencio y nadie lo detecta a tiempo: Let’s Encrypt emite certificados válidos solo 90 días, así que si el cron de certbot no se ejecuta bien, el navegador bloquea la web en cuanto expira, sin ningún aviso visible para quien administra el servidor.

En nuestro caso el cron sí se ejecutaba. Ese fue el problema, en realidad, porque nos dio una falsa sensación de tranquilidad durante semanas. Al migrar ese servidor al VPS nuevo en agosto, cambiamos el usuario que corría los servicios de sistema, y certbot se quedó sin permisos para escribir el certificado renovado en la ruta que nginx esperaba. El comando terminaba con código de salida distinto de cero cada noche, dejando el error apuntado en /var/log/letsencrypt/renewal.log, un fichero que, para qué engañarnos, no mira nadie salvo cuando ya ha pasado algo.

Y ahí está la parte que más me molesta de todo esto: llevamos años diciéndole a los clientes que el candado del navegador no es un detalle estético, que Google penaliza en buscadores a las webs sin HTTPS, que un formulario de contacto sin cifrar es una imprudencia. Que se nos caducara justo a nosotros fue más un golpe al orgullo que un problema técnico grave. El arreglo, una vez detectado, tardó quince minutos: corregir permisos, forzar certbot renew --force-renewal, recargar nginx. La vergüenza duró bastante más.

Por qué un cron que “funciona” no basta

El fallo real no fue el permiso mal puesto, eso pasa. El fallo fue no tener ninguna alarma que avisara si la renovación no se completaba con éxito, solo confiar en que el cron corriera y ya está. Un cron que se ejecuta pero falla es indistinguible, desde fuera, de uno que ni siquiera existe, y en los dos casos el resultado es el mismo: te enteras cuando alguien mira la pantalla roja.

Desde entonces cada certificado del servidor manda un ping a un servicio externo de monitorización de heartbeats justo después de renovarse con éxito. Si ese ping no llega en 25 horas (dejamos un margen sobre las 24 del cron diario), salta un aviso a un grupo de Telegram del equipo, no a una bandeja de correo que nadie abre en fin de semana. Cuesta cinco minutos montarlo por dominio y hubiera evitado toda esta historia. En total tenemos ahora mismo catorce dominios de clientes con certificados propios en ese servidor, y revisar uno por uno si el cron seguía vivo, cuando pasó esto, nos llevó una tarde entera que ya no queremos volver a perder.

Lo que todavía no tenemos resuelto

Lo que no hemos resuelto, y lo digo sin vender que ya está todo controlado, es qué pasa el día en que falle el propio servicio de monitorización, no el certificado. Añadir una alarma que avisa cuando algo se rompe soluciona el problema de hoy, pero desplaza el mismo riesgo un nivel más arriba: ahora dependemos de que ese heartbeat funcione, y de que alguien revise de vez en cuando que sigue activo. Después de la auditoría de seguridad que le hicimos a nuestro propio servidor ya sabíamos que confiar ciegamente en que “algo automático” seguirá funcionando para siempre es la forma más barata de llevarse un susto. Este solo fue el último recordatorio.

sslcertificadoshostingseguridad