Saltar a contenido

Configurar Fail2ban

UFW bloquea tráfico no deseado, pero no detecta intentos de intrusión repetidos. Fail2ban vigila los logs del servidor y, cuando un IP acumula demasiados fallos de autenticación o peticiones a rutas sensibles, crea una regla temporal en UFW para bloquearla.

Qué hace

Fail2ban ejecuta ciclos periódicos de lectura sobre los logs que se le indican:

  • Filtros — expresiones regulares que definen qué líneas del log son sospechosas (intentos de login fallidos, peticiones a /wp-config.php, etc.).
  • Jaulas — combinan un filtro con una acción: si una IP supera maxretry veces en el intervalo de tiempo definido, se aplica el baneo.
  • Acción ufw — en vez de manipular iptables directamente, Fail2ban crea y elimina reglas de UFW, manteniendo todo integrado.

Protección activa con jaulas integradas en UFW.

Traefik en Docker

Si tu servidor web corre detrás de Traefik en contenedores, fail2ban no lee los logs del host de forma directa — este paso no cubre ese caso. Necesitarás montar los logs del contenedor en el host o usar un plugin externo (por ejemplo f2b-traefik). La parte de sshd de abajo sí aplica igualmente.

Instalar

  1. Comprobar si ya está instalado:

    dpkg -l | grep fail2ban
    
    rpm -qa | grep fail2ban
    
  2. Instalar si hace falta:

    sudo apt install fail2ban
    
    sudo dnf install fail2ban
    

Configurar

  1. Comprobar que existe la acción ufw de fail2ban:

    ls /etc/fail2ban/action.d/ufw.conf
    

    Si no existe, usa banaction = iptables-multiport en vez de ufw en el paso siguiente.

  2. Crear el filtro para rutas sensibles:

    sudo vim /etc/fail2ban/filter.d/apache-sensitive-paths.conf
    

    Contenido:

    [Definition]
    failregex = ^<HOST> .* "(GET|POST) .*(wp-config\.php|\.env|\.git/config|xmlrpc\.php|\.htpasswd).*" (403|404)
    ignoreregex =
    
    sudo vim /etc/fail2ban/filter.d/nginx-sensitive-paths.conf
    

    Contenido (mismo patrón, adaptado al log de nginx):

    [Definition]
    failregex = ^<HOST> .* "(GET|POST) .*(wp-config\.php|\.env|\.git/config|xmlrpc\.php|\.htpasswd).*" (403|404)
    ignoreregex =
    
  3. Crear jail.local desde cero (no copiar jail.conf — solo va aquí lo que sobreescribes):

    sudo vim /etc/fail2ban/jail.local
    

    Contenido:

    [DEFAULT]
    banaction = ufw
    
    [sshd]
    enabled = true
    port    = 22
    maxretry = 5
    bantime  = 3600
    
    [apache-auth]
    enabled = true
    
    [apache-badbots]
    enabled = true
    
    [apache-sensitive-paths]
    enabled  = true
    port     = http,https
    filter   = apache-sensitive-paths
    logpath  = /var/log/apache2/*access.log
    maxretry = 1
    bantime  = 86400
    
    [DEFAULT]
    banaction = ufw
    
    [sshd]
    enabled = true
    port    = 22
    maxretry = 5
    bantime  = 3600
    
    [nginx-http-auth]
    enabled = true
    
    [nginx-botsearch]
    enabled = true
    
    [nginx-sensitive-paths]
    enabled  = true
    port     = http,https
    filter   = nginx-sensitive-paths
    logpath  = /var/log/nginx/*access.log
    maxretry = 1
    bantime  = 86400
    

     

    Fail2ban trae de serie los filtros nginx-http-auth y nginx-botsearch (equivalentes a apache-auth/apache-badbots), así que no hace falta crearlos a mano — solo el de rutas sensibles del paso anterior.

Verificar

  1. Reiniciar y comprobar el estado:

    sudo service fail2ban restart
    sudo fail2ban-client status
    sudo fail2ban-client status sshd
    sudo ufw status numbered
    

Y ahora qué

Fail2ban está activo y bloqueando intentos sospechosos. El siguiente paso es configurar las Actualizaciones automáticas para mantener el sistema parcheado.