Fail2ban Installation

Protection against brute force attacks - BTS SIO SISR

Objective

Deploy Fail2ban, an intrusion prevention system (IPS) that analyses log files and automatically bans IP addresses exhibiting malicious behaviour (repeated SSH login attempts, port scans, web attacks, etc.).

Prerequisites

  • Debian 11 / Ubuntu server
  • Active SSH service
  • Root or sudo access
  • iptables installed (usually present by default)

Full Procedure

Step 1: Install Fail2ban

apt update
apt install fail2ban -y

Verify the installation:

fail2ban-client --version

Step 2: Initial configuration

Copy the default configuration file (best practice: never modify jail.conf directly):

cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Why jail.local?
The jail.conf file is overwritten when Fail2ban is updated. The jail.local file takes priority and preserves your custom configuration.

Step 3: Basic configuration

Edit the configuration file:

nano /etc/fail2ban/jail.local

Find and modify the [DEFAULT] section (Ctrl+W to search):

[DEFAULT]
# Ban duration in seconds (3600 = 1 hour)
bantime = 3600

# Observation period in seconds (600 = 10 minutes)
findtime = 600

# Maximum number of attempts before ban
maxretry = 5

# Detection backend (auto, systemd, polling)
backend = systemd

# Default action (ban + optional email)
banaction = iptables-multiport
destemail = [email protected]
sendername = Fail2Ban
action = %(action_)s
Parameter explanations:
  • bantime: ban duration for the IP (in seconds)
  • findtime: time window for counting attempts
  • maxretry: number of allowed failures before ban
  • backend: log reading method (systemd for Debian 11)
  • action: action to execute on ban (iptables block)

Step 4: SSH jail configuration

Find the [sshd] section in the jail.local file:

[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
Note: If you changed the SSH port (e.g. 2222), change port = 2222

Save and quit (Ctrl+O, Enter, Ctrl+X)

Step 5: Start Fail2ban

Enable Fail2ban at system startup:

systemctl enable fail2ban

Start the service:

systemctl start fail2ban

Check the status:

systemctl status fail2ban
Expected result: The service should be "active (running)"

Verification and Useful Commands

Check SSH jail status

fail2ban-client status sshd

Displays:

  • Total number of banned IPs
  • Number of currently banned IPs
  • List of banned IPs

List all active jails

fail2ban-client status

Manually unban an IP

fail2ban-client set sshd unbanip 192.168.1.50

Manually ban an IP

fail2ban-client set sshd banip 192.168.1.50

Reload the configuration

systemctl reload fail2ban

View Fail2ban logs

tail -f /var/log/fail2ban.log

Or filtered for SSH:

grep 'sshd' /var/log/fail2ban.log

Check iptables rules added by Fail2ban

iptables -L f2b-sshd -v -n

Test the configuration before restart

fail2ban-client -t

Displays "OK" if the configuration is valid

Advanced Configuration: Protecting Other Services

Apache protection (HTTP/HTTPS)

Add to /etc/fail2ban/jail.local:

[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 5
bantime = 3600

[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/apache2/access.log
maxretry = 3
bantime = 86400

[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/error.log
maxretry = 6
bantime = 3600

Nextcloud protection

[nextcloud]
enabled = true
port = http,https
filter = nextcloud
logpath = /var/www/nextcloud/data/nextcloud.log
maxretry = 5
bantime = 3600

Create the Nextcloud filter:

nano /etc/fail2ban/filter.d/nextcloud.conf

Filter contents:

[Definition]
failregex = ^.*Login failed: '.*' \(Remote IP: ''.*$
 ^.*\"remoteAddr\":\"\".*\"message\":\"Login failed:.*$
ignoreregex =

MySQL/MariaDB protection

[mysqld-auth]
enabled = true
filter = mysqld-auth
port = 3306
logpath = /var/log/mysql/error.log
maxretry = 5
bantime = 3600

Port scan protection

[portscan]
enabled = true
filter = portscan
logpath = /var/log/syslog
maxretry = 5
bantime = 86400

Restart Fail2ban after changes:

systemctl restart fail2ban

Monitoring and Statistics

Ban statistics

# Currently banned IPs
fail2ban-client status sshd | grep "Banned IP list"

# Total number of bans
fail2ban-client status sshd | grep "Total banned"

# Ban history in logs
grep "Ban" /var/log/fail2ban.log

# Most banned IPs
grep "Ban" /var/log/fail2ban.log | awk '{print $NF}' | sort | uniq -c | sort -rn | head -10

Real-time monitoring

tail -f /var/log/fail2ban.log | grep --color 'Ban\|Unban'

Check failed SSH login attempts

grep "Failed password" /var/log/auth.log | tail -20

Security and Limitations

Advantages of Fail2ban

  • Automatic brute force protection
  • Reduces server load (fewer attempts)
  • Customisable for many services
  • Detailed attack logs
  • Low resource consumption
  • Compatible with iptables/nftables

Limitations and precautions

Points to note:
  • May ban legitimate IPs if misconfigured
  • Does not protect against distributed attacks (massive DDoS)
  • Ineffective if the attacker changes IP with each attempt
  • Requires regular monitoring (unban false positives)
  • iptables rules are lost on reboot (use iptables-persistent)

IP whitelist (never ban)

Edit /etc/fail2ban/jail.local, [DEFAULT] section:

ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 10.0.0.0/8
Explanations:
  • 127.0.0.1/8: localhost
  • ::1: IPv6 localhost
  • 192.168.1.0/24: local network (adapt to your network)
  • 10.0.0.0/8: RFC 1918 private ranges

iptables rule persistence

apt install iptables-persistent -y
netfilter-persistent save

Email notifications (optional)

Install an MTA (Mail Transfer Agent):

apt install postfix mailutils -y

Configuration in jail.local:

destemail = [email protected]
sendername = Fail2Ban
mta = mail
action = %(action_mwl)s

Permanent ban

For a permanent ban (not recommended, prefer long durations):

bantime = -1

Progressive ban (repeat offenders)

Install the recidive module:

[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
bantime = 604800 # 7 days
findtime = 86400 # 1 day
maxretry = 5

Bans IPs that have already been banned multiple times (repeat offenders)

Troubleshooting

Problem: Fail2ban does not start

journalctl -xe -u fail2ban
fail2ban-client -t

Check the syntax of configuration files

Problem: A jail is not working

# Check that the log file exists and is accessible
ls -l /var/log/auth.log

# Manually test the filter
fail2ban-regex /var/log/auth.log /etc/fail2ban/filter.d/sshd.conf

Problem: Unban yourself

If you are accidentally banned:

  1. Access via physical console or hypervisor
  2. Unban the IP:
    fail2ban-client set sshd unbanip YOUR_IP
  3. Add the IP to the whitelist (ignoreip)

Problem: iptables rules disappear

Install and configure iptables-persistent:

apt install iptables-persistent -y
netfilter-persistent save
systemctl enable netfilter-persistent

Key Points for the BTS Oral

  • Fail2ban: IPS (Intrusion Prevention System) based on log analysis
  • Principle: detection of malicious patterns in logs → automatic ban via iptables
  • Jail: protection configuration for a specific service (SSH, Apache, etc.)
  • Ban: adding an iptables DROP rule for the malicious IP
  • Key parameters: maxretry, bantime, findtime
  • Backend: systemd for Debian 11 (reads journald logs)
  • Complementarity: to be combined with firewall, SSH keys, port knocking
  • Limitations: ineffective against distributed DDoS, requires monitoring