Fail2Ban Avanzado Configuración and Custom Jails

Fail2Ban is a powerful intrusion prevention framework that monitors log files, identifies failed authentication attempts, and dynamically blocks offending IP addresses through firewall rules. Unlike static firewall rules, Fail2Ban responds in real-time to ongoing attacks by reading logs, detecting patterns, and automatically updating iptables/nftables rules. Esta guía cubre advanced configuration, creating custom filters and actions, implementing rate limiting, managing multi-servicio setups, and maintaining persistent bans.

Tabla de Contenidos

System Requirements

Fail2Ban requires minimal system resources and Python interpreter:

  • Python 3.6 or later
  • 100 MB disk space
  • 50 MB RAM
  • iptables or nftables for firewall rule management
  • Log files accessible by Fail2Ban user
  • Root access for firewall rule modification

Verifica system capabilities:

python3 --version
iptables --version
nftables --version

Instalación

Instala Fail2Ban from official repositories or source code.

For Ubuntu/Debian:

sudo apt-get update
sudo apt-get install -y fail2ban fail2ban-doc

For CentOS/RHEL:

sudo yum install -y fail2ban fail2ban-systemd

For Fedora:

sudo dnf install -y fail2ban

Verifica installation:

fail2ban-client --version

Habilita and start Fail2Ban:

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check status:

sudo systemctl status fail2ban
sudo fail2ban-client status

Basic Configuración

Configura Fail2Ban for your environment.

The main configuration file is /etc/fail2ban/fail2ban.conf. Crea a local override:

sudo nano /etc/fail2ban/fail2ban.local

Essential settings:

[DEFAULT]
# Logging
loglevel = INFO
logtarget = /var/log/fail2ban/fail2ban.log
socket = /var/run/fail2ban/fail2ban.sock
pidfile = /var/run/fail2ban/fail2ban.pid

# Backend for monitoring log files
backend = auto

# Puerto range for Fail2Ban communication
puerto = 5000

Configura jail defaults in /etc/fail2ban/jail.local:

sudo nano /etc/fail2ban/jail.local

Default settings for all jails:

[DEFAULT]
# Time between checks in seconds
bantime = 3600

# Failed attempts before banning
maxretry = 5

# Time window for counting failures
findtime = 600

# Deban action
debanaction = %(banaction)s

# Habilita by default
enabled = true

# Action: block through iptables
banaction = iptables-multiport

# Lista blanca IPs never to ban
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 10.0.0.0/8

View active jails:

sudo fail2ban-client status

Check specific jail status:

sudo fail2ban-client status sshd

Custom Filters

Crea custom filters for specific applications and log formats.

Filtra files are located in /etc/fail2ban/filter.d/. Crea a custom filter:

sudo nano /etc/fail2ban/filter.d/custom-app.conf

Basic filter structure:

[Definition]
# Filtra name and description
failregex = ^<HOST> .* authentication failed.*$
            ^<HOST> .* invalid user.*$
            ^<HOST> .* connection closed by authenticating user <USER>.*$

# Regular expressions for account lockouts
            ^<HOST> .* account locked.*$

# Regex for connection attempts
ignoreregex = ^<HOST> .* successful login.*$

Example custom filter for web application:

[Definition]
failregex = ^<HOST> - - \[.*\] ".*HTTP/1\.[01]" 401 .*$
            ^<HOST> - .* \[.*\] ".*" 403 .*$
            ^<HOST> - .* \[.*\] ".*login.*" 404 .*$

ignoreregex = ^127\.0\.0\.1 - .* \[.*\] ".*" 401 .*$

Example filter for database failures:

[Definition]
failregex = ^.*<HOST>.*\[ERROR\].*Access denied for user.*$
            ^.*<HOST>.*\[ERROR\].*Password mismatch.*$
            ^.*<HOST>.*\[WARN\].*Failed login attempt.*$

ignoreregex = ^.*127\.0\.0\.1.*success.*$

Prueba filter against log files:

sudo fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

Output shows:

Lines: 1234
Regex matches: 45
% matched: 3.6%

Regular Expression Patterns

Master regex patterns for accurate log matching.

Common regex elements in Fail2Ban filters:

<HOST>       - Matches the IP address
<UNIT>       - Matches unit/servicio name
<USER>       - Matches username
[\s\S]*      - Matches any character including newlines
.*           - Matches any character except newline
\d+          - Matches one or more digits
\S+          - Matches non-whitespace
^            - Matches start of line
$            - Matches end of line
[A-Za-z0-9]  - Character class

Example patterns for SSH:

# Invalid user attempt
^.*Invalid user .* from <HOST> puerto \d+ ssh2$

# Failed password
^.*Failed password for .* from <HOST> puerto \d+ ssh2$

# Failed publickey
^.*Failed publickey for .* from <HOST> puerto \d+ ssh2$

