Leer el registro de autenticación SSH: qué significa cada línea de fallo

Dónde se registran los inicios de sesión SSH fallidos en cada distribución, cómo descifrar las variantes de mensajes, y cómo distinguir una contraseña mal escrita de una botnet recorriendo una lista.

8 min de lectura

Dónde está realmente el registro

Esto es lo primero que despista, porque depende de la distribución. Debian y Ubuntu escriben los eventos de autenticación en /var/log/auth.log. RHEL, CentOS, AlmaLinux, Rocky y Fedora usan /var/log/secure. Los sistemas que han pasado por completo a journald pueden no tener ninguno de los dos archivos, y todo vive en el journal.

La respuesta portable es journalctl, que funciona en todas partes donde haya systemd:

bash
# Portable: leer el journal del propio sshd, en directo
journalctl -u ssh -f          # nombre de unidad en Debian/Ubuntu
journalctl -u sshd -f         # nombre de unidad en RHEL/Fedora

# Solo fallos, últimas 24 horas
journalctl -u ssh --since -24h | grep -E 'Failed|Invalid user'

# En distribuciones que aún escriben el archivo:
grep -E 'Failed|Invalid user' /var/log/auth.log     # Debian/Ubuntu
grep -E 'Failed|Invalid user' /var/log/secure       # familia RHEL

Las variantes de mensajes, descifradas

sshd emite un conjunto pequeño de mensajes de fallo, y cada uno significa algo concreto. Estos cinco cubren casi todo lo que verás:

  • Failed password for <user> from <ip> port <n> ssh2 — la cuenta existe, la contraseña era incorrecta. O un usuario real equivocándose, o un bot que adivinó un usuario válido.
  • Failed password for invalid user <user> from <ip> — la cuenta no existe. Casi siempre un ataque: tus usuarios conocen sus nombres de usuario. Suele venir acompañado de una línea «Invalid user» aparte.
  • Connection closed by authenticating user <user> <ip> port <n> [preauth] — el cliente abandonó a mitad de la autenticación. Típico de escáneres que solo querían el banner, y de servidores solo-claves rechazando intentos con contraseña.
  • Disconnected from authenticating user root <ip> port <n> [preauth] — un intento como root en un servidor donde root está prohibido. Un volumen alto aquí es la firma más común en un host expuesto.
  • Maximum authentication attempts exceeded for <user> from <ip> — el cliente agotó MaxAuthTries en una conexión. A menudo es un agente ofreciendo muchas claves, pero desde una dirección desconocida es un bot recorriendo credenciales.

Distinguir un ataque de una errata

Tres señales los separan, y conviene tener las tres antes de actuar automáticamente.

Ritmo y persistencia. Una persona hace dos o tres intentos en un minuto y luego o entra o te llama. Un bot mantiene un ritmo constante durante horas, toda la noche, sin pausa.

Diversidad de cuentas. Una persona prueba una cuenta: la suya. Un bot recorre una lista, y la mayoría de esas cuentas no existen — precisamente la firma «invalid user» de arriba.

Origen. Tu gente se conecta desde un puñado de direcciones conocidas. Los ataques llegan de rangos de hosting, desde una dirección distinta cada pocos cientos de intentos, a menudo desde varios países en la misma hora.

Esto agrupa los fallos del último día por dirección de origen y muestra qué usuarios probó cada una, de modo que las tres señales se ven a la vez:

bash
journalctl -u ssh --since -24h --no-pager |
  grep -oE 'Failed password for (invalid user )?[^ ]+ from [0-9.]+' |
  awk '{ ip = $NF; user = $(NF-2); count[ip]++; users[ip] = users[ip] " " user }
       END { for (i in count) printf "%6d  %-16s %s\n", count[i], i, users[i] }' |
  sort -rn | head -15

La línea sobre la que sí hay que alertar

Los inicios de sesión fallidos son ruido. Hay un mensaje que no lo es, y merece una alerta en vez de un panel:

Accepted password for <user> from <ip> — un inicio de sesión correcto con contraseña. Si tu servidor debería ser solo-claves, esta línea significa que no lo es y tienes un problema de configuración. Si las contraseñas están permitidas, esta línea desde una dirección que no reconoces justo después de una tanda de fallos del mismo rango es la secuencia que nunca quieres ver.

Junto a ella conviene vigilar: Accepted publickey con una huella de clave que no reconoces, y cualquier sesión sudo abierta por un usuario que no debería tenerla. Ambas son baratas de alertar y ambas importan mucho más que el volumen de rechazos.

bash
# Todos los inicios de sesión correctos de la última semana, con método y origen
journalctl -u ssh --since -7d --no-pager |
  grep -E 'Accepted (password|publickey|keyboard-interactive)'

De leer a bloquear

Leer el registro a mano es un diagnóstico, no una defensa — cuando lances la consulta, el ataque lleva ya una semana. Lo que cambia algo es hacerlo de forma continua y convertir un umbral en una regla de firewall.

La versión ingenua sigue el journal, cuenta fallos por origen y llama a nft para añadir la dirección a un conjunto bloqueado. Funciona, y luego se encuentra con los problemas de todo script así: el conjunto crece sin límite, el registro rota bajo carga y se pierden eventos, la unidad muere en silencio tras una actualización, y una coincidencia errónea deja al administrador fuera del único acceso.

SSH Protector ejecuta ese bucle como servicio, con un conjunto nftables consolidado, una lista blanca que siempre gana a un bloqueo, baneos restaurados al arrancar, y la decisión tomada localmente — así que aguanta cuando la red no aguanta. Lee el mismo flujo mostrado arriba; no se te oculta nada.

FAQ

¿Dónde se registran los inicios de sesión SSH fallidos en Linux?
En Debian y Ubuntu, /var/log/auth.log. En RHEL, CentOS, AlmaLinux, Rocky y Fedora, /var/log/secure. En sistemas que dependen por completo de journald no existe ninguno de los dos archivos y se lee el journal: journalctl -u ssh (o -u sshd, según el nombre de unidad de la distribución), que funciona en todas partes.
¿Qué significa «Failed password for invalid user»?
Que alguien intentó autenticarse con una cuenta que no existe en la máquina. Tus usuarios conocen sus nombres de usuario, así que esta línea es casi siempre un ataque — un bot recorriendo una lista de nombres comunes como root, admin, ubuntu, test, git u oracle. El volumen por sí solo no es alarmante: es el nivel de fondo en cualquier host expuesto.
¿Por qué veo miles de intentos de inicio de sesión como root?
Porque root es el primer nombre de toda lista de ataque, y los bots no tienen forma de saber que está prohibido en tu servidor. Con PermitRootLogin en no o prohibit-password no pueden tener éxito, pero tampoco dejan de intentarlo, ya que un intento no les cuesta nada. Contra el volumen actúa bloquear los orígenes, no la política de inicio de sesión.
¿Cómo veo los inicios de sesión SSH correctos?
Busca «Accepted» en el mismo registro — Accepted publickey, Accepted password o Accepted keyboard-interactive, seguidos del usuario, la dirección de origen y el puerto. Esta es la línea que merece alerta: un inicio de sesión correcto con contraseña en un servidor que debería ser solo-claves es una mala configuración, y uno desde una dirección desconocida tras una tanda de fallos es un incidente.

Deja de leer el registro a mano

El agente vigila exactamente este flujo y lo convierte en reglas de nftables, de forma continua. Un servidor gratis para siempre, sin tarjeta.