Instalar y configurar Fail2Ban en un VPS Linux

13 min de lectura·Matthieu·ubuntudebianufwnftablesnginxsshsecurityfail2ban|

Configure Fail2Ban para bloquear ataques de fuerza bruta en SSH y Nginx. Cubre acciones de baneo con UFW y nftables, jails personalizadas, escalamiento recidive y pruebas de filtros en Ubuntu 24.04 y Debian 12.

Fail2Ban vigila sus archivos de log en busca de fallos de autenticación repetidos y bloquea las direcciones IP infractoras a través de su firewall. Detiene los ataques de fuerza bruta antes de que tengan éxito. Un VPS recién desplegado suele recibir intentos de conexión SSH en cuestión de minutos. Fail2Ban es la defensa estándar.

Esta guía cubre la instalación en Ubuntu 24.04 y Debian 12, la configuración de jails para SSH y Nginx, ambos backends de acción de baneo (UFW y nftables), la jail recidive para reincidentes, y las pruebas de filtros con fail2ban-regex. Cada cambio de configuración incluye un paso de verificación.

Requisitos previos: Un VPS con Ubuntu 24.04 o Debian 12 con acceso root o sudo. Su firewall ya debe estar activo y SSH debe estar asegurado. Esta guía forma parte de la serie seguridad VPS Linux.

¿Cómo instalo Fail2Ban en Ubuntu 24.04 y Debian 12?

Instale Fail2Ban con apt. El paquete está en los repositorios por defecto de ambas distribuciones. Ubuntu 24.04 incluye la versión 1.0.2, al igual que Debian 12. En Debian 12, también necesita python3-systemd para que Fail2Ban pueda leer el journal de systemd.

sudo apt update && sudo apt install -y fail2ban

En Debian 12, instale los bindings de Python para systemd:

sudo apt install -y python3-systemd

Habilite e inicie el servicio:

sudo systemctl enable --now fail2ban

El flag enable hace que Fail2Ban se inicie en el arranque. El flag --now lo inicia de inmediato. Verifique que está funcionando:

sudo systemctl status fail2ban

Debería ver Active: active (running) en la salida. Si el estado muestra failed, consulte el journal:

journalctl -u fail2ban -n 20 --no-pager

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

jail.conf es el archivo de configuración por defecto incluido con el paquete. Las actualizaciones del paquete lo sobrescriben. Nunca edite jail.conf directamente. Sus cambios desaparecerán en el próximo apt upgrade.

jail.local es el archivo de sobreescritura tradicional. Fail2Ban lee primero jail.conf y luego aplica los ajustes de jail.local por encima. Funciona, pero el archivo crece hasta convertirse en un monolito difícil de mantener.

El directorio jail.d/ es el mejor enfoque. Coloque un archivo .conf por jail. Fail2Ban los carga en orden alfabético después de jail.conf y jail.local. Cada servicio queda aislado y es fácil añadir o eliminar jails sin tocar otras configuraciones.

Esta guía usa archivos drop-in en jail.d/. Compruebe que el directorio existe:

ls /etc/fail2ban/jail.d/

Ya debería existir. Si ve archivos como defaults-debian.conf, es normal. En Ubuntu 24.04, este archivo habilita la jail sshd y establece banaction = nftables como acción de baneo por defecto. En Debian 12, habilita la jail sshd. Como Fail2Ban carga los archivos de jail.d/ en orden alfabético, cualquier archivo de configuración por defecto personalizado debe ordenarse después de defaults-debian.conf para sobreescribir sus ajustes. Esta guía usa zz-defaults.conf por esa razón.

¿Cómo configuro la jail SSH en Fail2Ban?

La jail SSH monitoriza los logs de autenticación y banea las IP que fallan demasiadas veces al iniciar sesión. En Ubuntu 24.04 y Debian 12, la jail sshd está habilitada por defecto a través de /etc/fail2ban/jail.d/defaults-debian.conf. Pero los valores por defecto son permisivos (5 reintentos, baneo de 10 minutos). Ajústelos.

Cree una configuración drop-in:

sudo tee /etc/fail2ban/jail.d/sshd.conf > /dev/null << 'EOF'
[sshd]
enabled = true
mode = aggressive
port = ssh
backend = systemd
maxretry = 3
findtime = 600
bantime = 3600
EOF

