Cómo configurar Fail2ban para proteger SSH y Nginx
Los intentos automatizados contra SSH y sistemas de autenticación web consumen recursos y llenan los registros, incluso cuando no consiguen acceder. Fail2ban reduce ese ruido detectando fallos repetidos y aplicando bloqueos temporales mediante el firewall del servidor.
La clave es desplegarlo de forma gradual: confirmar primero qué logs existen, probar los filtros, validar la configuración y mantener una vía de acceso administrativo.
En Nginx, el filtro incluido nginx-http-auth protege autenticación HTTP básica. No detecta automáticamente los intentos fallidos de formularios como WordPress, webmail o paneles desarrollados a medida. Esos casos requieren que la aplicación registre la IP y el fallo de autenticación en un formato compatible o que se cree un filtro específico.Cuándo conviene usar Fail2ban
Fail2ban resulta especialmente útil en:
- Servidores con SSH expuesto a internet.
- Sitios con autenticación HTTP básica en Nginx.
- Paneles administrativos que generan logs de autenticación adecuados.
- Infraestructuras sin WAF ni un sistema externo de prevención de intrusiones.
Fail2ban complementa, pero no sustituye, el uso de claves SSH, MFA, actualizaciones de seguridad, restricciones de red y contraseñas robustas.
Requisitos previos
Antes de comenzar, necesitas:
- Debian o Ubuntu con acceso mediante
sudo. - Una segunda sesión SSH abierta o acceso a la consola del proveedor.
- La IP pública administrativa que no debe bloquearse.
- SSH y, opcionalmente, Nginx en funcionamiento.
- Un firewall compatible con las acciones instaladas por el paquete de Fail2ban.
- Logs que contengan la IP real del cliente.
Comprueba de dónde obtiene SSH sus eventos:
sudo journalctl -u ssh.service --since "15 minutes ago" --no-pager
sudo test -r /var/log/auth.log && sudo tail -n 30 /var/log/auth.logPara Nginx:
sudo test -r /var/log/nginx/error.log
sudo tail -n 30 /var/log/nginx/error.logSi el servidor está detrás de un proxy inverso, balanceador o CDN, confirma que Nginx registra la IP real del cliente y que solo confía en proxies conocidos. De lo contrario, Fail2ban podría bloquear la IP compartida del intermediario.
Cómo funciona Fail2ban
El proceso conecta cinco componentes:
- Log: SSH o Nginx registra un fallo.
- Filtro: una expresión reconoce el evento y extrae la IP.
- Jail: cuenta los fallos ocurridos dentro de
findtime. - Acción: al alcanzar
maxretry, agrega un bloqueo al firewall. - Unban: elimina el bloqueo después de
bantimeo por una orden administrativa.
Una jail combina un filtro con una o más acciones. El bloqueo se produce cuando una IP alcanza maxretry coincidencias dentro de findtime; la acción de desbloqueo se ejecuta al finalizar bantime. Manual de configuración de Fail2ban.
Paso 1: instalar Fail2ban
sudo apt update
sudo apt install -y fail2ban
sudo systemctl enable --now fail2banComprueba que el daemon responda:
sudo systemctl status fail2ban --no-pager
sudo fail2ban-client pingLa respuesta esperada de la última orden es Server replied: pong.
Paso 2: configurar la jail de SSH
No modifiques /etc/fail2ban/jail.conf. Los archivos .conf pertenecen al paquete y pueden cambiar durante una actualización. Las personalizaciones deben guardarse en archivos .local, que tienen precedencia sobre la configuración distribuida. Orden de carga de archivos.
Abre un archivo local:
sudoedit /etc/fail2ban/jail.d/sshd.localAgrega:
[sshd]
enabled = true
port = ssh
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 198.51.100.10Sustituye 198.51.100.10 por la IP administrativa real. Si administras el servidor mediante IPv6, incluye también esa dirección o su rango autorizado.
Los parámetros controlan:
maxretry: fallos permitidos antes del bloqueo.findtime: ventana dentro de la cual se cuentan los fallos.bantime: duración del bloqueo.ignoreip: direcciones o redes CIDR que nunca deben bloquearse.
port = ssh corresponde normalmente al puerto 22. Si SSH escucha en otro puerto, escribe su número real, por ejemplo port = 2222. Este parámetro determina qué tráfico bloquea la acción; no cambia el puerto del servicio SSH.
No fuerces inicialmente backend ni logpath: los paquetes de Debian y Ubuntu proporcionan valores adaptados a la distribución. Después comprobarás si la jail quedó asociada a un archivo o al journal de systemd.
Paso 3: probar el filtro de SSH
Si los eventos están en /var/log/auth.log:
sudo fail2ban-regex \
/var/log/auth.log \
/etc/fail2ban/filter.d/sshd.confSi SSH registra únicamente en el journal:
sudo fail2ban-regex \
systemd-journal \
/etc/fail2ban/filter.d/sshd.confRevisa los contadores Matched y Missed. La herramienta prueba las expresiones del filtro, pero no agrega reglas al firewall. Su finalidad oficial es comprobar si un filtro reconoce correctamente las líneas de log. Manual de fail2ban-regex.
Paso 4: configurar autenticación HTTP básica en Nginx
Primero confirma que /var/log/nginx/error.log existe y recibe mensajes como password mismatch o user ... was not found. Esos son los patrones que reconoce el filtro oficial. Filtro nginx-http-auth.
Crea el archivo:
sudoedit /etc/fail2ban/jail.d/nginx-http-auth.localAgrega:
[nginx-http-auth]
enabled = true
port = http,https
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 10m
bantime = 1h
ignoreip = 127.0.0.1/8 ::1 198.51.100.10Prueba el filtro antes de activar el cambio:
sudo fail2ban-regex \
/var/log/nginx/error.log \
/etc/fail2ban/filter.d/nginx-http-auth.confLa configuración oficial de la jail utiliza los puertos HTTP/HTTPS y el error log de Nginx. Jails incluidas por Fail2ban.
Si Nginx escribe exclusivamente en systemd-journald, no combines backend = systemd con un logpath de archivo. El backend de systemd consulta el journal mediante journalmatch; comprueba esta variante contra la versión instalada antes de aplicarla.
Paso 5: validar la configuración completa
Ejecuta la prueba de configuración:
sudo fail2ban-client -tNo recargues el servicio si aparece un error. Corrige primero la sección, ruta o parámetro señalado. La opción -t está destinada específicamente a validar la configuración. Manual de fail2ban-client.
También puedes inspeccionar la configuración resultante:
sudo fail2ban-client --dump-prettyPaso 6: aplicar los cambios
Cuando la validación finalice correctamente:
sudo fail2ban-client reloadLa recarga aplica la configuración sin detener por completo el servidor. Reserva el reinicio para cambios que realmente lo requieran:
sudo systemctl restart fail2banPaso 7: comprobar las jails
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo fail2ban-client status nginx-http-auth
sudo journalctl -u fail2ban --since "10 minutes ago" --no-pagerComprueba:
- Que
sshdynginx-http-authaparezcan enJail list. - Que cada jail muestre su fuente de logs o coincidencias del journal.
- Que no existan errores al cargar filtros o acciones.
- Que
Currently failed,Total failedyCurrently bannedevolucionen según los eventos.

