Leyendo los logs de una auditoría: qué es ruido y qué es real

Ilustración de lupa gigante inspeccionando racks de servidores con componentes flotando al fondo

En el artículo anterior expliqué el script que uso para auditar mis servidores y cómo ejecutarlo. Ahora toca la parte más importante: leer el output sin entrar en pánico ni ignorar lo que de verdad importa.

Porque el output de una auditoría tiene mucho ruido. Cosas que parecen graves y no lo son. Cosas que parecen menores y son urgentes. Y cosas que directamente no aplican a tu caso. Saber distinguirlas es la mitad del trabajo.

Antes de entrar en materia, un contexto personal: no parto de cero en esto de la seguridad en servidores Linux. Hace unos años hice una serie completa sobre hardening en Raspberry Pi — desde actualizar el firmware hasta auditoría con Lynis, pasando por SSH, UFW, rkhunter, fail2ban y copias de seguridad. Sabía lo que tenía que tener. Lo que no esperaba era encontrar que no lo tenía.

Lo primero que miré: usuarios y accesos

Esta sección suele ser la más reveladora. Lo que encontré en el servidor de producción:

▶ Últimos 20 intentos fallidos
root     ssh:notty    Wed Mar 25 08:03   2.57.122.195
root     ssh:notty    Wed Mar 25 08:02   2.57.122.195
root     ssh:notty    Wed Mar 25 08:02   2.57.122.195
...
   9113 Failed password
   3782 Invalid user
   4522 89.185.81.112
   4098 2.57.122.177
   3295 144.217.76.59

Más de 13.000 intentos fallidos de SSH en 25 días. Una sola IP con 4.522 intentos. Y el servidor sin fail2ban. Activo, escuchando, aguantando el chaparrón sin banear a nadie.

Esto no es una alerta menor. Es el problema más urgente del output y lo primero que hay que resolver.

Lo que hay que buscar en esta sección:

  • IPs con muchos intentos: más de 100 intentos desde una misma IP en pocos días es un escaneo activo.
  • Usuarios inusuales: intentos con usuarios como oracle, ubnt, solana o certbot indican diccionarios de credenciales comunes.
  • Logins exitosos desde IPs desconocidas: si ves un Accepted de una IP que no reconoces, para todo lo demás.
  • Solo una clave SSH por usuario: si authorized_keys tiene más claves de las esperadas, investiga.

Puertos abiertos: lo que escucha en 0.0.0.0

El script filtra específicamente los puertos que escuchan en todas las interfaces. Esto es lo que salió:

tcp   LISTEN   0.0.0.0:80      nginx
tcp   LISTEN   0.0.0.0:443     nginx
tcp   LISTEN   0.0.0.0:22      sshd
tcp   LISTEN   *:9080          promtail
tcp   LISTEN   *:46697         promtail

Los tres primeros son esperables. Los dos últimos no. Promtail — el agente que envía logs a Loki — estaba escuchando en todas las interfaces en lugar de solo en localhost. No era accesible desde internet porque UFW lo bloqueaba, pero era una configuración incorrecta que conviene corregir.

La regla general es simple: si un servicio no necesita ser accesible desde fuera, no debería escuchar en 0.0.0.0. Debería hacerlo en 127.0.0.1.

Lo que es normal ver en 0.0.0.0:

  • Puerto 80 y 443 (Nginx, tráfico web)
  • Puerto 22 (SSH)
  • Puerto de WireGuard

Lo que no debería estar ahí:

  • Puertos de monitorización (Prometheus, Loki, Promtail)
  • Paneles de administración
  • Bases de datos (MySQL en 127.0.0.1:3306 es correcto; en 0.0.0.0:3306 sería un problema grave)

Servicios: lo que corre sin que lo sepas

Esta sección tiene mucho ruido. La lista de servicios activos puede ser larga e intimidante. El truco es filtrar por lo que no debería estar ahí.

En mi caso encontré dos cosas relevantes:

PHP 8.3 y PHP 8.4 corriendo a la vez. Los tres sitios del servidor ya usaban 8.4. La 8.3 era un residuo de la migración, consumiendo memoria sin hacer nada.

Snapd habilitado en boot. En un servidor de producción sin ningún snap instalado. Seis servicios de systemd arrancando en cada reboot para gestionar paquetes que no existen.

También encontré multipathd activo — un servicio para gestionar múltiples rutas a discos SAN/iSCSI. En un VPS con un único disco virtual no tiene ningún sentido.

Lo que hay que buscar:

  • Versiones duplicadas de servicios (dos versiones de PHP, dos de Python...)
  • Servicios de gestión de paquetes que no usas (snapd, flatpak)
  • Servicios de hardware que no aplican a un VPS (multipathd, open-iscsi)
  • Servicios cloud que ya no tienen utilidad una vez el servidor está configurado (cloud-init)

Actualizaciones: el reboot pendiente silencioso

▶ Reboot pendiente
/var/run/reboot-required

Este fichero existe cuando hay actualizaciones instaladas que requieren reinicio — normalmente el kernel o glibc. El servidor llevaba días con un kernel nuevo instalado pero sin cargar.

No es urgente como el fail2ban, pero es el tipo de cosa que se acumula. Un servidor que lleva semanas sin reiniciar tras un kernel update de seguridad es un riesgo innecesario.

También hay que revisar los paquetes actualizables. Si aparecen paquetes de seguridad sin instalar y unattended-upgrades está habilitado, algo no está funcionando bien.

Logs: el tamaño importa

1.3G    /var/log/journal
151M    /var/log/btmp
68M     /var/log/btmp.1

El journal ocupando 1.3 GB en un VPS con 38 GB de disco no es un problema crítico, pero es una señal de que nadie ha configurado límites. El fichero btmp — que registra los intentos fallidos de login — llegaba a 151 MB, consecuencia directa de los 13.000 intentos sin fail2ban baneando a nadie.

Lo que parece grave y no lo es

El script también devuelve cosas que a primera vista asustan pero son completamente normales:

World-writable dirs en /var/lib/containerd/: son capas de overlayfs de contenedores Docker. Así funcionan por diseño.

Ficheros SUID en /var/lib/containerd/: binarios del sistema dentro de la imagen del contenedor. No son SUID en el host, solo dentro del sistema de ficheros del contenedor.

Muchos servicios marcados como UNSAFE por systemd-analyze: Lynis también lo reporta. La mayoría son servicios del sistema que no tienen sandboxing de systemd configurado. Es una mejora avanzada que tiene poco impacto real para la mayoría de casos.

Lynis: la puntuación de partida

Con todo esto sobre la mesa, pasé Lynis para tener un número de referencia:

Hardening index : 68
Tests performed : 269
Warnings        : 1
Suggestions     : 46

68 sobre 100. No es un desastre, pero hay margen. El único warning real era la ausencia de repositorio de seguridad en sources.list — un artefacto de usar los repos de PHP de sury.org. Las 46 sugerencias van desde cosas críticas a recomendaciones que no tienen ningún sentido para un VPS.

En el próximo artículo, qué hice con todo esto: qué arreglé, en qué orden, qué decidí ignorar y por qué. Y cómo quedó la puntuación al final.

Jaume Ferré

Jaume Ferré

Tengo un trabajo que no tiene nada que ver con esto. Pero me gusta cacharrear con webs, Linux y el homelab. De vez en cuando alguien me paga por ello, lo cual siempre sorprende. Canon R7 en mano y Arch Linux de fondo.

¿Te ha sido útil?

Ayúdame a mejorar con tu puntuación.

0.0 (0 votos)
Comentarios