Significado de cada parámetro:

Parámetro Valor Significado
enabled true Activa esta jail
mode aggressive Detecta más patrones de fallo SSH, incluyendo fallos de autenticación por clave
port ssh Monitoriza el puerto SSH (se resuelve a 22, o su puerto personalizado)
backend systemd Lee del journal de systemd en lugar de archivos de log
maxretry 3 Banea después de 3 intentos fallidos
findtime 600 Cuenta fallos en una ventana de 10 minutos
bantime 3600 Banea durante 1 hora (3600 segundos)

Si cambió su puerto SSH (debería hacerlo), reemplace ssh por su número de puerto:

port = 2222

Reinicie Fail2Ban para aplicar los cambios:

sudo systemctl restart fail2ban

Verifique que la jail está activa:

sudo fail2ban-client status sshd

Salida esperada:

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

Fíjese bien: la línea Journal matches confirma que Fail2Ban lee del journal de systemd, no de un archivo de log. Esto es correcto para Ubuntu 24.04 y Debian 12.

¿Cómo configuro Fail2Ban con UFW como acción de baneo?

Si usa UFW como firewall, configure Fail2Ban para insertar reglas de baneo a través de UFW. Es el camino más sencillo, adecuado para la mayoría de configuraciones.

Cree un archivo de valores por defecto que establezca UFW como acción de baneo. El nombre zz-defaults.conf es intencional: en Ubuntu 24.04, el paquete incluye defaults-debian.conf que establece banaction = nftables. Su archivo debe ordenarse alfabéticamente después para sobreescribir ese valor.

sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = ufw
banaction_allports = ufw
backend = systemd
EOF

Reinicie y verifique:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Cuando Fail2Ban banea una IP, ejecuta ufw insert 1 deny from <IP> to any. Compruebe las reglas UFW después de un baneo:

sudo ufw status numbered

Verá las reglas deny de Fail2Ban en la parte superior de la lista.

¿Cómo configuro Fail2Ban para usar nftables en lugar de iptables?

Para servidores de producción que usan nftables directamente (sin UFW), utilice la acción de baneo nftables-multiport. Fail2Ban crea su propia tabla nftables y gestiona las reglas de baneo allí sin interferir con su conjunto de reglas existente.

Cree el archivo de valores por defecto. En Ubuntu 24.04, defaults-debian.conf ya establece banaction = nftables, así que este paso es técnicamente opcional. Pero es buena práctica ser explícito. En Debian 12, este archivo es obligatorio.

sudo tee /etc/fail2ban/jail.d/zz-defaults.conf > /dev/null << 'EOF'
[DEFAULT]
banaction = nftables-multiport
banaction_allports = nftables[type=allports]
chain = input
backend = systemd
EOF

Reinicie y verifique:

sudo systemctl restart fail2ban
sudo fail2ban-client status sshd

Para confirmar la integración con nftables, liste la tabla de Fail2Ban:

sudo nft list tables

Debería ver una tabla llamada inet f2b-table. Después de un baneo, inspeccione su contenido:

sudo nft list table inet f2b-table

Comparación de acciones de baneo: UFW vs nftables

Aspecto UFW (banaction = ufw) nftables (banaction = nftables-multiport)
Comando de baneo ufw insert 1 deny from <IP> Añade la IP a un conjunto nftables
Dónde aparecen las reglas ufw status numbered nft list table inet f2b-table
Soporte IPv6 Sí (UFW lo gestiona) Sí (familia inet)
Persistencia Las reglas UFW persisten entre reinicios Fail2Ban las reaplica al iniciar
Rendimiento Coincidencia lineal de reglas Búsqueda basada en conjuntos (más rápida a escala)
Ideal para Configuraciones simples, un solo servicio Producción, muchas jails, alto volumen de baneos

Elija un enfoque. No mezcle acciones de baneo UFW y nftables en el mismo servidor.

¿Cómo añado mi dirección IP a la lista blanca de Fail2Ban?

Añada su IP a ignoreip para evitar bloquearse a sí mismo. Esto es importante. Si escribe mal su contraseña tres veces, Fail2Ban baneará su propia IP. Perderá el acceso SSH.

