Fail2Ban es una herramienta que monitorea logs del sistema (como los intentos de login de SSH) y bloquea automáticamente, vía iptables o nftables, las IPs que superan un número de intentos fallidos configurado. Cada servicio protegido (SSH, Nginx, Postfix, etc.) tiene su propio jail — una configuración independiente con sus propias reglas de detección y tiempo de bloqueo.
Instalación
Fail2Ban está disponible en los repositorios oficiales de las principales distribuciones.
Debian / Ubuntu:
sudo apt update
sudo apt install fail2ban
sudo systemctl enable --now fail2banRed Hat / CentOS / Rocky / AlmaLinux:
sudo dnf install epel-release
sudo dnf install fail2ban
sudo systemctl enable --now fail2banPor defecto, Fail2Ban trae solo el jail de SSH activo (o ninguno, según la distribución). La configuración recomendada es nunca editar /etc/fail2ban/jail.conf directamente, ya que se sobrescribe con las actualizaciones — en su lugar, se crea /etc/fail2ban/jail.local con las secciones que se quieran personalizar o activar:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.localJails más comunes
Un jail se activa agregando o editando su sección en jail.local con enabled = true. Estos son los más usados en un servidor típico:
- sshd — protege el servicio SSH contra ataques de fuerza bruta en intentos de login. Es el jail más usado y suele venir activo por defecto.
- nginx-http-auth — bloquea IPs que fallan repetidamente la autenticación básica HTTP en Nginx.
- nginx-limit-req — banea IPs que exceden los límites de tasa (
limit_req) configurados en Nginx, útil contra scraping o abuso de API. - postfix — protege el servidor de correo contra intentos de relay no autorizado o fuerza bruta en autenticación SMTP.
- apache-auth — equivalente a
nginx-http-authpero para servidores Apache. - recidive — un jail «de segundo nivel»: vigila el propio log de Fail2Ban y aplica bloqueos más largos a IPs que son baneadas repetidamente por otros jails (reincidentes).
Ejemplo de activación del jail sshd con parámetros personalizados en jail.local:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 3600Donde maxretry es el número de intentos fallidos permitidos, findtime la ventana de tiempo (en segundos) en la que se cuentan esos intentos, y bantime cuánto dura el bloqueo. Tras cualquier cambio en jail.local, se debe reiniciar el servicio:
sudo systemctl restart fail2banAdministración: ver lo baneado
Para consultar el estado general y por jail:
# Listar todos los jails activos
sudo fail2ban-client status
# Ver detalle de un jail específico (intentos totales, IPs baneadas)
sudo fail2ban-client status sshdLa salida de status sshd muestra, entre otros datos, Total failed (intentos fallidos acumulados) y Banned IP list (las IPs actualmente bloqueadas). Para ver el detalle de logs de baneos recientes directamente:
sudo grep 'Ban' /var/log/fail2ban.log | tail -20Y para revisar las reglas realmente aplicadas a nivel de firewall (la capa que efectivamente bloquea el tráfico):
sudo iptables -L -n -v -x f2b-sshdEl resto de esta guía documenta un caso real de troubleshooting: un jail con un volumen alto de intentos fallidos, donde el desbloqueo estándar no reflejaba cambios correctamente.
Diagnóstico del problema
Se detectó un alto volumen de intentos fallidos (Total failed: 50634) con 15 IPs bloqueadas activamente. Se intentaron realizar desbloqueos manuales, pero se identificó que la IP objetivo no estaba en la lista de bloqueados actual (Banned IP list).
Esto es más común de lo que parece: el jail puede tener la IP bloqueada a nivel de iptables/nftables sin que la base de datos interna de Fail2Ban (SQLite, normalmente en /var/lib/fail2ban/fail2ban.sqlite3) refleje el mismo estado — de ahí la necesidad de verificar ambas capas por separado.
1. Consulta y monitoreo
Para verificar el estado del jail e identificar las direcciones bajo sanción:
# Ver IPs actualmente bloqueadas en el jail sshd
sudo fail2ban-client status sshd
# Listar todos los jails activos en la instancia de Fail2Ban
fail2ban-client status
# Verificar reglas activas dentro de la cadena específica de iptables
sudo iptables -L -n -v -x f2b-sshd2. Ejecución de desbloqueo (unban)
Comandos para liberar IPs individuales o masivamente:
# Desbloquear una IP específica por su dirección
sudo fail2ban-client set sshd unbanip <IP_ADDRESS>
# Intentar el desbloqueo masivo de todas las IPs en el jail 'sshd'
sudo fail2ban-client set sshd unbanip ALL
# Limpiar la cadena de iptables (uso extremo si persiste el bloqueo)
sudo iptables -F f2b-sshd3. Automatización y troubleshooting
En caso de que los comandos estándar no reflejen cambios en iptables, se sugiere este bucle para procesar cada IP individualmente:
# Bucle Bash para desbloqueo manual iterativo
for ip in $(sudo fail2ban-client status sshd | awk '/Banned IP list:/ {print $4}'); do
sudo fail2ban-client set sshd unbanip $ip;
done
# Reinicio del servicio para refrescar la base de datos interna y reglas
sudo systemctl restart fail2banWhitelist: prevenir el auto-bloqueo
Para evitar volver a quedar bloqueado por accidente (por ejemplo, tu propia IP fija o la red interna), conviene agregar excepciones permanentes en jail.local:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.100.0/24Cualquier IP dentro de ignoreip nunca será bloqueada por ningún jail, sin importar cuántos intentos fallidos genere.
Notas técnicas adicionales
- Retorno 0: en
fail2ban-client, el retorno0indica que la operación se ejecutó exitosamente, aunque no necesariamente significa que haya habido cambios si la IP ya estaba libre. - Persistencia en iptables: si las IPs siguen bloqueadas tras usar
unbanip ALL, es necesario verificar reglas manuales consudo nft list ruleseto limpiar directamente la cadena deiptables. - Diferencia entre capas: un
unbanipexitoso a nivel de Fail2Ban no siempre elimina la regla correspondiente en el firewall si hubo inconsistencias previas — por eso conviene verificar ambos lados (Fail2Ban y iptables/nftables) tras cualquier operación de desbloqueo masivo.