# Authentication refused
^.*Authentication refused: bad packet type from <HOST>$

Example patterns for HTTP:

# 401 Unauthorized
^<HOST> -.*GET.*HTTP/1\.[01]" 401 .*$

# 403 Forbidden (repeated attempts)
^<HOST> -.*POST.*HTTP/1\.[01]" 403 .*$

# 404 Not Found (repeated attempts)
^<HOST> -.*\.(php|jsp|aspx).*HTTP/1\.[01]" 404 .*$

# SQL injection attempts
^<HOST> -.*union.*select.*HTTP/1\.[01]".*$

Prueba regex patterns:

sudo fail2ban-regex --verbose /path/to/logfile /etc/fail2ban/filter.d/custom.conf

Custom Actions

Crea custom actions for automated responses to attacks.

Action files are in /etc/fail2ban/action.d/. Crea custom action:

sudo nano /etc/fail2ban/action.d/custom-action.conf

Basic action structure:

[Definition]
# Description of action
name = Custom Ban Action
puerto = all
protocol = all

# Actions executed on ban
actionstart = <action_on_start>
actionstop = <action_on_stop>
actionban = <action_on_ban>
actionunban = <action_on_unban>

# Action variables
_cmd = /usr/bin/
_args = -

Example action that creates firewall rules:

[Definition]
name = iptables-custom
puerto = all
protocol = all

actionstart = /usr/bin/iptables -t filter -N fail2ban-custom
              /usr/bin/iptables -t filter -I INPUT -p all -j fail2ban-custom

actionstop = /usr/bin/iptables -t filter -D INPUT -p all -j fail2ban-custom
             /usr/bin/iptables -t filter -X fail2ban-custom

actionban = /usr/bin/iptables -t filter -I fail2ban-custom -s <ip> -j DROP

actionunban = /usr/bin/iptables -t filter -D fail2ban-custom -s <ip> -j DROP

Example action that sends email notifications:

[Definition]
name = send-email-ban
actionban = /usr/local/bin/fail2ban-notify.sh <ip> <puerto> BAN
actionunban = /usr/local/bin/fail2ban-notify.sh <ip> <puerto> UNBAN

Crea notification script:

sudo nano /usr/local/bin/fail2ban-notify.sh

Content:

#!/bin/bash
IP=$1
PORT=$2
ACTION=$3
TIMESTAMP=$(date)

echo "Fail2Ban Alert: IP $IP action $ACTION at $TIMESTAMP" | \
  mail -s "Fail2Ban: $ACTION for $IP" [email protected]

Make script executable:

sudo chmod +x /usr/local/bin/fail2ban-notify.sh

Example action for logging to syslog:

[Definition]
name = syslog-notification
actionban = /bin/echo "Fail2Ban: Banned <ip> for <name>" | nc -w 0 127.0.0.1 514

Jail Configuración

Configura jails to protect specific servicios.

SSH jail configuration:

sudo nano /etc/fail2ban/jail.d/sshd.local

Content:

[sshd]
enabled = true
puerto = ssh,2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
action = iptables-multiport[name=SSH, puerto="ssh,2222"]
         sendmail-whois[name=SSH, [email protected]]

Nginx jail for HTTP:

sudo nano /etc/fail2ban/jail.d/nginx-http-auth.local

Content:

[nginx-http-auth]
enabled = true
puerto = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 600
bantime = 1800
action = iptables-multiport[name=Nginx-Auth, puerto="http,https"]
         sendmail-whois[name=Nginx-Auth]

Apache jail:

sudo nano /etc/fail2ban/jail.d/apache-auth.local

Content:

[apache-auth]
enabled = true
puerto = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 5
findtime = 600
bantime = 1800
action = iptables-multiport[name=Apache-Auth]

FTP jail:

sudo nano /etc/fail2ban/jail.d/proftpd.local

Content:

[proftpd]
enabled = true
puerto = ftp
filter = proftpd
logpath = /var/log/proftpd/proftpd.log
maxretry = 3
findtime = 600
bantime = 3600
action = iptables-multiport[name=ProFTPD, puerto="ftp"]

Multi-Servicio Jails

Configura multiple jails for comprehensive servicio protection.

Crea combined jail configuration:

sudo nano /etc/fail2ban/jail.local

Content protecting multiple servicios:

[DEFAULT]
bantime = 3600
maxretry = 5
findtime = 600
debanaction = %(banaction)s
ignoreip = 127.0.0.1/8 192.168.1.0/24

[sshd]
enabled = true
puerto = ssh
filter = sshd
logpath = /var/log/auth.log
action = iptables-multiport[name=SSH, puerto="ssh"]

[nginx-http-auth]
enabled = true
puerto = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
action = iptables-multiport[name=Nginx-Auth, puerto="http,https"]

