SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor

Instalar Fail2ban en Ubuntu 24.04 para bloquear bots SSH

En Ubuntu 24.04, apt install ya bloquea ataques SSH. Comprueba fail2ban-client status sshd y corrige el caso en que Total failed permanece en 0.

Qué hace realmente Fail2ban

Fail2ban es un daemon que lee registros. Supervisa los mensajes de autenticación de SSH y, después de varios fallos desde una dirección en un intervalo breve, ejecuta un comando del firewall que bloquea esa dirección durante un tiempo. Esa es toda la idea. La configuración ocupa unas treinta líneas en un archivo, y en Ubuntu 24.04 la instalación consiste en un único comando apt que deja el sistema protegido antes de modificar nada.

Debe quedar claro qué es y qué no es. Fail2ban no autentica a nadie, no cifra nada y no detiene un único intento de inicio de sesión decidido; solo detiene los intentos repetidos desde el mismo origen. Es un filtro de ruido y un limitador de frecuencia, no una cerradura. Su función es evitar que el escaneo constante en segundo plano del puerto 22 siga consumiendo CPU, ancho de banda y espacio en los registros, y ralentizar a cualquier atacante que tenga que proceder desde una dirección cada vez.

Lo que Fail2ban no sustituye

Fail2ban es la tercera capa, no la primera. Si el servidor todavía acepta contraseñas para SSH, una botnet distribuida entre miles de direcciones puede seguir intentando autenticarse, porque cada dirección permanece por debajo del umbral de bloqueo y nunca lo activa. La defensa real contra esto es la autenticación exclusiva mediante claves, que hace imposible adivinar contraseñas, independientemente del número de intentos. Fail2ban sobre la autenticación exclusiva mediante claves cumple dos funciones útiles: elimina de los registros el ruido de los ataques de fuerza bruta y expulsa pronto a los escáneres para que dejen de saturar el puerto. Considérelo una medida de defensa en profundidad. Se sitúa después de la autenticación mediante claves y del firewall, nunca delante de ellos.

Requisitos previos y la realidad de Ubuntu 24.04

Necesita un VPS con Ubuntu 24.04 con acceso root o sudo, y SSH ya configurado, preferiblemente mediante autenticación por clave. Fail2ban es eficiente: consume unas pocas decenas de megabytes de RAM y no requiere ajustar límites.

Ahora, la parte en la que todas las guías antiguas se equivocan. Durante años, el consejo estándar fue "instale Fail2ban y añada backend = systemd, porque Ubuntu dejó de escribir en /var/log/auth.log". Ese consejo solo es válido en algunas imágenes. Un servidor Ubuntu 24.04 estándar o una imagen en la nube todavía instalan rsyslog, cuyas reglas predeterminadas escriben auth,authpriv.* en /var/log/auth.log, por lo que en la mayoría de los VPS los fallos de SSH terminan en ese archivo además del journal de systemd. Las imágenes mínimas (la imagen en la nube mínima de Ubuntu 24.04 se distribuye sin rsyslog) y la mayoría de los contenedores registran SSH solo en el journal, y ahí el archivo de texto realmente no existe. De cualquier manera, en Ubuntu 24.04 el paquete Fail2ban ya lo tiene en cuenta. El paquete incluye /etc/fail2ban/jail.d/defaults-debian.conf, y ese archivo, no los valores predeterminados originales, es el que su servidor ejecuta realmente:

[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd

[sshd]
enabled = true

Lea esto con atención, porque resuelve dos dudas antes de que toque nada. backend = systemd significa que la jaula de SSH lee el journal, por lo que no importa si su imagen escribe en auth.log o no. banaction = nftables significa que los bloqueos se aplican mediante nftables, que es el firewall que Ubuntu 24.04 utiliza realmente, en lugar del antiguo iptables. Y [sshd] enabled = true significa que la jaula está activa desde el primer arranque. En resumen: un apt install fail2ban estándar en Ubuntu 24.04 bloquea los ataques de fuerza bruta SSH de forma inmediata. La mayor parte de su trabajo consiste en confirmar esto, ajustar la política y asegurarse de no bloquearse a sí mismo.

La vieja trampa de auth.log sigue siendo un problema en tres situaciones, y vale la pena reconocerlas: instaló Fail2ban con pip en lugar de apt, por lo que no existe defaults-debian.conf; está dentro de un contenedor sin privilegios sin un journal de systemd que leer; o siguió un tutorial antiguo y pegó backend = auto en su propio jail.local, sobrescribiendo el valor predeterminado que funciona. La primera y la tercera solo rompen el bloqueo de SSH en una imagen sin rsyslog, como una imagen mínima, porque donde rsyslog se ejecuta, el backend de archivos encuentra /var/log/auth.log y funciona. La sección de modos de fallo muestra exactamente cómo se ve cada uno.

Paso 1: Instalarlo y confirmar que ya está bloqueando

sudo apt update
sudo apt install -y fail2ban

Ubuntu 24.04 incluye Fail2ban 1.0.2, y el paquete incorpora python3-systemd como dependencia obligatoria, por lo que el backend del journal tiene todo lo necesario. El servicio se habilita y se inicia automáticamente:

sudo systemctl status fail2ban

Debe aparecer active (running). Después, compruebe el jail que ya está funcionando:

sudo fail2ban-client status sshd

En un VPS público accesible durante unos minutos, normalmente ya verá fallos contabilizados y direcciones bloqueadas. Internet analiza continuamente el puerto 22. Esto demuestra que la configuración predeterminada funciona. A partir de aquí, debe ajustarla, no crearla desde cero.

Paso 2: Edite jail.local, nunca jail.conf

Fail2ban mantiene sus valores predeterminados en /etc/fail2ban/jail.conf. No edite ese archivo. Una actualización del paquete puede reemplazarlo, tal como advierte la cabecera del propio archivo, y sus ediciones podrían perderse. Fail2ban lee los archivos en un orden fijo: primero jail.conf, luego jail.d/*.conf en orden alfabético, después jail.local y finalmente jail.d/*.local en orden alfabético, donde el último valor prevalece. Por lo tanto, jail.local sobrescribe el defaults-debian.conf del paquete, pero cualquier archivo *.local que usted coloque en jail.d/ se lee después y lo sobrescribe a su vez; mantenga sus sobrescrituras en un solo lugar para saber qué valor está activo. El archivo .local es suyo y las actualizaciones del paquete nunca lo modifican. La misma regla se aplica a los filtros, donde un archivo *.local sobrescribe al filter.d/*.conf suministrado.

Por lo tanto, escriba un pequeño jail.local que sobrescriba solo los pocos ajustes que le interesan y deje tanto jail.conf como el jail.d/defaults-debian.conf del paquete intactos como referencia.

Paso 3: Escribir /etc/fail2ban/jail.local

sudo nano /etc/fail2ban/jail.local

Introduzca este contenido y cambie la dirección de la línea ignoreip por su propia IP pública:

[DEFAULT]
# Ubuntu 24.04 already sets these two in jail.d/defaults-debian.conf.
# Pinning them here documents the dependency and survives if that
# file is ever removed or changed by an upgrade.
backend   = systemd
banaction = nftables

# Ban for one hour ...
bantime  = 1h
# ... if an address fails ...
maxretry = 5
# ... 5 times within 10 minutes.
findtime = 10m

# Never ban these. PUT YOUR OWN IP HERE.
ignoreip = 127.0.0.1/8 ::1 10.0.0.24

# Longer bans for repeat offenders: 1h, 2h, 4h ... up to a week.
bantime.increment = true
bantime.maxtime   = 1w

[sshd]
enabled = true

Cada línea tiene una función:

  • bantime, findtime y maxretry definen la política. El valor predeterminado incluido, bantime, solo dura diez minutos; una hora es un mínimo más razonable. Cinco fallos desde una misma dirección en un periodo de diez minutos activan la prohibición. Las personas reales suelen escribir mal una contraseña una o dos veces; cinco fallos en diez minutos indican un script.
  • ignoreip es su medida de seguridad. Añada aquí la dirección pública desde la que se conecta para que Fail2ban nunca pueda bloquearle el acceso a su propio servidor. Una conexión doméstica con una IP cambiante es un motivo para preferir el enfoque de VPN al final, no para omitir esta línea.
  • bantime.increment = true hace que cada prohibición repetida dure más que la anterior: una hora, después dos y luego cuatro, hasta bantime.maxtime. Las direcciones que siguen regresando quedan bloqueadas progresivamente durante más tiempo.

Obtenga la dirección que debe incluir en la lista de permitidas desde la máquina desde la que se conecta mediante SSH, no desde el servidor:

curl -s ifconfig.me

Aquí puede generar un jail.local adaptado a sus puertos y a su política de prohibiciones, y después pegarlo en el archivo:

ToolFail2ban jail generator

Paso 4: Reiniciar y verificar que lee el journal

sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

El -t ejecuta primero una prueba de configuración, por lo que un error tipográfico en jail.local provoca un fallo evidente en este punto en lugar de dejar el servicio inactivo. Un estado saludable de la jaula (jail) se ve así:

Status for the jail: sshd
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     14
|  `- Journal matches:  _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
   |- Currently banned: 1
   |- Total banned:     3
   `- Banned IP list:   203.0.113.66

El número que demuestra que Fail2ban está leyendo realmente sus inicios de sesión es Total failed. Si es mayor que cero, o aumenta cuando usted falla deliberadamente un inicio de sesión desde otra máquina, el journal está siendo leído y ha terminado. Si se mantiene en 0 sin importar cuántas veces falle, y está seguro de que no está probando desde la dirección en ignoreip, salte a los modos de fallo descritos a continuación.

Observe que la línea Journal matches todavía nombra a sshd.service. En Ubuntu, la unidad de SSH es en realidad ssh.service, pero el filtro incluido también coincide con _COMM=sshd, y OpenSSH en 24.04 registra sus fallos desde un proceso llamado sshd, por lo que la coincidencia funciona. Ese detalle solo importa si está en una versión más reciente de OpenSSH (9.8 o posterior, donde el trabajador por conexión es sshd-session); los modos de fallo cubren ese caso.

Paso 5: Observe un bloqueo real o fuerce uno para realizar pruebas

Los bloqueos reales ocurren por sí solos en cuestión de minutos en cualquier VPS público. Para observar uno, siga el registro:

sudo tail -f /var/log/fail2ban.log

Un bloqueo se ve así:

2026-07-15 10:31:40,502 fail2ban.filter  [812]: INFO    [sshd] Found 203.0.113.66 - 2026-07-15 10:31:40
2026-07-15 10:31:44,118 fail2ban.actions [812]: NOTICE  [sshd] Ban 203.0.113.66

Para probar el mecanismo de principio a fin sin esperar, bloquee manualmente una dirección de documentación, nunca la suya. 203.0.113.66 se encuentra en TEST-NET-3, un bloque reservado para documentación, por lo que no puede ser un host real ni una dirección privada en la red de su proveedor:

sudo fail2ban-client set sshd banip 203.0.113.66

El comando imprime 1 y la dirección aparece bajo Banned IP list en fail2ban-client status sshd. Ahora confirme que el bloqueo existe realmente en el firewall. En Ubuntu 24.04 se utiliza nftables, no iptables:

sudo nft list table inet f2b-table

Verá un conjunto llamado addr-set-sshd que contiene 203.0.113.66, y una cadena f2b-chain que rechaza cualquier origen presente en ese conjunto. Si fail2ban-client indica que una dirección está bloqueada pero no aparece nada en nft list, su acción de bloqueo no coincide con su firewall; consulte la nota sobre nftables/iptables en los modos de fallo.

Paso 6: Desbloquearse y recuperar el acceso si se queda fuera

Si ha bloqueado una dirección que no debía, incluida la suya, elimínela:

sudo fail2ban-client set sshd unbanip 203.0.113.66

Devuelve 1 si la operación tiene éxito. Para eliminar todos los bloqueos de todas las jaulas:

sudo fail2ban-client unban --all

No confíe en que una sesión SSH abierta le salvará: el bloqueo de nftables rechaza todos los paquetes de la dirección bloqueada hacia el puerto 22, incluidas las conexiones establecidas, por lo que una sesión existente se congela en el momento en que se aplica el bloqueo. Si se bloquea a sí mismo y no tiene una entrada ignoreip, quedará fuera hasta que el bloqueo expire. Recupere el acceso a través de la consola web de su proveedor (VNC o serie), que no pasa por SSH, y espere a que pase el tiempo de bantime o ejecute el comando de desbloqueo desde allí.

Paso 7: Hacer que las prohibiciones persistan y aumenten

Fail2ban conserva las prohibiciones activas en una pequeña base de datos SQLite en /var/lib/fail2ban/fail2ban.sqlite3, por lo que sobreviven al reinicio del servicio o del sistema; no las pierde. Las líneas bantime.increment que ya agregó convierten cada infractor reincidente en un problema que aumenta para él, aproximadamente desde una hora hasta una semana.

Para aplicar una política general de "tres infracciones", Fail2ban incluye una cárcel recidive que supervisa su propio /var/log/fail2ban.log y aplica prohibiciones prolongadas a cualquier dirección que haya sido prohibida varias veces en todas las cárceles. Como [DEFAULT] ahora usa el backend systemd, configure esta cárcel para que vuelva a leer el archivo de registro para el que está diseñada:

[recidive]
enabled  = true
backend  = auto
logpath  = /var/log/fail2ban.log
bantime  = 1w
findtime = 1d
maxretry = 5

backend = auto con el logpath explícito mantiene recidive leyendo el fail2ban.log sin formato. Allí aparecen realmente las líneas Ban que cuenta. El valor predeterminado de systemd que configuró globalmente la dirigiría al journal, donde esas líneas no aparecen.

Paso 8: Combínalo con SSH que use solo claves y, mejor aún, con una VPN

Fail2ban solo resulta útil junto con la autenticación mediante claves. En un archivo independiente dentro de /etc/ssh/sshd_config.d/, por ejemplo /etc/ssh/sshd_config.d/00-hardening.conf, establece:

PasswordAuthentication no
KbdInteractiveAuthentication no

Después, sudo systemctl restart ssh. Con las contraseñas desactivadas, la fuerza bruta no puede tener éxito; Fail2ban sirve entonces para reducir el ruido de los registros y expulsar pronto a los escáneres. Una medida aún más sólida consiste en mantener SSH completamente fuera de Internet pública: coloca SSH detrás de una VPN WireGuard autohospedada y configura el firewall para que el puerto 22 solo responda a través del túnel. Nadie puede aplicar fuerza bruta a un puerto al que no puede acceder, y Fail2ban pasa a ser una protección secundaria en lugar de la primera línea de defensa.

Fail2ban no se limita a SSH. Cualquier servicio que registre intentos de inicio de sesión fallidos puede tener una cárcel: un servidor de correo, un sitio nginx o un gestor de contraseñas Vaultwarden autohospedado cuyo inicio de sesión web prefieras no dejar expuesto al relleno de credenciales. Cuando una aplicación web se encuentra detrás de un sitio nginx con un certificado de Let's Encrypt, apunta un filtro de Fail2ban a su registro de acceso, igual que la cárcel de SSH apunta al journal.

Modos de fallo, con las cadenas exactas que verá

"Have not found any log file for sshd jail", y Fail2ban no arranca. Este es el viejo problema auth.log, y en Ubuntu 24.04 solo ocurre cuando /var/log/auth.log no existe (una imagen sin rsyslog, como una imagen mínima o un contenedor) y el journal no se está leyendo: una instalación pip sin defaults-debian.conf, un contenedor sin journal, o una línea backend = auto errónea pegada en jail.local. En un backend de archivos sin /var/log/auth.log, la jaula sshd no puede encontrar su registro y el daemon completo aborta. fail2ban.log muestra:

ERROR   Failed during configuration: Have not found any log file for sshd jail

Debido a que ese error es fatal, el servicio nunca se inicia, y fail2ban-client status reporta entonces el síntoma derivado:

ERROR  Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?

Esa línea de "socket path" no significa que Fail2ban esté roto, significa que nunca arrancó porque una jaula no pudo encontrar su registro. Configurar backend = systemd en [DEFAULT], lo cual el paquete de Ubuntu ya hace por usted, soluciona ambos mensajes a la vez.

La jaula está activa pero Total failed nunca aumenta. El daemon está ejecutándose y el journal se está leyendo, pero los fallos reales se acumulan en journalctl -u ssh mientras el contador permanece en 0. Primero descarte lo obvio: usted está probando desde una dirección listada en ignoreip, por lo que sus propios fallos están exentos por diseño. Si ese no es el caso, usted está en una compilación de OpenSSH donde el trabajador por conexión es sshd-session (9.8 y posteriores), cuyo journal _COMM es sshd-session, no sshd, por lo que la coincidencia predeterminada lo ignora. Amplíe la coincidencia en el bloque [sshd]:

[sshd]
enabled      = true
backend      = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd + _COMM=sshd-session

Reinicie, provoque un fallo de inicio de sesión a propósito desde una dirección que no esté en ignoreip, y confirme que Total failed finalmente aumenta.

Se ha bloqueado a sí mismo: Connection refused. Dejó su propia dirección fuera de ignoreip, probó algunos inicios de sesión fallidos, y ahora:

ssh: connect to host 10.0.0.10 port 22: Connection refused

El rechazo, en lugar de un tiempo de espera silencioso, es el veredicto reject predeterminado de la acción de nftables haciendo su trabajo con usted. Soluciónelo como en el Paso 6: desbloquee desde una sesión en una dirección diferente no bloqueada, o desde la consola del proveedor; una sesión ya abierta desde la dirección bloqueada también se congela. Luego añada su dirección a ignoreip para que no vuelva a ocurrir.

Fail2ban dice que una dirección está bloqueada, pero aún puede conectar. El contador en status sshd aumenta, pero la dirección aún llega al puerto 22. Esto es un desajuste entre la acción de bloqueo y el firewall, y en Ubuntu 24.04 casi siempre significa que sobrescribió el banaction = nftables funcional con banaction = iptables-multiport copiado de una guía antigua, en una máquina sin capa iptables. fail2ban.log muestra:

fail2ban.actions [812]: ERROR  Failed to execute ban jail 'sshd' action 'iptables-multiport'

Elimine esa sobrescritura y deje la acción nftables empaquetada, o, si gestiona el firewall completamente mediante ufw y desea que los bloqueos aparezcan allí, configure banaction = ufw en [DEFAULT]. Reinicie y confirme que la regla aparece con sudo nft list ruleset | grep f2b.

Fail2ban no arranca tras editar jail.local. Un error tipográfico, un encabezado erróneo o un valor de tiempo incorrecto hacen que el servicio se niegue a arrancar. Pida a Fail2ban que verifique la configuración antes de ejecutarse:

sudo fail2ban-client -t

Indica el archivo y la jaula con el problema, por ejemplo Errors in jail 'sshd'. Skipping..., para que corrija la fuente en lugar de adivinar.

FAQ

¿La instalación estándar de Fail2ban en Ubuntu 24.04 bloquea realmente los ataques SSH?

Sí. El paquete incluye /etc/fail2ban/jail.d/defaults-debian.conf, que habilita la jaula sshd, configura backend = systemd para que lea el journal de systemd independientemente de si su imagen escribe en /var/log/auth.log, y establece banaction = nftables para que los bloqueos se apliquen mediante el firewall real de Ubuntu. Una instalación estándar de apt install fail2ban protege SSH desde el primer arranque. Confírmelo con sudo fail2ban-client status sshd y busque un valor distinto de cero en Total failed.

¿Por qué Fail2ban no bloquea nada en mi servidor?

Descarte las tres causas comunes en orden. Es posible que esté realizando pruebas desde una dirección incluida en ignoreip, la cual está exenta por diseño. Puede haber sobrescrito la configuración predeterminada funcional al copiar backend = auto en jail.local desde una guía antigua, lo cual rompe el bloqueo de SSH en una imagen que carece de rsyslog y, por tanto, de auth.log. O bien, puede estar dentro de un contenedor que no tiene un journal de systemd que leer. Compruebe Total failed en fail2ban-client status sshd: si el valor nunca aumenta mientras journalctl -u ssh muestra fallos reales, la jaula está leyendo en el lugar incorrecto.

¿Cómo desbloqueo mi propia dirección IP?

Ejecute sudo fail2ban-client set sshd unbanip YOUR.IP.HERE, que devuelve 1 si tiene éxito, o sudo fail2ban-client unban --all para eliminar todos los bloqueos. Si se ha quedado fuera de SSH, utilice la consola web o VNC de su proveedor para ejecutar el mismo comando; el bloqueo rechaza cada paquete desde su dirección hacia el puerto 22, por lo que incluso una sesión que ya estaba abierta dejará de funcionar. Luego, añada su dirección a ignoreip para que no vuelva a ocurrir.

¿Cuál es la diferencia entre jail.conf y jail.local?

jail.conf contiene los valores predeterminados del desarrollador de Fail2ban y puede ser reemplazado por una actualización del paquete, por lo que cualquier edición ahí corre riesgo. El paquete de Debian/Ubuntu aplica sus propios ajustes mediante jail.d/defaults-debian.conf. Sus cambios deben ir en jail.local, que se lee después de ambos y prevalece sobre ellos, y que las actualizaciones nunca modifican. Solo un archivo *.local dentro de jail.d/ se lee aún más tarde, así que no deje archivos sueltos allí. Mantenga jail.conf como referencia de solo lectura.

¿Reemplaza Fail2ban la autenticación SSH basada en claves?

No. Fail2ban limita la tasa de fallos repetidos desde una misma dirección; no hace nada contra un intento de adivinación lento y distribuido donde cada dirección se mantiene por debajo del umbral. La autenticación solo mediante claves (PasswordAuthentication no) hace que la adivinación de contraseñas sea imposible desde el principio, y Fail2ban entonces reduce el ruido en los registros y expulsa a los escáneres rápidamente. Utilice ambos y, de ser posible, mantenga SSH fuera de la internet pública por completo.