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, acceso como root o mediante sudo y SSH configurado y operativo, preferiblemente con autenticación mediante claves. Fail2ban consume pocos recursos: unas decenas de megabytes de RAM y no requiere ajustar límites.
Ahora, la parte que casi todas las guías antiguas describen de forma incorrecta. Durante años, la recomendación estándar fue «instale Fail2ban y añada backend = systemd, porque Ubuntu dejó de escribir /var/log/auth.log». Esa recomendación se basa en un cambio real: las imágenes modernas de servidores y de nube se distribuyen sin rsyslog, por lo que SSH solo escribe en el journal de systemd y ese archivo de texto ya no existe. Sin embargo, en Ubuntu 24.04 el paquete de Fail2ban ya contempla este cambio. El paquete instala /etc/fail2ban/jail.d/defaults-debian.conf, y ese archivo, no los valores predeterminados del proyecto original, es el que realmente utiliza el servidor:
[DEFAULT]
banaction = nftables
banaction_allports = nftables[type=allports]
backend = systemd
[sshd]
enabled = trueLea esto con atención, porque resuelve dos cuestiones antes de modificar nada. backend = systemd significa que la jail de SSH lee el journal, por lo que la ausencia de auth.log no importa. banaction = nftables significa que las prohibiciones se aplican mediante nftables, el firewall que Ubuntu 24.04 utiliza realmente, en lugar del iptables antiguo. Y [sshd] enabled = true significa que la jail está habilitada desde el primer arranque. En resumen: un apt install fail2ban estándar de Ubuntu 24.04 bloquea los ataques de fuerza bruta contra SSH sin configuración adicional. La mayor parte del trabajo consiste en confirmarlo, ajustar la política y asegurarse de no bloquear su propio acceso.
El problema antiguo de auth.log todavía aparece en tres situaciones, y conviene reconocerlas: instaló Fail2ban con pip en lugar de apt, por lo que no existe defaults-debian.conf; está dentro de un contenedor sin privilegios que no tiene un journal de systemd disponible para leer; o siguió un tutorial antiguo y pegó backend = auto en su propio jail.local, sobrescribiendo la configuración predeterminada funcional. La sección sobre modos de fallo muestra exactamente cómo se presenta cada caso.
Paso 1: Instalarlo y confirmar que ya está bloqueando
sudo apt update
sudo apt install -y fail2banUbuntu 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 fail2banDebe aparecer active (running). Después, compruebe el jail que ya está funcionando:
sudo fail2ban-client status sshdEn 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: Edita jail.local, nunca jail.conf
Fail2ban mantiene sus valores predeterminados originales en /etc/fail2ban/jail.conf. No edites ese archivo. Cada apt upgrade del paquete puede reemplazarlo, y tus cambios desaparecerán sin aviso. Fail2ban lee los archivos en un orden fijo: primero jail.conf, después todo lo que haya en jail.d/, luego jail.local, y prevalece el último valor. El archivo .local es tuyo, y las actualizaciones del paquete nunca lo modifican. La misma regla se aplica a los filtros: un archivo *.local reemplaza al filter.d/*.conf incluido en el paquete.
Por tanto, debes escribir un jail.local pequeño que reemplace solo los pocos ajustes que necesitas y dejar jail.conf y jail.d/defaults-debian.conf, incluidos en el paquete, intactos como referencia.
Paso 3: Escribir /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.localIntroduzca 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 = trueCada línea tiene una función:
bantime,findtimeymaxretrydefinen 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.ignoreipes 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 = truehace que cada prohibición repetida dure más que la anterior: una hora, después dos y luego cuatro, hastabantime.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.meAquí puede generar un jail.local adaptado a sus puertos y a su política de prohibiciones, y después pegarlo en el archivo:
Paso 4: Reinicie y verifique que está leyendo el journal
sudo fail2ban-client -t
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd-t ejecuta primero una prueba de configuración, por lo que un error tipográfico en jail.local falla claramente aquí en lugar de dejar el servicio detenido. El estado de una jail operativa tiene este aspecto:
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: 10.0.0.66El número que demuestra que Fail2ban está leyendo realmente los inicios de sesión es Total failed. Si es mayor que cero o aumenta cuando provoca deliberadamente un fallo de inicio de sesión desde otra máquina, se está leyendo el journal y el proceso ha terminado. Si permanece en 0 independientemente de cuántas veces falle, y está seguro de que no está realizando la prueba desde la dirección incluida en ignoreip, consulte los modos de fallo que aparecen más abajo.
Observe que la línea Journal matches todavía indica 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. Este detalle solo importa si utiliza 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 una prohibición real o fuerce una para realizar pruebas
Las prohibiciones reales llegan por sí solas en pocos minutos en cualquier VPS público. Para observar una, siga el registro:
sudo tail -f /var/log/fail2ban.logUna prohibición tiene este aspecto:
2026-07-15 10:31:40,502 fail2ban.filter [812]: INFO [sshd] Found 10.0.0.66 - 2026-07-15 10:31:40
2026-07-15 10:31:44,118 fail2ban.actions [812]: NOTICE [sshd] Ban 10.0.0.66Para probar todo el proceso sin esperar, prohíba manualmente una dirección destinada a documentación, nunca la suya:
sudo fail2ban-client set sshd banip 10.0.0.66Muestra 1 y la dirección aparece en Banned IP list dentro de fail2ban-client status sshd. Ahora confirme que el bloqueo existe realmente en el firewall. En Ubuntu 24.04 se usa nftables, no iptables:
sudo nft list table inet f2b-tableVerá un conjunto llamado addr-set-sshd que contiene 10.0.0.66 y una cadena f2b-chain que rechaza cualquier origen incluido en ese conjunto. Si fail2ban-client indica que una dirección está prohibida, pero no aparece nada en nft list, la acción de prohibición no coincide con el firewall. Consulte la nota sobre nftables/iptables en la sección de modos de fallo.
Paso 6: Quite su propio bloqueo y recupere el acceso si queda bloqueado
Si bloqueó una dirección que no debía, incluida la suya, elimínela:
sudo fail2ban-client set sshd unbanip 10.0.0.66Devuelve 1 si la operación se realiza correctamente. Para eliminar todos los bloqueos de todas las jaulas:
sudo fail2ban-client unban --allNo confíe en que una sesión SSH ya abierta lo proteja: el bloqueo de nftables rechaza todos los paquetes de la dirección bloqueada al 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, perderá el acceso hasta que expire el bloqueo. Recupere el acceso mediante la consola web de su proveedor (VNC o serie), que no utiliza SSH, y espere a que transcurra bantime o ejecute allí el comando para quitar el bloqueo.
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 = 5backend = 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 noDespué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 y cadenas exactas que verá
"Have not found any log file for sshd jail", y Fail2ban no se inicia. Este es el antiguo problema de auth.log. En Ubuntu 24.04 solo aparece si algo ha sobrescrito el valor predeterminado del paquete, si hay una instalación de pip sin defaults-debian.conf, si se usa un contenedor sin journal o si se pegó un backend = auto suelto en jail.local. En un backend de archivos sin /var/log/auth.log, el jail sshd no puede encontrar su registro y todo el daemon se cancela. fail2ban.log muestra:
ERROR Failed during configuration: Have not found any log file for sshd jailComo este error es fatal, el servicio nunca se inicia. A continuación, fail2ban-client status informa del síntoma derivado:
ERROR Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?La línea "socket path" no significa que Fail2ban esté dañado. Significa que nunca se inició porque un jail no pudo encontrar su registro. Establecer backend = systemd en [DEFAULT], algo que el paquete de Ubuntu ya hace, corrige ambos mensajes a la vez.
El jail está activo, pero Total failed nunca cambia. El daemon se está ejecutando y se está leyendo el journal, pero los fallos reales se acumulan en journalctl -u ssh mientras el contador permanece en 0. Primero descarte lo evidente: está probando desde una dirección incluida en ignoreip, por lo que sus propios fallos están excluidos intencionadamente. Si no es eso, usa una compilación de OpenSSH en la que el worker por conexión es sshd-session (9.8 y posteriores). Su journal _COMM es sshd-session, no sshd, por lo que el patrón incluido no lo detecta. Amplíe el patrón en el bloque [sshd]:
[sshd]
enabled = true
backend = systemd
journalmatch = _SYSTEMD_UNIT=ssh.service + _COMM=sshd + _COMM=sshd-sessionReinicie el servicio, provoque un fallo de inicio de sesión desde una dirección que no esté en ignoreip y confirme que Total failed finalmente aumenta.
Se ha bloqueado: Connection refused. No incluyó su propia dirección en ignoreip, probó varios inicios de sesión incorrectos y ahora:
ssh: connect to host 10.0.0.10 port 22: Connection refusedLa denegación, en lugar de un tiempo de espera silencioso, se debe al veredicto predeterminado reject de la acción nftables. Se está aplicando a su propia conexión. Corríjalo como se indica en el paso 6: quite el bloqueo desde una sesión en otra dirección que no esté bloqueada o desde la consola del proveedor. Una sesión ya abierta desde la dirección bloqueada también se congela. Después, añada su dirección a ignoreip para evitar que vuelva a ocurrir.
Fail2ban indica que una dirección está bloqueada, pero aún puede conectarse. El contador de status sshd aumenta, pero la dirección aún llega al puerto 22. Esto indica una incompatibilidad entre la acción de bloqueo y el firewall. En Ubuntu 24.04, casi siempre significa que sobrescribió el banaction = nftables funcional con banaction = iptables-multiport, copiado de una guía antigua, en un sistema sin una capa de iptables. fail2ban.log muestra:
fail2ban.actions [812]: ERROR Failed to execute ban jail 'sshd' action 'iptables-multiport'Elimine esa sobrescritura y deje activa la acción nftables proporcionada por el paquete. Como alternativa, si administra todo el firewall mediante ufw y quiere que los bloqueos aparezcan allí, establezca banaction = ufw en [DEFAULT]. Reinicie el servicio y confirme que la regla aparece con sudo nft list ruleset | grep f2b.
Fail2ban no se inicia después de editar jail.local. Un error tipográfico, un encabezado suelto o un valor de tiempo incorrecto pueden impedir que el servicio se inicie. Pida a Fail2ban que compruebe la configuración antes de ejecutarlo:
sudo fail2ban-client -tEl comando indica el archivo y el jail con el problema, por ejemplo Errors in jail 'sshd'. Skipping.... Así puede corregir el origen en lugar de adivinar.
FAQ
¿La instalación estándar de Fail2ban en Ubuntu 24.04 bloquea realmente los ataques contra SSH?
Sí. El paquete incluye /etc/fail2ban/jail.d/defaults-debian.conf, que habilita la jaula sshd, establece backend = systemd para que lea el journal de systemd en lugar del /var/log/auth.log inexistente y establece banaction = nftables para que los bloqueos se apliquen mediante el firewall real de Ubuntu. Un apt install fail2ban sin cambios 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?
Descarta las tres causas habituales en este orden. Es posible que estés probando desde una dirección incluida en ignoreip, que está exenta por diseño. También es posible que hayas sustituido la configuración predeterminada funcional al pegar backend = auto en jail.local siguiendo una guía antigua, lo que impide leer el journal en una imagen sin auth.log. O quizá estés dentro de un contenedor sin ningún journal de systemd que leer. Comprueba Total failed en fail2ban-client status sshd: si nunca aumenta mientras journalctl -u ssh muestra fallos reales, la jaula está leyendo el lugar equivocado.
¿Cómo desbloqueo mi propia dirección IP?
Ejecuta sudo fail2ban-client set sshd unbanip YOUR.IP.HERE, que devuelve 1 si la operación se realiza correctamente, o sudo fail2ban-client unban --all para eliminar todos los bloqueos. Si no puedes acceder por SSH, utiliza la consola web o VNC de tu proveedor para ejecutar el mismo comando. El bloqueo rechaza todos los paquetes de tu dirección hacia el puerto 22, por lo que incluso una sesión ya abierta deja de funcionar. Después, añade tu dirección a ignoreip para evitar que vuelva a bloquearse.
¿Cuál es la diferencia entre jail.conf y jail.local?
jail.conf contiene los valores predeterminados de Fail2ban y se sobrescribe con cada actualización del paquete, por lo que cualquier modificación termina perdiéndose. El paquete de Debian/Ubuntu aplica su propia configuración mediante jail.d/defaults-debian.conf. Tus cambios deben estar en jail.local, que se lee al final y prevalece sobre ambos archivos, y que las actualizaciones nunca modifican. Deja jail.conf como referencia de solo lectura.
¿Fail2ban sustituye la autenticación SSH basada en claves?
No. Fail2ban limita la frecuencia de los fallos repetidos desde una dirección; no puede hacer nada contra un intento lento y distribuido en el que cada dirección permanece por debajo del umbral. La autenticación exclusiva mediante claves (PasswordAuthentication no) hace que los intentos de adivinar contraseñas sean imposibles, y Fail2ban reduce el ruido de los logs y expulsa antes a los escáneres. Utiliza ambos mecanismos y, preferiblemente, mantén SSH completamente fuera de Internet pública.