Añada su IP a los valores por defecto:

sudo tee /etc/fail2ban/jail.d/01-whitelist.conf > /dev/null << 'EOF'
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 YOUR_IP_HERE
EOF

Reemplace YOUR_IP_HERE por su dirección IP pública real. Puede encontrarla ejecutando curl -4 ifconfig.me desde su máquina local. Añada múltiples IP separadas por espacios.

Reinicie y verifique que la lista blanca está cargada:

sudo systemctl restart fail2ban
sudo fail2ban-client get sshd ignoreip

La salida lista todas las IP y rangos en la lista blanca. Confirme que su IP aparece en la lista.

Advertencia: Si se conecta desde una IP dinámica, añadirla a la lista blanca ofrece protección limitada. Mantenga un método de acceso secundario (acceso por consola desde el panel de su proveedor de hosting) como respaldo en caso de baneo.

¿Cómo protejo Nginx con jails Fail2Ban personalizadas?

Fail2Ban incluye varios filtros para Nginx. Los más útiles son nginx-http-auth para fuerza bruta en autenticación HTTP básica y nginx-botsearch para escáneres que sondean rutas inexistentes. También puede crear filtros personalizados para patrones específicos de su aplicación.

Jail nginx-http-auth

Esta jail banea las IP que fallan repetidamente en la autenticación HTTP básica. Lee del log de errores de Nginx.

sudo tee /etc/fail2ban/jail.d/nginx-http-auth.conf > /dev/null << 'EOF'
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 3
findtime = 600
bantime = 3600
EOF

Jail nginx-botsearch

Esta jail captura bots que escanean rutas vulnerables (/wp-admin, /phpmyadmin, /.env). Lee del log de acceso de Nginx las respuestas 404.

sudo tee /etc/fail2ban/jail.d/nginx-botsearch.conf > /dev/null << 'EOF'
[nginx-botsearch]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 7200
EOF

Filtro personalizado: banear errores 4xx excesivos

Para aplicaciones detrás de Nginx, puede querer banear IP que generen demasiados errores 4xx. Esto captura credential stuffing, abuso de API y enumeración de rutas. Los filtros integrados no cubren este caso, así que cree un filtro personalizado.

Cree el archivo de filtro:

sudo tee /etc/fail2ban/filter.d/nginx-4xx.conf > /dev/null << 'EOF'
[Definition]
failregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
ignoreregex = ^<HOST> - \S+ \[.*\] "[A-Z]+ /favicon\.ico
              ^<HOST> - \S+ \[.*\] "[A-Z]+ /robots\.txt
EOF

La failregex coincide con líneas del log de acceso de Nginx donde la respuesta es un código de estado 4xx. La ignoreregex excluye falsos positivos comunes como las peticiones a favicon.ico y robots.txt.

Cree la jail:

sudo tee /etc/fail2ban/jail.d/nginx-4xx.conf > /dev/null << 'EOF'
[nginx-4xx]
enabled = true
port = http,https
filter = nginx-4xx
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 600
bantime = 3600
EOF

El maxretry más alto de 20 evita banear usuarios legítimos que encuentran algunos 404 durante la navegación normal.

Reinicie Fail2Ban y compruebe que todas las jails están cargadas:

sudo systemctl restart fail2ban
sudo fail2ban-client status

Salida esperada mostrando todas las jails activas:

Status
|- Number of jail:      4
`- Jail list:   nginx-4xx, nginx-botsearch, nginx-http-auth, sshd

Para más información sobre la protección de Nginx a nivel de aplicación, consulte la guía sobre rate limiting en Nginx.

¿Cómo pruebo los filtros de Fail2Ban con fail2ban-regex?

Antes de activar una jail, pruebe su filtro contra logs reales. La herramienta fail2ban-regex ejecuta un filtro contra un archivo de log e informa de las coincidencias. Esto evita desplegar un filtro que no coincida con nada (inútil) o que coincida con todo (banea usuarios legítimos).

Pruebe el filtro personalizado nginx-4xx:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Ejemplo de salida:

Running tests
=============

Use   failregex filter file : nginx-4xx, basedir: /etc/fail2ban
Use         log file : /var/log/nginx/access.log
Use         encoding : utf-8

Results
=======

Failregex: 42 total
|-  #) [# of hits] regular expression
|   1) [42] ^<HOST> - \S+ \[.*\] "[A-Z]+ .+" (400|401|403|404|405) \d+
`-

