Un servidor se configura una vez y después vive por su cuenta. Un mes más tarde hay paquetes esperando actualización, el certificado se ha acercado a tres semanas de su caducidad, tras instalar algo ajeno apareció una línea de más en la configuración de SSH, y la cárcel que debía vigilar los accesos se detuvo sin que nadie se enterara. Nada de eso grita. Todo, simplemente, deja de ser cierto en silencio.

A continuación, doce cosas que conviene comprobar con regularidad, con los comandos. La ronda lleva unos quince minutos. El orden va de aquello por donde se entra a aquello que se rompe solo.

SSH: cinco líneas

Lo que hay que mirar no es el archivo, sino la configuración efectiva: se compone de /etc/ssh/sshd_config, de todo el directorio sshd_config.d y de los valores por defecto de la compilación.

sudo sshd -T | grep -iE 'permitrootlogin|passwordauthentication|permitemptypasswords|maxauthtries|x11forwarding'

Lo que queremos ver: permitrootlogin no, passwordauthentication no, permitemptypasswords no, maxauthtries en 3–4 y x11forwarding no. Las tres primeras son la puerta; las dos últimas, sus bisagras: un tope de intentos por conexión y un reenvío gráfico que a un servidor no le sirve de nada.

Dos advertencias, dos maneras fáciles de dejarse fuera. La primera: no desactive el acceso por contraseña ni el acceso de root antes de comprobar que su clave funciona, en una sesión aparte y sin cerrar la actual. Si está leyendo esto conectado como root con contraseña, esas dos líneas le dejarán fuera precisamente a usted.

La segunda: el orden de los archivos. OpenSSH se queda con el primer valor que encuentra para un parámetro, y los archivos de sshd_config.d se leen por orden alfabético. Las imágenes de nube suelen dejar ahí un 50-cloud-init.conf, que se impondrá a su propio archivo si lo llamó algo así como 90-hardening.conf. Los ajustes propios van con un número menor: 00- o 10-. Y el resultado se comprueba con sshd -T, no leyendo el archivo.

Cortafuegos: una comprobación

sudo ufw status verbose

Conviene recordar que esa salida muestra intenciones, no resultados. Una regla puede figurar en la lista y no cerrar nada: el propio UFW está desactivado, el puerto lo atiende algo publicado por Docker (que escribe sus reglas en iptables por debajo de UFW), o el tráfico llega al servidor por otro camino. Por eso vale la pena contrastar la lista de reglas con lo que realmente escucha hacia fuera:

sudo ss -tulpn | grep -v '127.0.0.1\|::1'

fail2ban: dos comprobaciones

No basta con que el servicio esté en marcha: hace falta además una cárcel que funcione para SSH.

sudo fail2ban-client status
sudo fail2ban-client status sshd

El contratiempo más habitual aquí es una cárcel muda. En Debian 12 y en las Ubuntu recientes puede no existir /var/log/auth.log en absoluto: rsyslog no está instalado y los registros viven solo en journald. Una cárcel con el logpath de fábrica arranca entonces, se declara activa y no bloquea a nadie jamás. Se cura apuntándola al diario de systemd:

printf '[sshd]\nenabled = true\nbackend = systemd\n' | sudo tee /etc/fail2ban/jail.d/sshd-systemd.local
sudo systemctl restart fail2ban

La señal que permite detectarlo sin hurgar en configuraciones: en fail2ban-client status sshd, «Currently failed» y «Total failed» siguen en cero mientras el diario contiene con claridad accesos fallidos.

Actualizaciones: tres comprobaciones

Por separado: cuántos paquetes esperan en total, cuántos de ellos son de seguridad y si el sistema pide reinicio tras una actualización del núcleo.

sudo apt update
apt list --upgradable 2>/dev/null | grep -c -- '-security'
ls /var/run/reboot-required 2>/dev/null && echo 'hace falta reiniciar'

La tercera comprobación es si están activadas las actualizaciones de seguridad automáticas, para que las dos primeras no se conviertan en un ritual mensual:

systemctl status unattended-upgrades --no-pager
cat /etc/apt/apt.conf.d/20auto-upgrades

Ese archivo debe llevar un 1 en ambas líneas. Si falta el paquete: sudo apt install unattended-upgrades && sudo dpkg-reconfigure -plow unattended-upgrades.

Certificados: una comprobación

Un certificado de Let's Encrypt vive noventa días, y la renovación funciona sola justo hasta el día en que deja de hacerlo. Lo que hay que mirar no es el panel del registrador, sino lo que el servidor sirve de verdad:

echo | openssl s_client -connect localhost:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
sudo certbot renew --dry-run

El primer comando da la fecha de caducidad del certificado que se sirve para ese nombre; el segundo comprueba que la renovación saldrá bien sin esperar al plazo real. Vale la pena recorrer todos los nombres que atiende el servidor, no solo el dominio principal: el que se olvida siempre es el subdominio añadido después.

Disco: una comprobación

df -h
df -i

Dos comandos, porque el espacio y los registros de archivos se agotan de forma independiente. En la mayoría de los servidores el segundo llega antes al techo: millones de archivos pequeños en las sesiones de PHP o en la caché de la aplicación dan un IUse% de 100 con gigabytes todavía libres. Tenemos un artículo aparte que detalla ambos casos.

Qué falla en esta lista

La lista es correcta, pero tiene una propiedad: exige que alguien se acuerde de ella. Quince minutos a la semana es poco, mientras haya un solo servidor y mientras haya un motivo. Tras dos meses tranquilos la ronda se salta, y de que la cárcel se detuvo uno se entera por los registros de otra persona.

Por eso hemos reunido exactamente estas doce comprobaciones en un panel gratuito aparte: Arcivéo FREE. Se instala con un solo comando, funciona en su propio servidor, no nos envía nada y no requiere registro. Un recolector se ejecuta por cron cada cinco minutos y escribe lo mismo en una base de datos local: accesos SSH y conexiones rechazadas, estado de UFW y fail2ban, actualizaciones de seguridad pendientes, plazos de los certificados, espacio en disco. El historial es de siete días y la interfaz está en 34 idiomas. El precio es cero, también en un servidor de trabajo: la licencia permite instalar el panel en máquinas propias, incluidas las de la empresa, y no permite revenderlo ni ofrecerlo como servicio para servidores ajenos.

La pila de la edición gratuita es modesta: instala y activa UFW y fail2ban, y a partir de ahí muestra el estado. ModSecurity, Suricata, AIDE y los demás módulos no están ahí, esos pertenecen a la de pago. Pero para dejar de llevar la ronda semanal en la cabeza, basta. Cómo se ven esos mismos datos en el panel completo puede verlo en las páginas de demostración de abajo.