No notas la fuerza bruta sobre la autenticación de correo cuando es pequeña. La notas cuando el registro de IMAP se convierte en un dispositivo de denegación de servicio, los ventiladores de la CPU parecen un dron y los usuarios juran que “no cambió nada” mientras Outlook intenta la misma contraseña una y otra vez.
Fail2ban puede ayudar. También puede causar daño—en silencio—bloqueando a tu CEO en medio de una llamada de junta porque la app de correo del teléfono guardó una contraseña errónea durante ocho horas. La diferencia no es “instalar fail2ban”. La diferencia son las reglas, el enrutamiento de logs y un despliegue que respete la realidad de producción.
Contra qué te estás defendiendo realmente
Los servidores de correo atraen atacantes por razones aburridas: las credenciales tienen valor, SMTP es ubicuo y la reutilización de contraseñas es una fuente inagotable. Los “ataques” de mayor volumen que verás normalmente no son sofisticados. Son ruidosos, repetitivos y rentables porque los operadores apuestan a encontrar una cuenta débil entre mil.
Patrones comunes de ataque al correo que vale la pena banear
- Fuerza bruta de autenticación IMAP/POP (Dovecot, Courier): fallos repetidos de inicio de sesión contra nombres de usuario reales.
- Fuerza bruta SMTP AUTH (Postfix SASL, Exim): fallos repetidos de SASL, a menudo desde botnets.
- Fuerza bruta en paneles web/UI (Roundcube, Rspamd WebUI, mailcow admin, paneles personalizados): adivinación de contraseñas y sondas de sesión.
- Abuso del protocolo SMTP: HELO inválidos, abuso de pipelining, ataques de diccionario “RCPT TO”. A veces es rastreo de spam; a veces es preludio de abuso.
- Credential stuffing: no muchos intentos por IP. Aquí fracasan las configuraciones ingenuas de fail2ban, porque cada IP se mantiene por debajo de tu umbral.
Para qué sirve fail2ban (y para qué no)
Fail2ban destaca en el limitado por tasa por IP basado en logs. Si un atacante usa una IP para martillar autenticaciones, puedes cortarlo rápidamente. Si reparte intentos entre miles de IPs, fail2ban pierde eficacia; entonces necesitas controles aguas arriba (greylisting, reputación, límites de tasa, CAPTCHA en UIs web, MFA o filtrado a nivel de proveedor).
Además: fail2ban no reemplaza una seguridad de correo correcta. Aún necesitas políticas de contraseñas robustas, MFA donde sea posible, deshabilitar autenticación en texto claro cuando puedas y una exposición sensata (no publiques paneles de administración a Internet si puedes evitarlo).
Datos interesantes & historia (los ataques al correo no son nuevos)
- SMTP precede a la autenticación moderna. SMTP se diseñó a principios de los años 80 para redes cooperativas; añadir auth y TLS llegó mucho después.
- Los “relays abiertos” fueron normales. En los 90 muchos MTAs reenviaban correo libremente; el spam convirtió eso en un problema y llevó a restringir los relays.
- El greylisting se popularizó en los 2000. Explotó que los MTAs legítimos reintentaban la entrega; muchos bots de spam no lo hacían.
- SASL es más antiguo de lo que muchos piensan. El Simple Authentication and Security Layer data de finales de los 90 y fue diseñado para estandarizar la autenticación entre protocolos.
- fail2ban surgió a mediados de los 2000. Surgió con la ola de “automatización basada en logs” en Linux—simple, eficaz y peligrosamente fácil de configurar mal.
- Las botnets pasaron de origen único a ataques distribuidos. El credential stuffing actual suele usar muchas IPs con intentos pocos por IP, reduciendo el valor de los bans ingenuos por IP.
- Journald cambió el juego para el parseo de logs. Cuando los sistemas pasaron de ficheros planos a logs estructurados, las herramientas que asumían /var/log/* tuvieron que adaptarse.
- IPv6 volvió obsoleto “banear el /24”. Los atacantes pueden rotar direcciones en rangos masivos, y banear IPv6 descuidadamente puede eliminar redes legítimas.
- El correo sigue siendo una vía principal de brechas. No porque SMTP sea mágico, sino porque las credenciales permiten restablecer contraseñas, acceder a facturas y aprovechar la confianza interna.
Asegura los logs primero (o fail2ban es un placebo)
Fail2ban solo puede actuar sobre lo que ve. La mayoría de tickets “fail2ban no funciona” se reducen a uno de tres problemas:
- El servicio no registra fallos de autenticación en un formato que se pueda parsear.
- Los logs van a un sitio que fail2ban no vigila (journald vs ficheros, contenedores, chroot, syslog dividido).
- La regex no coincide con las líneas reales (porque el formato de logs de tu distro difiere del modelo mental del autor).
Decide tu backend: ficheros o systemd/journald
En distribuciones modernas, a menudo quieres el backend systemd para no perseguir ficheros rotados y permisos. Pero si tus MTAs escriben en ficheros syslog clásicos, el tail de ficheros funciona. Elige uno por host y mantenlo consistente; las configuraciones híbridas son donde el troubleshooting muere.
Además: considera que los sistemas de correo con frecuencia están divididos en contenedores o VMs separadas. Si Postfix corre en un contenedor y Dovecot en otro, fail2ban en un tercer contenedor no verá los logs a menos que los reenvíes. Tu mensaje “jail enabled” no significa nada si está mirando a una habitación vacía.
Broma #1: Lo único más confiable que un bot de fuerza bruta es un ejecutivo que “no cambió nada” justo antes del fallo.
Jails para correo que atrapan ataques reales
Abajo hay jails que suelen funcionar en pilas Postfix + Dovecot del mundo real, además de un par de objetivos web relacionados con correo. La meta no es “banear todo”. La meta es: banear abuso de alta confianza rápidamente, y tratar señales ambiguas con cautela.
Suposiciones base
- Ejecutas fail2ban 0.11+ (más nuevo es mejor, especialmente por mejoras en el backend systemd).
- Tus acciones de firewall son consistentes: nftables en Debian/Ubuntu modernos, firewalld en sistemas tipo RHEL, iptables en setups más antiguos.
- Tus servicios de correo registran la IP del cliente en la misma línea que el fallo (o en una línea correlacionada que el filtro soporte).
Fallos de autenticación SASL de Postfix (fuerza bruta SMTP AUTH)
Este jail banea tras fallos repetidos de autenticación SASL, que son de alta señal. Atrapa el clásico “probar 10 contraseñas para user@domain” rápidamente.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/postfix-sasl.local
[postfix-sasl]
enabled = true
backend = systemd
filter = postfix[mode=auth]
maxretry = 6
findtime = 10m
bantime = 4h
bantime.increment = true
bantime.factor = 2
bantime.multipliers = 1 2 4 8 16 32
action = nftables-multiport[name=postfix-sasl, port="smtp,submission,submissions"]
journalmatch = _SYSTEMD_UNIT=postfix.service
Por qué funciona: Está ligado a fallos de auth, no a rarezas del protocolo. Usa bantime incremental para que reincidentes reciban bans más largos sin castigar permanentemente a alguien que tecleó mal la contraseña una vez.
Fallos de autenticación de Dovecot (fuerza bruta IMAP/POP)
Los logs de Dovecot suelen ser directos e incluyen la IP remota. Esto hace un buen jail—otra vez, eventos de alta señal.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/dovecot.local
[dovecot]
enabled = true
backend = systemd
filter = dovecot
maxretry = 5
findtime = 10m
bantime = 6h
bantime.increment = true
bantime.factor = 2
bantime.multipliers = 1 2 4 8 16
action = nftables-multiport[name=dovecot, port="imap,imaps,pop3,pop3s"]
journalmatch = _SYSTEMD_UNIT=dovecot.service
Opinión: Si expones IMAP/POP a Internet público, quieres este jail. “Solo tenemos unos pocos usuarios” no es una estrategia; es una forma de programar tu próximo incidente.
Roundcube (fuerza bruta en inicio de sesión webmail)
Los logs de Roundcube varían según la configuración, y mucha gente olvida habilitar registros útiles. Fail2ban puede ayudar si tienes líneas consistentes de fallos de login en syslog o en los logs de Roundcube.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/roundcube.local
[roundcube]
enabled = true
backend = auto
filter = roundcube-auth
logpath = /var/log/roundcube/errors.log
maxretry = 5
findtime = 15m
bantime = 12h
action = nftables-multiport[name=roundcube, port="http,https"]
Detalle clave: La fuerza bruta en webmail suele venir de un pequeño conjunto de IPs, pero el credential stuffing puede no hacerlo. Este jail ayuda con el primer caso.
Rspamd WebUI (fuerza bruta en panel de administración)
Si expones la WebUI de Rspamd a Internet, te estás buscando problemas. Si debes hacerlo, al menos protégelo.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/rspamd.local
[rspamd]
enabled = true
backend = systemd
filter = rspamd
maxretry = 4
findtime = 10m
bantime = 24h
action = nftables-multiport[name=rspamd, port="http,https"]
journalmatch = _SYSTEMD_UNIT=rspamd.service
Recidive: atrapa a los reincidentes a través de todos los jails
Recidive vigila el propio log de fail2ban. Si una IP es baneada repetidamente a lo largo del tiempo, merece un ban más largo. Esta es una de las pocas funciones “configurar y olvidar” que realmente paga dividendos.
cr0x@server:~$ sudo sed -n '1,200p' /etc/fail2ban/jail.d/recidive.local
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
backend = auto
bantime = 7d
findtime = 1d
maxretry = 3
action = nftables-allports[name=recidive]
Cuando no banear: ruido de “rejected” en SMTP
Te sentirás tentado a banear por líneas “NOQUEUE: reject” de Postfix. No empieces por ahí. Muchos rejects son malas configuraciones legítimas de remitentes reales, y banearlos puede crear fallos de entregabilidad difíciles de explicar.
Si implementas un jail para abuso de protocolo, mantenlo conservador y monitoréalo como un halcón. Trátalo como “reducir spam de logs”, no como “seguridad”.
Banco de pruebas de regex: prueba el match antes de banear
Tus filtros valen lo que vale tu regex. El método práctico es:
- Recopila líneas de logs representativas (buenas, malas y raras).
- Usa
fail2ban-regexcontra logs reales. - Ajusta hasta que las coincidencias sean correctas y los falsos positivos sean aburridamente raros.
- Solo entonces habilita el jail.
Una cita que la gente de operaciones aprende a machetazos:
“La esperanza no es una estrategia.” — idea parafraseada a menudo en círculos de operaciones
Broma #2: La regex es como una motosierra: poderosa, ruidosa y tarde o temprano te harás daño si la usas sin supervisión.
Tareas prácticas: comandos, salidas, decisiones (12+)
Tarea 1: Confirma que fail2ban está ejecutándose y no está flapping
cr0x@server:~$ systemctl status fail2ban --no-pager
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-01-04 08:11:22 UTC; 2h 14min ago
Docs: man:fail2ban(1)
Main PID: 1047 (fail2ban-server)
Tasks: 5 (limit: 18963)
Memory: 64.3M
CPU: 2min 18.541s
Qué significa: “active (running)” con tiempo de actividad estable sugiere que no se está cayendo ni reiniciando constantemente.
Decisión: Si está reiniciando o inactivo, arregla eso primero. Ninguna afinación de regex ayuda si el demonio está muerto.
Tarea 2: Lista los jails habilitados (chequeo de realidad)
cr0x@server:~$ sudo fail2ban-client status
Status
|- Number of jail: 4
`- Jail list: dovecot, postfix-sasl, recidive, rspamd
Qué significa: Estos son los únicos jails que están haciendo algo.
Decisión: Si tu jail previsto no aparece, no está habilitado o falló al cargar. Ve a leer journalctl -u fail2ban.
Tarea 3: Comprueba los contadores de un jail
cr0x@server:~$ sudo fail2ban-client status postfix-sasl
Status for the jail: postfix-sasl
|- Filter
| |- Currently failed: 12
| |- Total failed: 981
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 7
|- Total banned: 103
`- Banned IP list: 198.51.100.23 203.0.113.14 203.0.113.77
Qué significa: “Currently failed” es el número de fallos en la ventana; “Currently banned” son los bans activos.
Decisión: Si “Total failed” sube pero los bans son cero, tu maxretry puede ser muy alto, findtime muy corto, o el filtro hace match pero la acción no funciona.
Tarea 4: Verifica la integración con el firewall (ejemplo nftables)
cr0x@server:~$ sudo nft list ruleset | sed -n '1,120p'
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
tcp dport { 22, 25, 465, 587, 993 } accept
}
}
table inet f2b-table {
set f2b-postfix-sasl {
type ipv4_addr
flags timeout
}
chain f2b-postfix-sasl {
ip saddr @f2b-postfix-sasl drop
}
}
Qué significa: Hay una tabla/conjunto de fail2ban para el jail. Si falta, la acción no aplicó reglas.
Decisión: Si fail2ban dice que baneó IPs pero nftables no tiene sets/cadenas, estás usando la acción equivocada o faltan permisos/capacidades.
Tarea 5: Confirma que Postfix registre fallos SASL donde fail2ban pueda verlos
cr0x@server:~$ sudo journalctl -u postfix.service -S "30 min ago" | grep -E "SASL|authentication failed" | tail -n 5
Jan 04 10:12:43 mail postfix/smtpd[22901]: warning: unknown[203.0.113.77]: SASL LOGIN authentication failed: authentication failure
Jan 04 10:12:45 mail postfix/smtpd[22901]: warning: unknown[203.0.113.77]: SASL LOGIN authentication failed: authentication failure
Qué significa: Tienes las líneas esperadas, con IPs visibles.
Decisión: Si no ves estas líneas, tu auth SASL puede estar en otra unidad/facilidad de log, o los fallos de auth están suprimidos. Arregla el logging antes de los filtros.
Tarea 6: Confirma el formato de fallo de auth de Dovecot
cr0x@server:~$ sudo journalctl -u dovecot.service -S "30 min ago" | grep -i "auth failed" | tail -n 3
Jan 04 10:06:12 mail dovecot: auth: passwd-file(jdoe,203.0.113.14): Password mismatch
Jan 04 10:06:15 mail dovecot: imap-login: Aborted login (auth failed, 1 attempts): user=<jdoe>, method=PLAIN, rip=203.0.113.14, lip=192.0.2.10, TLS
Qué significa: Incluye rip= (IP remota), que es lo que muchos filtros por defecto usan como clave.
Decisión: Si tus líneas no contienen IP, necesitarás un filtro distinto o ajustar la configuración de logging de Dovecot.
Tarea 7: Prueba un filtro contra logs reales antes de habilitarlo
cr0x@server:~$ sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/postfix.conf --print-all-matched
Running tests
=============
Use failregex file : /etc/fail2ban/filter.d/postfix.conf
Use log file : /var/log/auth.log
Results
=======
Failregex: 18 total
|- #) [# of hits] regular expression
| 1) [18] warning: .*?\[<HOST>\]: SASL .* authentication failed
`-
Lines: 12458 lines, 0 ignored, 18 matched, 12440 missed
Qué significa: La regex coincide exactamente con las líneas esperadas. “Missed” está bien; es todo lo demás.
Decisión: Si las coincidencias son cero, arregla la regex o el logpath. Si las coincidencias son enormes, puede que estés coincidiendo con líneas benignas y necesites afinar.
Tarea 8: Simula tus parámetros de ban con fail2ban-client get
cr0x@server:~$ sudo fail2ban-client get postfix-sasl maxretry
6
cr0x@server:~$ sudo fail2ban-client get postfix-sasl findtime
600
cr0x@server:~$ sudo fail2ban-client get postfix-sasl bantime
14400
Qué significa: Los valores están en segundos para algunas consultas. 600 segundos = 10 minutos; 14400 = 4 horas.
Decisión: Si tu entorno tiene clientes móviles inestables o oficinas con NAT, considera un maxretry ligeramente mayor o un bantime más corto al principio, y luego aumenta una vez que los falsos positivos estén controlados.
Tarea 9: Inspecciona los logs de fail2ban por errores de acción (el asesino silencioso)
cr0x@server:~$ sudo tail -n 50 /var/log/fail2ban.log
2026-01-04 10:12:49,381 fail2ban.actions [1047]: NOTICE [postfix-sasl] Ban 203.0.113.77
2026-01-04 10:12:49,512 fail2ban.actions [1047]: ERROR Failed to execute ban jail 'postfix-sasl' action 'nftables-multiport': returned 127
2026-01-04 10:12:49,513 fail2ban.actions [1047]: ERROR Invariant check failed. Trying again...
Qué significa: “Baneó” en la mente de fail2ban, pero la acción falló al ejecutarse (exit 127 a menudo significa binario faltante o comando incorrecto).
Decisión: Arregla la herramienta de acción (ruta del comando nft, permisos, definición de la acción) antes de confiar en cualquier contador de bans.
Tarea 10: Comprueba si estás baneando un NAT (oficina) y perjudicando a muchos usuarios
cr0x@server:~$ sudo fail2ban-client status dovecot
Status for the jail: dovecot
|- Filter
| |- Currently failed: 2
| |- Total failed: 204
| `- File list: /var/log/mail.log
`- Actions
|- Currently banned: 1
|- Total banned: 9
`- Banned IP list: 198.51.100.10
Qué significa: Una IP está actualmente baneada. Si esa IP es un NAT corporativo, acabas de bloquear a todos los que están detrás.
Decisión: Si esto ocurre, añade una lista de ignorados dirigida para IPs de egress de oficina conocidas, pero solo después de verificar que no estás whitelisteando a un atacante detrás de una “VPN de oficina”.
Tarea 11: Añadir una IP en ignore de forma segura (y mantenerla auditable)
cr0x@server:~$ sudo sed -n '1,120p' /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.0.2.0/24 198.51.100.10
Qué significa: Estas fuentes nunca serán baneadas por ningún jail.
Decisión: Mantén las listas de ignore pequeñas. Prefiere whitelistear solo IPs de egress fijas que controles y monitorees. No metas rangos enteros de ISP aquí porque un VIP se quejó.
Tarea 12: Desbanear una IP (y luego averiguar por qué fue baneada)
cr0x@server:~$ sudo fail2ban-client set dovecot unbanip 198.51.100.10
1
Qué significa: “1” indica éxito (un ban removido).
Decisión: Desbanea y luego investiga de inmediato: ¿fue error de usuario, credential stuffing o un cliente con mal comportamiento? Si no respondes eso, volverás mañana.
Tarea 13: Confirma que tu jail vigila la fuente correcta (backend systemd)
cr0x@server:~$ sudo fail2ban-client get postfix-sasl backend
systemd
cr0x@server:~$ sudo fail2ban-client get postfix-sasl journalmatch
_SYSTEMD_UNIT=postfix.service
Qué significa: El jail lee logs de journald filtrados por la unidad Postfix.
Decisión: Si journalmatch está vacío y tu sistema es ruidoso, puedes parsear líneas no relacionadas y generar bans sin sentido. Añade la coincidencia.
Tarea 14: Mide la tasa de ataque para ajustar umbrales
cr0x@server:~$ sudo journalctl -u postfix.service -S "1 hour ago" | grep -c "SASL LOGIN authentication failed"
482
Qué significa: 482 fallos por hora no es “radiación de fondo”. Eso es abuso activo o un colapso de cliente.
Decisión: Si la tasa es alta, mantiene findtime razonablemente corto (5–15 minutos) para que los bans se disparen rápido. Si la tasa es baja y temes falsos positivos, alarga findtime y sube maxretry.
Guion de diagnóstico rápido
Cuando “el correo va lento” o “la gente no puede iniciar sesión” y sospechas de fail2ban, quieres rapidez. No perfección. Aquí está el camino más corto hacia la verdad.
Primero: ¿está fail2ban bloqueando realmente tráfico?
- Revisa los bans activos en el jail relevante (
fail2ban-client status <jail>). - Verifica que las reglas/sets del firewall existan y contengan la IP baneada (salida de nftables/iptables).
- Si usas un reverse proxy o balanceador, confirma que la IP origen en los logs es el cliente real, no el proxy.
Segundo: ¿el jail está coincidiendo con las líneas de log correctas?
- Toma una línea reciente de fallo de journald/syslog.
- Ejecuta
fail2ban-regexcontra ella (o un pequeño fragmento) usando el filtro exacto del jail. - Valida que el host extraído es correcto (especialmente con IPv6, direcciones entre corchetes o envoltorios de hostname “unknown”).
Tercero: ¿es un problema de cliente que se hace pasar por ataque?
- Busca un usuario que genere fallos repetidos desde una sola IP NAT.
- Comprueba si la contraseña cambió recientemente (registros de helpdesk, sincronización de directorio, revocación de token OAuth).
- Si es correo móvil, asume credenciales obsoletas y lógica de reintento agresiva hasta que se demuestre lo contrario.
Cuarto: ¿es el “ataque” distribuido?
- Cuenta IPs únicas que producen fallos de auth en la última hora.
- Si el número es enorme y cada IP tiene bajo volumen, fail2ban solo mordisqueará los bordes.
- Mueve el esfuerzo a límites de tasa, filtrado aguas arriba, autenticación más fuerte o deshabilitar temporalmente endpoints de auth expuestos que no necesitas.
Errores comunes: síntoma → causa raíz → arreglo
1) “fail2ban dice baneado, pero el atacante sigue insistiendo”
Síntoma: El jail muestra bans; los logs siguen mostrando fallos de auth desde la misma IP.
Causa raíz: Acción mal configurada (acción de backend equivocada, nft/iptables faltante, firewalld no en ejecución), o los bans se aplican a IPv4 mientras el tráfico es IPv6.
Arreglo: Verifica la presencia de la regla del firewall y que la cadena esté ligada al INPUT. Asegura que tu acción soporte inet/IPv6 donde sea necesario; usa la tabla inet de nftables o acciones dual-stack.
2) “Usuarios detrás de un NAT de oficina no pueden revisar correo”
Síntoma: Varios usuarios reportan timeouts IMAP/SMTP; una IP está baneada.
Causa raíz: Un cliente mal configurado detrás del NAT dispara bans para todos.
Arreglo: Aumenta maxretry ligeramente para Dovecot/Postfix auth, habilita bans incrementales y añade un ignoreip de alcance limitado solo si puedes monitorizar y confiar en ese egress.
3) “Nunca ocurren bans, pero los logs muestran fallos”
Síntoma: Total failed se mantiene en cero; los logs de fail2ban están silenciosos.
Causa raíz: Backend/logpath incorrecto. Ejemplo: el jail vigila /var/log/auth.log, pero tu sistema solo loguea en journald.
Arreglo: Cambia a backend = systemd con journalmatch, o asegura que rsyslog escriba el fichero esperado.
4) “Los bans explotan tras una actualización”
Síntoma: Miles de bans, incluidos clientes legítimos.
Causa raíz: El formato de logs cambió (actualización de paquete, nueva verbosidad), y la regex ahora coincide con más de lo debido.
Arreglo: Ejecuta fail2ban-regex sobre una muestra de logs nuevos; ajusta expresiones; añade ignoreregex para líneas benignas conocidas.
5) “Baneamos el balanceador de carga”
Síntoma: Todo se rompe de golpe; los logs muestran la misma IP interna fallando auth repetidamente.
Causa raíz: X-Forwarded-For no se pasó, o el proxy de correo oculta la IP del cliente, así que todos los fallos parecen provenir del proxy.
Arreglo: Arregla el logging para incluir la IP real del cliente, o ejecuta fail2ban en el borde donde puedas ver a los clientes. No adivines.
6) “recidive está baneando redes buenas por una semana”
Síntoma: Bans largos tras ráfagas cortas de fallos.
Causa raíz: Afinaste los jails primarios demasiado agresivamente, causando falsos bans; recidive los amplificó.
Arreglo: Suaviza los jails primarios (sube maxretry, acorta bantime), luego vuelve a habilitar recidive cuando los falsos positivos sean raros.
7) “La entrega desde redes móviles es inestable”
Síntoma: Imposibilidad aleatoria de conectar desde LTE, pero Wi‑Fi funciona.
Causa raíz: Bans demasiado amplios por rejects SMTP o anomalías de protocolo; los carriers móviles comparten espacio de IP y hacen NAT agresivo.
Arreglo: Evita banear por rejects genéricos de SMTP. Banea por fallos de auth y abuso explícito, no por “cliente dijo HELO raro”.
Tres mini-historias corporativas (cómo falla esto en empresas reales)
Mini-historia 1: El incidente causado por una suposición equivocada
Una empresa mediana migró correo desde una VM legada a una nueva versión de distro. Copiaron la configuración antigua de fail2ban tal cual: mismos jails, mismas rutas de logs, mismos filtros. Incluso celebraron: “Es idéntico, así que es seguro”.
Lo que cambió fue aburrido: el logging se movió a journald y rsyslog dejó de escribir /var/log/auth.log por defecto. Fail2ban hizo tail de un fichero que existía, pero estaba básicamente vacío. Mientras tanto, los fallos SASL de Postfix se acumularon en journald, invisibles.
La primera señal no fue “nos atacan”. La primera señal fue CPU: los workers de auth de Dovecot estaban ocupados rechazando logins todo el día. La segunda señal fue una toma de cuenta: una contraseña reutilizada, un buzón comprometido y luego un pico de spam saliente que dañó su reputación IP.
La solución no fue heroica. Cambiaron a backend = systemd, añadieron journalmatch por servicio, probaron con fail2ban-regex y de pronto los bans comenzaron a ocurrir por las razones correctas. La lección no fue “usa journald”. Fue “nunca asumas que tus logs están donde solían estar”.
Mini-historia 2: La optimización que salió mal
Otra organización tuvo una idea ingeniosa: reducir el volumen de logs. Sus logs de correo eran masivos, el almacenamiento “demasiado caro” y alguien decidió bajar la verbosidad en fallos de auth. Menos disco, menos alertas, todos contentos.
Dos semanas después, notaron un patrón nuevo: usuarios bloqueados intermitentemente. Su servicio de directorio mostraba intentos raros de login, pero los hosts de correo tenían detalle insuficiente para atribuir fuentes confiablemente. Los bans de fail2ban se volvieron caóticos porque los logs restantes no incluían consistentemente la IP remota en las líneas de fallo.
“Optimizaban” más bajando maxretry y aumentando bantime para compensar. Así terminaron baneando NATs de hoteles y redes de conferencias por un día entero. Los tickets de soporte aumentaron. Ejecutivos se involucraron. Ya sabes el resto.
Revirtieron el logging para incluir contexto de auth, mantuvieron logrotate sensato y llevaron la discusión de costes donde debía estar: el almacenamiento es más barato que los incidentes. Luego ajustaron fail2ban basándose en tasas de fallo medidas, no en sensaciones.
Mini-historia 3: La práctica aburrida pero correcta que salvó el día
Una compañía regulada ejecutaba correo en un entorno segmentado: SMTP frontal separado, IMAP separado y una red de gestión. Su config de fail2ban era poco glamorosa. Cada jail se probó con fail2ban-regex durante las revisiones de cambio. Cada entrada de whitelist tenía referencia de ticket. Cada acción usaba un único backend de firewall (nftables) en todos los hosts.
Un viernes por la noche, una campaña de credential stuffing golpeó su endpoint IMAP. Fue distribuida y lenta por IP. Fail2ban no detuvo todos los intentos, porque no puede banear lo que nunca supera los umbrales. Pero sí detuvo el subconjunto ruidoso rápido, lo que mantuvo el servicio responsivo y los logs legibles.
La verdadera victoria vino de sus dashboards “aburridos”: monitorizaron tasas de fallo de auth y conteo de IPs únicas. En una hora reconocieron la firma del stuffing. Temporalmente ajustaron límites en el borde, forzaron restablecimientos de contraseña para un pequeño conjunto de cuentas objetivo y aplicaron MFA adicional en webmail.
El lunes por la mañana fue tranquilo. Sin noche en vela. El informe del incidente fue casi molesto por su simplicidad: reglas probadas, logging consistente y métricas. El éxito en operaciones a menudo parece que nadie notó que hiciste algo.
Listas de comprobación / plan paso a paso
Paso 1: Establece visibilidad (antes de banear)
- Elige tu fuente de logs: journald o ficheros. No mezcles a la ligera.
- Confirma que puedes ver líneas de fallo de Postfix y Dovecot con IPs.
- Habilita logging de fail2ban a un fichero conocido (
/var/log/fail2ban.loges típico).
Paso 2: Empieza con jails de alta señal
- Habilita el jail de Postfix SASL auth.
- Habilita el jail de Dovecot auth.
- Opcionalmente habilita jails de UI web (Roundcube, Rspamd) solo si están expuestos.
Paso 3: Ajusta umbrales con datos medidos
- Mide fallos de auth por hora y conteo de IPs únicas.
- Configura
maxretrypara atrapar bots, no errores tipográficos (empieza en 5–6). - Usa
findtimede 10–15 minutos para capturar ráfagas. - Usa bantime incremental para castigar abuso reiterado sin disparar fusibles permanentes.
Paso 4: Despliega con seguridad
- Habilita un jail a la vez.
- Observa los bans durante 24 horas.
- Audita las primeras docenas de IPs baneadas: confirma que son abuso real.
- Sólo entonces habilita recidive.
Paso 5: Hazlo soportable para on-call
- Documenta cómo desbanear y dónde revisar logs.
- Mantén las listas de ignore mínimas y revisadas.
- Asegura que el backend del firewall sea consistente entre hosts (nftables o firewalld; elige uno).
Preguntas frecuentes
1) ¿Debo ejecutar fail2ban en el servidor de correo o en el firewall?
Ejecuta donde puedas ver confiablemente la IP real del cliente y donde un ban realmente bloquee tráfico. Si los logs muestran la IP del proxy, ejecuta fail2ban en el proxy/borde o arregla el logging.
2) ¿Cuál es un punto de partida razonable para maxretry/findtime/bantime?
Para fallos de auth: maxretry=5–6, findtime=10m, bantime=4–12h, más bans incrementales. Luego ajusta según falsos positivos y tasa de ataque observada.
3) ¿Por qué veo muchos “failed” pero pocos bans?
O bien los fallos se distribuyen en muchas IPs (ataque distribuido), o tus umbrales son demasiado indulgentes. Mide IPs únicas por hora; si es alto, fail2ban no será una bala de plata.
4) ¿Fail2ban detendrá el credential stuffing?
Parcialmente. Detiene el subconjunto ruidoso. Para el stuffing real (muchas IPs, pocos intentos cada una) necesitas controles adicionales: límites de tasa, MFA, mejores contraseñas y a veces filtrado de reputación aguas arriba.
5) ¿Debo banear por líneas “NOQUEUE: reject” de Postfix?
No como primer paso. Esas líneas incluyen muchos fallos benignos. Empieza con fallos de auth. Si luego añades bans por abuso de protocolo, mantenlos conservadores y monitorizados.
6) ¿Cómo evito banear oficinas enteras detrás de NAT?
Usa bantime incremental, mantén maxretry ligeramente más alto para IMAP si tus usuarios son mayormente móviles y considera whitelistear solo IPs de egress estables que poseas. Mejor: educa a los usuarios y aplica MFA donde sea posible.
7) ¿IPv6 cambia algo?
Sí. Asegura que tus acciones soporten IPv6 y que tus filtros extraigan direcciones IPv6 correctamente. También evita la tentación de “banear un rango entero”; la dirección IPv6 lo hace arriesgado muy rápido.
8) ¿Debo habilitar recidive?
Sí, pero no el primer día. Primero prueba que tus jails base tengan pocos falsos positivos. Recidive amplifica tus elecciones—buenas o malas.
9) ¿Cuál es la forma más segura de probar nuevos filtros?
Usa fail2ban-regex contra logs reales y revisa las líneas coincidentes. No despliegues un filtro que no hayas probado con tu propio formato de logs.
10) ¿Cómo sé si fail2ban es el cuello de botella?
Usualmente no lo es. El cuello suele ser los backends de auth (LDAP/SQL), I/O de disco por logging excesivo o CPU por workers TLS/auth. Fail2ban suele ser solo el mensajero—y a veces el chivo expiatorio.
Conclusión: próximos pasos que no fallarán
Si quieres que fail2ban para correo realmente ayude, trátalo como código de producción: observable, probado y desplegado en fases.
- Verifica los logs primero (unidad del servicio, fuente de logs, IP presente en líneas de fallo).
- Habilita solo jails de alta señal (Postfix SASL, Dovecot auth) y prueba coincidencias con
fail2ban-regex. - Usa bantime incremental para castigar abuso reiterado y reducir daños colaterales.
- Valida la acción del firewall (existen reglas nftables/iptables y están realmente aplicadas al tráfico).
- Añade recidive al final, una vez que confíes en tu tasa de falsos positivos.
- Documenta el procedimiento de desban y mantiene las whitelists pequeñas y auditables.
Haz eso, y fail2ban se convertirá en lo que debe ser: no “teatro de seguridad”, sino un portero útil y de bajo mantenimiento para los alborotadores más obvios.