Ignoreregex: 3 total

Date template hits:
...

Lines: 1842 lines, 0 ignored, 42 matched, 1800 missed

Fíjese bien: la salida muestra 42 líneas coincidentes de 1842. Es una proporción razonable. Si el filtro coincidiera con el 90 % de las líneas, la regex es demasiado amplia. Si coincidiera con 0 líneas, o la regex es incorrecta o el log aún no tiene errores 4xx.

Para ver qué líneas coincidieron:

sudo fail2ban-regex --print-all-matched /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Para ver qué líneas no coincidieron (útil para ajustar):

sudo fail2ban-regex --print-all-missed /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-4xx.conf

Pruebe el filtro sshd integrado contra el journal de systemd:

sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf

¿Cómo configuro la jail recidive para reincidentes?

La jail recidive vigila el propio log de Fail2Ban. Cuando una IP es baneada varias veces en cualquier jail, la jail recidive aplica un baneo más largo. Es una escalada: primera infracción = 1 hora, reincidentes = 1 semana.

En un servidor de producción con mucho tráfico, la jail recidive es lo que realmente mantiene alejados a los atacantes persistentes.

sudo tee /etc/fail2ban/jail.d/recidive.conf > /dev/null << 'EOF'
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
banaction = %(banaction_allports)s
maxretry = 3
findtime = 86400
bantime = 604800
EOF
Parámetro Valor Significado
logpath /var/log/fail2ban.log Ruta de log de respaldo. Con backend = systemd, Fail2Ban lee sus propias entradas de journal en su lugar (el filtro recidive tiene una directiva journalmatch integrada)
maxretry 3 Se activa tras 3 baneos de otras jails
findtime 86400 Revisa las últimas 24 horas (86400 segundos)
bantime 604800 Banea durante 1 semana (604800 segundos)
banaction %(banaction_allports)s Bloquea todos los puertos, no solo el que provocó el baneo

El filtro recidive viene incluido con Fail2Ban en /etc/fail2ban/filter.d/recidive.conf. No necesita crearlo.

Reinicie y verifique:

sudo systemctl restart fail2ban
sudo fail2ban-client status recidive

¿Cómo monitorizo los baneos y desbaneo una dirección IP?

Fail2Ban proporciona fail2ban-client para todas las tareas de monitorización y gestión. Estos comandos funcionan independientemente de su backend de acción de baneo.

Comprobar el estado general

sudo fail2ban-client status

Lista todas las jails activas y sus contadores de baneo.

Comprobar una jail específica

sudo fail2ban-client status sshd

Muestra las IP actualmente baneadas, el total de baneos y los fallos actuales.

Banear manualmente una IP

sudo fail2ban-client set sshd banip 203.0.113.50

Desbanear una IP

sudo fail2ban-client set sshd unbanip 203.0.113.50

Si la IP fue baneada por la jail recidive, desbaneéla allí también:

sudo fail2ban-client set recidive unbanip 203.0.113.50

Comprobar qué acción de baneo usa una jail

sudo fail2ban-client get sshd actions

Recargar la configuración sin reiniciar

sudo fail2ban-client reload

Leer el log de Fail2Ban

journalctl -u fail2ban -f

Esto sigue el log del servicio Fail2Ban en tiempo real. Verá los eventos de baneo y desbaneo a medida que ocurran.

El log de aplicación de Fail2Ban con los detalles de los baneos:

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

Referencia de comandos fail2ban-client

Comando Función
fail2ban-client status Listar todas las jails
fail2ban-client status <jail> Mostrar detalles de la jail e IP baneadas
fail2ban-client set <jail> banip <IP> Banear manualmente una IP
fail2ban-client set <jail> unbanip <IP> Desbanear una IP
fail2ban-client reload Recargar toda la configuración
fail2ban-client reload <jail> Recargar una sola jail
fail2ban-client get <jail> bantime Mostrar duración del baneo
fail2ban-client get <jail> findtime Mostrar ventana de fallos
fail2ban-client get <jail> maxretry Mostrar umbral de reintentos
fail2ban-client get <jail> ignoreip Mostrar IP en lista blanca
fail2ban-client get <jail> actions Mostrar acción de baneo en uso

