Fail2ban 2026: configuración efectiva para proteger tu servidor SSH
Fail2ban: protege tu servidor SSH contra ataques de fuerza bruta
Fail2ban es la herramienta clásica para proteger SSH contra ataques automatizados. Aprende a instalarlo, configurarlo y adaptarlo a tu caso.
—
TL;DR — Lo que vas a tener al final
- Tiempo de setup: 1-2 horas para un server nuevo.
- Requisitos: Acceso root, 2 sesiones SSH abiertas durante cambios.
- Resultado: Login por clave ed25519, fail2ban activo, 99% de ataques bloqueados.
- Troubleshooting: Consola del proveedor, journalctl -u sshd, fail2ban-client status.
¿Por qué Fail2ban?
Si tienes un servidor SSH expuesto a internet, es cuestión de tiempo que recibas intentos de fuerza bruta. Por ejemplo:
# Revisa tu auth.log
sudo tail -n 1000 /var/log/auth.log | grep "Failed password" | head
/var/log/auth.log (en Debian/Ubuntu; en RHEL/Fedora es /var/log/secure) es donde sshd loguea cada intento de autenticación, exitoso o no. El grep "Failed password" filtra los fallidos — si ves muchos (más de 100 por día en un server normal), tienes bots automatizados probando credenciales. En servers con IP pública en zonas densas (cloud AWS, GCP, Hetzner), puedes ver miles de intentos por día — un atacante automatizado prueba listas de usuarios comunes (root, admin, ubuntu, oracle, postgres) con passwords de diccionarios. Si tu server lleva más de una semana online y el log no muestra ninguno, o no está expuesto a internet, o algo está mal configurado y los logs están rotando demasiado rápido para verse.
Vas a ver líneas como:
Failed password for invalid user admin from 185.220.101.45 port 12345 ssh2
Failed password for invalid user root from 185.220.101.45 port 12346 ssh2
Failed password for invalid user oracle from 185.220.101.45 port 12347 ssh2
Estos son bots probando passwords por fuerza bruta. Fail2ban los bloquea automáticamente. La 185.220.101.45 que aparece en el ejemplo es un nodo Tor exit conocido (rango de relays Tor de abuso) — es típico ver el mismo origen probando decenas de usuarios en pocos segundos.
—
Cómo funciona Fail2ban
1. Monitorea logs (auth.log, sshd.log, etc)
2. Detecta patrones (muchos intentos fallidos desde misma IP)
3. Banea la IP usando iptables/nftables
4. Levanta el ban después de un tiempo configurable
—
Instalación
Fail2ban está en los repos oficiales de todas las distros. La instalación incluye el cliente (fail2ban-client), el server (fail2ban-server), y un set de filtros preconfigurados para los servicios más comunes (sshd, apache, nginx, postfix, etc.). El servicio queda deshabilitado por defecto en Debian/Ubuntu después de instalar — hay que activarlo a mano.
# Ubuntu/Debian
sudo apt install fail2ban
# Fedora/RHEL
sudo dnf install fail2ban
# Habilitar y arrancar
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Verificar estado
sudo systemctl status fail2ban
Si systemctl status fail2ban muestra “inactive (dead)” después de start: el proceso murió al arrancar, casi siempre por un error de config. Corré journalctl -u fail2ban -n 50 para ver el traceback. Las causas más comunes: archivo jail.local con sintaxis inválida, paths de logs que no existen (/var/log/auth.log en RHEL donde se llama /var/log/secure), o conflicto con SELinux/AppArmor. Para SELinux en RHEL: sudo ausearch -m avc --start recent te muestra si SELinux está bloqueando el acceso al socket de iptables/nftables.
—
Configuración
Importante: NUNCA edites /etc/fail2ban/jail.conf directamente. Crea /etc/fail2ban/jail.local con tus overrides. La razón: cuando actualizás el paquete fail2ban, jail.conf se sobreescribe con la versión nueva del upstream — tus cambios se pierden. jail.local se preserva en updates (es override explícito).
sudo nano /etc/fail2ban/jail.local
Si ya existe un jail.local con defaults de la distro, editá ese — no lo crees de cero encima (los defaults traen un par de jails útiles como recidive y sshd ya pre-configurados).
Configuración básica recomendada
El bloque [DEFAULT] aplica a todos los jails que no sobrescriban explícitamente. Los valores que importan:
bantime— cuánto tiempo queda baneada una IP.1h(1 hora) es conservador;24ho1wpara servers críticos.findtime— ventana de tiempo en la que se cuentan losmaxretryintentos. Si pasan 10 minutos entre intentos, el contador se resetea.maxretry— número de intentos fallidos antes del ban. 5 es razonable para SSH, 3 más estricto, 10 más permisivo.
[DEFAULT]
# IP que NUNCA se banean (tu IP de casa, etc)
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
# Tiempo de baneo
bantime = 1h
# Ventana de tiempo para contar intentos
findtime = 10m
# Número de intentos antes de banear
maxretry = 5
# Acción: banea via iptables
banaction = iptables-multiport
banaction_allports = iptables-allports
# Email de notificación (opcional)
destemail = [email protected]
sender = [email protected]
mta = sendmail
Advertencia crítica con ignoreip: poné todas las IPs desde las que tú te conectás. Si te baneás a tú mismo (IP dinámica de ISP que cambia entre findtime y el baneo), perdés acceso hasta que el ban expire. Si tu ISP usa CGNAT (muchos ISPs argentinos ahora), estás compartiendo IP con miles de usuarios — un atacante desde esa misma IP te puede dejar afuera sin querer. Solución para CGNAT: usa VPN (WireGuard) para entrar, y dejá solo la IP de la VPN en ignoreip. O usa un bastion host con IP fija al que siempre entrás primero.
Jail específico para SSH
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 24h
findtime = 10m
Empezamos con 3 intentos en 10 min, baneo 24h. Estricto pero razonable.
Jail más agresivo para SSH
[sshd-aggressive]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 2
bantime = 7d
findtime = 5m
Para servidores críticos donde quieres ser muy estricto.
—
Ver jails activos
fail2ban-client status (sin argumentos) lista todos los jails cargados. Con el nombre del jail (status sshd), te muestra detalle: filtros activos, archivos de log que está mirando, IPs baneadas actualmente, y contadores totales desde que arrancó el servicio. Sirve para verificar que un jail está matcheando y baneando como esperas.
sudo fail2ban-client status
# Status
# |- Number of jail: 2
# `- Jail list: sshd, sshd-aggressive
sudo fail2ban-client status sshd
# Status for jail: sshd
# |- Filter
# | |- Currently failed: 3
# | |- Total failed: 47
# | `- File list: /var/log/auth.log
# `- Actions
# |- Currently banned: 1
# |- Total banned: 12
# `- Banned IP list: 185.220.101.45
Si Currently failed sube permanentemente pero Total banned queda en cero, las reglas de match están agarrando intentos fallidos pero la acción de ban no se está ejecutando. Eso pasa cuando: 1) banaction está mal seteado (apunta a una action que no existe), 2) el baneo iptables falla por permisos (Fail2ban necesita ejecutar iptables como root), 3) el jail tiene enabled = false por error.
Comandos útiles:
# Ver IPs baneadas
sudo fail2ban-client get sshd banip
# Banear una IP manualmente
sudo fail2ban-client set sshd banip 1.2.3.4
# Desbanear una IP
sudo fail2ban-client set sshd unbanip 1.2.3.4
# Recargar config
sudo fail2ban-client reload
reload es la forma correcta de aplicar cambios en jail.local sin reiniciar el servicio (los bans existentes se preservan). Si después del reload los jails nuevos no aparecen, hay que hacer reload de nuevo — algunas versiones solo recargan la config pero no activan jails nuevos. El set ... banip te sirve para banear manualmente una IP que detectaste haciendo abuso pero que todavía no llegó al threshold del jail. El unbanip es clave si te baneaste a tú mismo: lo corres desde la consola (IPMI, KVM) o desde otro host que esté en ignoreip.
—
Filters personalizados
Fail2ban viene con filters preconfigurados para SSH. Si quieres uno custom:
/etc/fail2ban/filter.d/custom-ssh.conf:
[Definition]
failregex = ^.*Failed password for .* from .*$
^.*Invalid user .* from .*$
^.*Connection closed by authenticating user .* .*$
ignoreregex =
—
Notificaciones por email
Para que Fail2ban te avise cuando banee algo, tienes que tener un MTA (mail transfer agent) configurado. sendmail es el más simple de configurar (compatible con mail command), pero postfix es más robusto y la mayoría de los servers lo tienen instalado de serie. Si no quieres configurar un MTA local, puedes usar ssmtp que reenvía a un SMTP externo (Gmail, Mailgun, etc.) — pero requiere guardar credenciales.
sudo apt install sendmail # o postfix
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
destemail = [email protected]
sender = fail2ban@$(hostname)
mta = sendmail
action = %(action_mwl)s
action_mwl = m (mail) + w (who) + l (log). Te envía email con detalles. Antes de activar esto en producción: mandá un test con sudo fail2ban-client set sshd banip 1.2.3.4 y revisa que el mail llegue a tu inbox. Si tu MTA no está configurado (DNS reverso, SPF, DKIM), el mail va a spam o rebota. Para servers en producción seria, mandá las notificaciones a un canal asíncrono (Slack, Telegram) — el email es lento y poco confiable bajo carga.
Si los emails no llegan: 1) revisa /var/log/mail.log (Postfix) o /var/log/mail.log (Sendmail) para ver si el MTA aceptó el mensaje, 2) prueba mandar un mail manual con echo "test" | mail -s "test" [email protected], 3) si el mail sale pero no llega, el destino lo está marcando como spam (configurar SPF/DKIM en tu dominio o usar una dirección de envío verificable).
—
Baneo permanente para reincidentes
Crea un jail custom para IPs reincidentes:
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
bantime = 1y
findtime = 1d
maxretry = 5
action = iptables-allports[name=recidive]
Esto banea por 1 año a IPs que han sido baneadas 5 veces en 1 día.
—
Whitelist de IPs confiables
[DEFAULT]
# Nunca banear estas IPs
ignoreip = 127.0.0.1/8 ::1
192.168.1.0/24
10.0.0.0/8
203.0.113.42 # tu IP de oficina
—
Notificar Slack
Si quieres alertas en Slack:
sudo nano /etc/fail2ban/action.d/slack.conf
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = curl -X POST -H 'Content-type: application/json'
--data '{"text":"Fail2ban: IP baneada en "}'
https://hooks.slack.com/services/TU_WEBHOOK_URL
actionunban =
jail.local:
[DEFAULT]
action = iptables-multiport[name=ssh] slack
—
Protecciones adicionales
Fail2ban protege SSH pero también puedes proteger otros servicios:
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
[postfix]
enabled = true
port = smtp,465,587
filter = postfix
logpath = /var/log/mail.log
maxretry = 5
[dovecot]
enabled = true
port = imap,imaps,pop3,pop3s
filter = dovecot
logpath = /var/log/mail.log
maxretry = 5
—
Monitorear con logs
Tres comandos que cubren el 90% del debugging:
# Ver bans recientes
sudo journalctl -u fail2ban --since "1 hour ago" | grep "Ban"
# Estadísticas
sudo fail2ban-client status
sudo fail2ban-client status sshd
# Top IPs con más intentos fallidos
sudo grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -rn | head
journalctl -u fail2ban --since "1 hour ago" te muestra todo lo que fail2ban logueó en la última hora — bans, unbans, errores de regex, problemas de iptables. Filtrá con grep "Ban" para ver solo los bans. Si hay bans de una IP que está en ignoreip, tienes un typo en la config.
El comando de awk '{print $11}' extrae la columna 11 de cada línea de log de auth.log — que es la IP que intenta autenticarse (después de “from”). El pipe a sort | uniq -c agrupa y cuenta, después sort -rn los ordena por cantidad descendente, head muestra el top 10. Advertencia: el número de columna puede variar según la versión de sshd y el idioma del sistema (auth.log en español tiene “Contraseña” en vez de “password”). Si no funciona, ajustá el $11 al número correcto. Alternativa más robusta: grep -oE 'from [0-9.]+' /var/log/auth.log | sort | uniq -c | sort -rn.
—
Fail2ban + Docker
Si corres apps en Docker, Fail2ban puede banear IPs que hacen requests abusivos:
[nginx-docker]
enabled = true
port = http,https
filter = nginx-docker
logpath = /var/log/nginx/access.log
maxretry = 100
findtime = 5m
bantime = 1h
Esto protege tu Nginx que corre en Docker contra scrapers, bots maliciosos, etc.
—
Resumen
Fail2ban es una capa de seguridad esencial para cualquier servidor SSH expuesto a internet. Setup típico:
1. Instalar (1 min)
2. Configurar /etc/fail2ban/jail.local (5 min)
3. Activar jail sshd con maxretry=3, bantime=24h
4. Monitorear con fail2ban-client status
Tiempo de protección: inmediato. Costo: cero.
Lee también: Hardening de SSH para asegurar SSH antes de aplicar Fail2ban, o nftables firewall para protección a nivel de red.
Preguntas frecuentes
¿Por qué Fail2ban 2026: configuración efectiva para proteger tu servidor SSH es relevante para sysadmins Linux?
Forma parte del flujo diario de administración. Los conceptos explicados se aplican directamente a servidores en producción y resuelven problemas reales que enfrentan sysadmins hispanohablantes.
¿Qué necesito para empezar con Fail2ban 2026: configuración efectiva para?
Distribución Linux actualizada (Debian, Ubuntu, RHEL, Fedora o Arch), acceso root, y conexión a internet. Para producción: entorno de staging separado antes de aplicar cambios.
¿Cuáles son los errores más comunes con Fail2ban 2026: configuración efectiva para?
Los tres más frecuentes: (1) saltar la lectura de logs, (2) aplicar cambios directos en producción sin probar, (3) olvidar permisos y ownership. La documentación y un plan de rollback siempre.
¿Cuándo usar Fail2ban 2026: configuración efectiva para y cuándo una alternativa?
Esta solución es ideal para el caso descrito. Alternativas como Docker, Ansible o configuración manual pueden ser mejores según contexto: portabilidad, escala y reproducibilidad son los factores clave.
¿Cómo migro desde una configuración previa a Fail2ban 2026: configuración efectiva para?
Documentar el estado actual, probar la nueva configuración en staging, validar funcionalmente, y aplicar en producción con rollback plan listo. Los posts de SoyLinux incluyen troubleshooting para los problemas más comunes.
Lee también
- Guía Fedora 44: Novedades, Instalación y Upgrade para Sysadmins Linux
- Configura VLANs en Linux con nmcli: Guía paso a paso para sysadmins
- Protege tu SSH: Guía esencial para configurar Fail2ban en Linux
- Guía Definitiva: Configura Kubernetes con kubeadm en Ubuntu para Sysadmins Linux
- Configura Prometheus y Grafana: Guía DevOps para SysAdmins Linux
