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
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
- 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
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
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
- 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
- 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:
- Access via physical console or hypervisor
- Unban the IP:
fail2ban-client set sshd unbanip YOUR_IP - 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