Por qué proteger RADIUS con fail2ban#
FreeRADIUS es el pilar de autenticación en muchas redes empresariales: VPNs, switches con 802.1X, Wi-Fi corporativo. El puerto 1812 UDP recibe constantemente intentos de credential stuffing, especialmente si la IP del servidor tiene alguna exposición pública. A diferencia de SSH, donde el atacante necesita llegar a un servicio TCP con negociación, RADIUS sobre UDP no tiene overhead de conexión: enviar miles de paquetes de autenticación cuesta casi nada al atacante.
fail2ban resuelve esto de forma elegante: lee los logs de autenticación, detecta patrones de fallo repetidos y añade reglas de firewall temporales para bloquear el origen. El resultado es que un atacante que falla cinco veces queda bloqueado durante horas sin intervención manual.
Este artículo asume FreeRADIUS 3.x sobre Ubuntu/Debian y fail2ban 0.11+. Para SSH, también se cubre el gotcha del logpath duplicado que impide arrancar el servicio.
Instalación#
fail2ban está en los repositorios oficiales:
apt update && apt install fail2ban ufw -y
systemctl enable fail2banSi UFW no está activo aún, actívalo antes de continuar. fail2ban necesita que el backend de firewall esté operativo para añadir reglas:
ufw allow OpenSSH
ufw enableEstructura de configuración: jail.local es la clave#
Nunca editar /etc/fail2ban/jail.conf. Ese archivo lo sobreescribe el paquete en cada actualización. La práctica correcta es crear /etc/fail2ban/jail.local, que se fusiona con jail.conf en tiempo de carga y tiene precedencia sobre cualquier valor que defina.
El mismo principio aplica a los filtros: /etc/fail2ban/filter.d/ contiene los archivos .conf originales del paquete. Si necesitas modificar un filtro existente, crea un archivo .local con el mismo nombre junto al original.
Jail para SSH#
La jail de SSH viene incluida y activa por defecto en muchas distribuciones, pero hay un error frecuente que hace que fail2ban no arranque: el parámetro logpath definido dos veces cuando se sobreescribe la jail en jail.local.
El bloque correcto para SSH es el siguiente:
[sshd]
enabled = true
logpath = /var/log/auth.logSi en tu jail.local tienes una sección [sshd] y además la jail por defecto en jail.conf también define logpath, fail2ban 0.11+ trata la clave duplicada como error de configuración y se niega a arrancar. La solución es definir logpath solo en jail.local y dejar que sobreescriba el valor de jail.conf.
Para verificar que la configuración es válida antes de reiniciar:
fail2ban-client -tSi no aparece ningún error, la sintaxis es correcta.
Jail para FreeRADIUS#
FreeRADIUS escribe los fallos de autenticación en /var/log/freeradius/radius.log. La jail personalizada usa un findtime más corto que la de SSH porque los ataques de credential stuffing son más agresivos en ráfagas cortas:
[radius-login]
enabled = true
port = 1812
protocol = udp
logpath = /var/log/freeradius/radius.log
maxretry = 5
findtime = 300
bantime = 7200
filter = radius-loginParámetros destacados:
protocol = udp— fail2ban delega a UFW, que sí puede bloquear UDP por IP de origen.findtime = 300— ventana de detección de 5 minutos: cinco fallos en ese periodo activan el bloqueo.bantime = 7200— el origen queda baneado 2 horas. Más agresivo que el SSH porque un servidor RADIUS no tiene usuarios legítimos haciendo diez intentos seguidos.
Filtro personalizado para RADIUS#
fail2ban no incluye un filtro para FreeRADIUS por defecto. Hay que crearlo:
nano /etc/fail2ban/filter.d/radius-login.conf[Definition]
failregex = Login incorrect.*client <HOST>
Auth: .*Login incorrect.*\[<HOST>\]
ignoreregex =El placeholder <HOST> es la notación de fail2ban para capturar la IP del origen. Las dos expresiones cubren los dos formatos que usa FreeRADIUS 3.x en función de la versión y configuración del módulo pap/chap:
Login incorrect.*client <HOST>captura la forma más común donde la IP aparece en el campoclient.Auth: .*Login incorrect.*\[<HOST>\]cubre el formato alternativo con la IP entre corchetes.
Para verificar que el filtro funciona contra entradas reales del log antes de activar la jail:
fail2ban-regex /var/log/freeradius/radius.log /etc/fail2ban/filter.d/radius-login.confLa salida muestra cuántas líneas coinciden. Si el contador es cero con un log que tiene fallos conocidos, hay que ajustar las expresiones.
Configuración completa de jail.local#
El archivo resultante integra todo lo anterior con UFW como backend de baneo:
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 5
banaction = ufw
[sshd]
enabled = true
logpath = /var/log/auth.log
[radius-login]
enabled = true
port = 1812
protocol = udp
logpath = /var/log/freeradius/radius.log
maxretry = 5
findtime = 300
bantime = 7200
filter = radius-loginLa sección [DEFAULT] establece los valores base para todas las jails. Cada jail puede sobrescribir los que necesite, como hace radius-login con findtime y bantime.
banaction = ufw indica a fail2ban que gestione los bloqueos mediante UFW en lugar de iptables directamente. Esto mantiene la coherencia: UFW es la herramienta de gestión de firewall en el sistema, y los baneos de fail2ban aparecen en ufw status junto con el resto de reglas.
Jails que no hay que activar sin verificar#
Un error habitual al configurar fail2ban es activar jails para servicios que no están instalados. Si jail.local tiene [apache-auth] enabled = true pero Apache no está en el sistema, fail2ban buscará el logpath de Apache y fallará al arrancar porque el archivo no existe.
Las jails problemáticas más habituales en un servidor sin esos servicios:
apache-auth,apache-badbots,apache-noscriptvsftpddovecot,postfix
La regla es simple: solo activar jails de servicios que estén instalados y en ejecución en el sistema.
Aplicar la configuración y verificar#
Tras guardar jail.local y el filtro radius-login.conf:
systemctl restart fail2ban
systemctl status fail2banPara ver el estado general de todas las jails activas:
fail2ban-client statusLa salida muestra la lista de jails en ejecución. Para ver el detalle de una jail específica, incluyendo los IPs actualmente baneados:
fail2ban-client status sshd
fail2ban-client status radius-loginLa salida incluye el número total de fallos detectados, IPs baneadas en este momento y el histórico de baneos desde el último reinicio.
Para desbanear manualmente una IP (por ejemplo, si un administrador se bloquea a sí mismo):
fail2ban-client set radius-login unbanip 192.168.1.100
fail2ban-client set sshd unbanip 192.168.1.100Seguimiento en los logs#
fail2ban escribe su propia actividad en /var/log/fail2ban.log. Las entradas relevantes tienen este aspecto:
2026-06-18 10:23:41,452 fail2ban.actions [1234]: NOTICE [radius-login] Ban 203.0.113.45
2026-06-18 10:23:41,460 fail2ban.actions [1234]: NOTICE [sshd] Ban 198.51.100.72Para seguir los baneos en tiempo real:
tail -f /var/log/fail2ban.log | grep BanEn infraestructura con volumen alto de intentos, es habitual ver docenas de baneos por hora en el puerto RADIUS. Eso confirma que el sistema funciona y cuantifica la presión que estaba recibiendo el servidor sin protección.
Conclusión#
La combinación fail2ban + UFW cubre los dos vectores de autenticación más atacados en infraestructura de red: SSH para administración y RADIUS para acceso de usuarios. La configuración descrita en este artículo añade una capa de protección activa con un coste de mantenimiento prácticamente nulo una vez desplegada.
El punto más importante es el que más se pasa por alto: usar jail.local para toda la configuración propia y validar siempre con fail2ban-client -t antes de reiniciar el servicio. Los errores de configuración silenciosos —jails con logpath duplicado o servicios inexistentes— son la causa más habitual de que fail2ban arranque pero no proteja nada.