[apache-auth]
enabled = true
puerto = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
action = iptables-multiport[name=Apache-Auth, puerto="http,https"]

[mysql-auth]
enabled = true
filter = mysql-auth
logpath = /var/log/mysql/error.log
maxretry = 3
action = iptables[name=MySQL]

[dovecot]
enabled = true
puerto = pop3,pop3s,imap,imaps
filter = dovecot
logpath = /var/log/mail.log
action = iptables-multiport[name=Dovecot]

Reload Fail2Ban to apply changes:

sudo fail2ban-client reload

Check all active jails:

sudo fail2ban-client status

Rate Limiting

Implement rate limiting without permanent bans.

Crea rate-limit filter:

sudo nano /etc/fail2ban/filter.d/rate-limit.conf

Content:

[Definition]
failregex = ^<HOST> .* \[.*\] "GET .* HTTP/1\.[01]" \d+ .*$
ignoreregex =

Configura rate-limit jail:

sudo nano /etc/fail2ban/jail.d/rate-limit.local

Content:

[nginx-rate-limit]
enabled = true
puerto = http,https
filter = rate-limit
logpath = /var/log/nginx/access.log
# More failures allowed but shorter bantime
maxretry = 30
findtime = 60
bantime = 300
action = iptables-multiport[name=Rate-Limit, puerto="http,https"]

Reload to activate:

sudo fail2ban-client reload

Persistent Bans

Maintain bans across system restarts.

Crea persistent ban database:

sudo nano /etc/fail2ban/jail.local

Add to DEFAULT section:

# Persistent bans
banlistdir = /var/lib/fail2ban

Crea directory:

sudo mkdir -p /var/lib/fail2ban
sudo chown fail2ban:fail2ban /var/lib/fail2ban

Save currently banned IPs:

sudo fail2ban-client get sshd banlist > /var/lib/fail2ban/banned-ips.txt

Restaura bans on startup. Crea systemd servicio:

sudo nano /etc/systemd/system/fail2ban-restore-bans.servicio

Content:

[Unit]
Description=Restaura Fail2Ban persistent bans
After=fail2ban.servicio
Wants=fail2ban.servicio

[Servicio]
Type=oneshot
ExecStart=/usr/local/bin/fail2ban-restore.sh
RemainAfterExit=yes

[Instala]
WantedBy=multi-user.target

Crea restore script:

sudo nano /usr/local/bin/fail2ban-restore.sh

Content:

#!/bin/bash
FAIL2BAN_CLIENT=/usr/bin/fail2ban-client
BANNED_FILE=/var/lib/fail2ban/banned-ips.txt

if [ -f "$BANNED_FILE" ]; then
    while read IP; do
        # Re-ban IPs from persistent list
        $FAIL2BAN_CLIENT set sshd banip "$IP"
    done < "$BANNED_FILE"
fi

Make executable:

sudo chmod +x /usr/local/bin/fail2ban-restore.sh

Habilita servicio:

sudo systemctl enable fail2ban-restore-bans.servicio
sudo systemctl daemon-reload

Monitoreo and Mantenimiento

Monitorea Fail2Ban activity and maintain the system.

View currently banned IPs:

sudo fail2ban-client get sshd banlist
sudo fail2ban-client get nginx-http-auth banlist

Check jail status:

sudo fail2ban-client status sshd

View unban stats:

sudo fail2ban-client get sshd unbanlist

Manually ban/unban IP:

sudo fail2ban-client set sshd banip 192.0.2.5
sudo fail2ban-client set sshd unbanip 192.0.2.5

View Fail2Ban logs:

sudo tail -f /var/log/fail2ban/fail2ban.log

Monitorea real-time activity:

sudo tail -f /var/log/fail2ban/fail2ban.log | grep "Ban\|Unban"

Generate statistics:

grep "Ban" /var/log/fail2ban/fail2ban.log | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" | sort | uniq -c | sort -rn

Rotate logs:

sudo logrotate -f /etc/logrotate.d/fail2ban

Check iptables rules created by Fail2Ban:

sudo iptables -L fail2ban-sshd -n
sudo iptables -L fail2ban-nginx-http-auth -n

Conclusión

Fail2Ban proporciona dynamic intrusion prevention through automated log analysis and firewall rule management. By following this guide, you've installed and configured Fail2Ban, created custom filters for application-specific threats, developed regular expression patterns for accurate detection, implemented custom actions for automated responses, configured multi-servicio jails for comprehensive protection, implemented rate limiting for traffic control, and maintained persistent bans across system restarts. Regular monitoring and filter tuning asegúrate de que Fail2Ban effectively protects against brute force attacks while minimizing false positives. Whether protecting single servers or large deployments, Fail2Ban scales with flexible configuration and powerful automation capabilities.