Prueba controlada del bloqueo
Para comprobar la acción de firewall sin provocar fallos reales, bloquea temporalmente una IP reservada para documentación:
sudo fail2ban-client set sshd banip 203.0.113.10
sudo fail2ban-client status sshdLuego elimínala:
sudo fail2ban-client set sshd unbanip 203.0.113.10Esta prueba confirma la jail y la acción de ban/unban, pero no sustituye la prueba del filtro con fail2ban-regex.
Para probar la detección completa, usa un entorno aislado y una IP de prueba que no figure en ignoreip. Mantén abierta la sesión administrativa mientras verificas el resultado.
Desbloquear una IP legítima
sudo fail2ban-client set sshd unbanip 203.0.113.10Para saber en qué jails está bloqueada una dirección:
sudo fail2ban-client banned 203.0.113.10No elimines reglas directamente del firewall mientras Fail2ban está activo: el daemon conserva su propio estado y podría recrearlas.
Problemas frecuentes
La jail no aparece
Ejecuta:
sudo fail2ban-client -t
sudo journalctl -u fail2ban -n 100 --no-pagerBusca errores de sintaxis, filtros inexistentes o rutas sin archivos.
Hay fallos en el log, pero no aparecen coincidencias
Comprueba el log real con fail2ban-regex y verifica que la IP no esté incluida en ignoreip. Confirma también que la hora del servidor y la de los registros sean coherentes.
Nginx no detecta un formulario web
nginx-http-auth reconoce autenticación HTTP básica registrada por Nginx. Un formulario gestionado por PHP, WordPress u otra aplicación necesita un filtro específico basado en los logs de esa aplicación.
Se bloquean usuarios legítimos
Desbloquea la IP y aumenta maxretry o reduce la ventana findtime. No uses bloqueos permanentes durante la etapa inicial.
Las IP bloqueadas no aparecen en UFW
UFW puede administrar las reglas base mientras Fail2ban utiliza otra acción dinámica, como nftables o iptables. Verifica los bans con fail2ban-client y revisa la acción efectiva antes de buscar las reglas en una herramienta concreta.
Buenas prácticas para producción
- Usa claves SSH y desactiva contraseñas cuando sea viable.
- Mantén una consola alternativa o segunda sesión durante el despliegue.
- Incluye solo redes administrativas controladas en
ignoreip. - No autorices rangos demasiado amplios.
- Monitorea aumentos repentinos de fallos y bloqueos.
- Revisa periódicamente que los logs y filtros sigan coincidiendo.
- Mantén Fail2ban, OpenSSH y Nginx actualizados.
- Combina Fail2ban con un firewall de política restrictiva, MFA y controles perimetrales cuando corresponda.
Fail2ban funciona mejor como una capa de reducción de abuso y ruido operativo. No corrige credenciales débiles ni vulnerabilidades de la aplicación, pero limita de forma práctica los intentos repetitivos cuando los logs, filtros y acciones están correctamente validados.