Verificación de extremo a extremo: provocar un baneo y confirmar que funciona

No asuma que su configuración funciona. Pruébela. Provoque un baneo real y verifique toda la cadena: detección en logs, acción de baneo, regla de firewall y desbaneo.

Paso 1: Desde otra máquina (no su IP en la lista blanca), intente inicios de sesión SSH con una contraseña incorrecta. Después de 3 fallos (coincidiendo con maxretry), la conexión debería ser rechazada.

Si no tiene una segunda máquina, use fail2ban-client para simular un baneo:

sudo fail2ban-client set sshd banip 198.51.100.25

Paso 2: Verifique que el baneo está registrado:

sudo fail2ban-client status sshd

La IP baneada debería aparecer en Banned IP list.

Paso 3: Verifique que la regla de firewall existe.

Para UFW:

sudo ufw status numbered | grep 198.51.100.25

Para nftables:

sudo nft list table inet f2b-table

La IP debería aparecer en un conjunto dentro de la tabla.

Paso 4: Desbanee y verifique la eliminación:

sudo fail2ban-client set sshd unbanip 198.51.100.25
sudo fail2ban-client status sshd

La IP ya no debería aparecer en la lista de baneos. Compruebe el firewall de nuevo para confirmar que la regla fue eliminada.

Referencia de parámetros de configuración de Fail2Ban

Parámetro Por defecto Recomendado Descripción
bantime 10m 1h o 3600 Duración del baneo
findtime 10m 10m o 600 Ventana para contar fallos
maxretry 5 3 para SSH, 5-20 para web Fallos antes del baneo
ignoreip 127.0.0.1/8 ::1 Añada su IP IP que nunca se banean
banaction nftables (Ubuntu 24.04), iptables-multiport (upstream) ufw o nftables-multiport Comando de firewall a ejecutar
backend auto systemd Fuente de logs (journal systemd en distribuciones modernas)
destemail root@localhost Su email Destinatario de alertas
action %(action_)s %(action_mwl)s para alertas por email Acción ejecutada al banear

¿Algo salió mal?

Fail2Ban no arranca: Compruebe si hay errores de sintaxis en sus archivos de jail. Un corchete faltante o un valor inválido impedirán el arranque.

sudo fail2ban-client -t

Esto prueba la configuración sin iniciar el servicio. Corrija los errores que reporte.

La jail muestra 0 coincidencias pero hay ataques: El backend probablemente es incorrecto. En Ubuntu 24.04 y Debian 12, use backend = systemd. Si usa backend = auto y el sistema no tiene /var/log/auth.log, Fail2Ban no lee nada.

La IP baneada aún puede conectarse: La acción de baneo no coincide con su firewall. Si usa UFW, establezca banaction = ufw. Si usa nftables directamente, establezca banaction = nftables-multiport. Compruebe que la regla de firewall existe después de un baneo.

Se ha baneado a sí mismo: Acceda a su servidor a través de la consola web de su proveedor de hosting (VNC/KVM). Desde allí:

sudo fail2ban-client set sshd unbanip YOUR_IP

O detenga Fail2Ban por completo:

sudo systemctl stop fail2ban

Luego corrija su configuración ignoreip y reinicie.

Fail2Ban consume demasiada memoria: En servidores con archivos de log grandes, Fail2Ban puede consumir memoria. Establezca dbpurgeage para limitar el tamaño de la base de datos:

sudo tee /etc/fail2ban/jail.d/99-performance.conf > /dev/null << 'EOF'
[DEFAULT]
dbpurgeage = 7d
EOF

Copyright 2026 Virtua.Cloud. Todos los derechos reservados. Este contenido es una obra original del equipo de Virtua.Cloud. La reproducción, republicación o redistribución sin permiso escrito está prohibida.

¿Listo para probarlo?

Protege tu VPS Linux con Fail2Ban.

Ver planes VPS