Fail2ban is an intrusion prevention framework that protects server services from brute-force and other automated attacks by scanning log files and banning IPs in the host firewall. This guide provides a production-ready configuration for SSH hardening, including custom jail tuning, firewall integration, and alignment with Swiss security standards (BSI/OSI).
Fail2ban operates as a stateless daemon composed of three core components:
1. Filters: Regex patterns that search log files (e.g., /var/log/auth.log) for failed authentication attempts. 2. Jails: Define which filters trigger actions, what services to ban, and how long the ban lasts. 3. Actions: Shell scripts (typically firewall rule modifications) that enforce the ban by adding a block rule to the OS firewall.
Workflow:Log Event → Filter Match → Retry Counter Increases → Max Retries Hit → Action Triggered (IP Ban)
⚠️ Prerequisite: Ensure you have root/sudo access. Never configure Fail2ban remotely until you test on a console or ensure you have an out-of-band access method (like VNC/IPMI), as misconfiguration can lock you out.
sudo apt update
sudo apt install fail2ban -y sudo systemctl enable fail2ban sudo systemctl start fail2ban
sudo dnf install epel-release -y
sudo dnf install fail2ban -y sudo systemctl enable fail2ban sudo systemctl start fail2ban
/etc/fail2ban/jail.conf. It will be overwritten on updates. Always create /etc/fail2ban/jail.local.
Create the override file:
sudo nano /etc/fail2ban/jail.local
Paste the following baseline SSH configuration:
[DEFAULT]
# Ignore internal traffic (replace with your specific subnets) ignoreip = 127.0.0.1/8, ::1, 10.0.0.0/8, 192.168.0.0/16
# Ban duration: 10 minutes (600 seconds) bantime = 600
# Number of attempts before ban: 5 maxretry = 5
# Window to count attempts: 10 minutes (600 seconds) findtime = 600
# Backend detection for log files backend = auto
# Actions (Default) # Use iptables for legacy, nftables for modern (RHEL 9+, Debian 11+) action = %(action_mwl)s
[sshd] enabled = true port = ssh filter = sshd logpath = %(sshd_logpath)s maxretry = 5 bantime = 1h action = iptables[name=SSH, protocol=tcp, port=ssh]
Key Configuration Notes:
- logpath: For Ubuntu/Debian, usually /var/log/auth.log. For CentOS/RHEL, usually /var/log/secure. - action: iptables is the standard, but for newer distributions, nftables is preferred. - nftables Action: action = nftables[name=SSH, protocol=tcp, port=ssh]
While the built-in SSHD filter is robust, you may need to handle specific scenarios (e.g., custom auth logs, or integrating with a custom app).
If you have an application that logs specific failure patterns:
1. Create the filter:
sudo mkdir -p /etc/fail2ban/filter.d
sudo nano /etc/fail2ban/filter.d/myapp-auth.conf
2. Content:
[Definition]
failregex = Failed password for (.*? from)?
3. Create the jail: In /etc/fail2ban/jail.local:
[myapp-jail]
enabled = true port = http,https filter = myapp-auth logpath = /var/log/myapp/auth.log bantime = 3600 action = iptables[name=MyApp, protocol=tcp]
If you are running CentOS/RHEL with firewalld, use the following action line:
action = firewallcmd-name=ssh
Note: Ensure the firewall service is active before starting Fail2ban.
A "recidive" jail is a second layer of defense. If an IP hits the ban threshold multiple times across different jails, it gets permanently banned (or for a long duration).
Add to /etc/fail2ban/jail.local:
[recidive]
enabled = true logpath = %(sshd_logpath)s maxretry = 3 bantime = 10d ignoreip = 127.0.0.1/8
Logic: If an IP is banned 3 times by any other jail, it enters the Recidive jail for 10 days.
Crucial for preventing self-lockout during updates or automated scripts.
1. Identify your IPs: Use ip addr or ifconfig. 2. Add to ignoreip:
[DEFAULT]
ignoreip = 127.0.0.1, ::1, 192.168.1.100, 10.0.0.0/24
If you have a known hostile environment, tighten the parameters:
[sshd]
enabled = true maxretry = 3 bantime = 3600 # 1 hour findtime = 600
# Check system status
sudo fail2ban-client status
# Check specific jail status sudo fail2ban-client status sshd
# See banned IPs currently sudo fail2ban-client get sshd banned
Fail2ban writes events to /var/log/fail2ban.log. Use tail for real-time monitoring:
sudo tail -f /var/log/fail2ban.log
Look for lines containing: - FAIL (Triggering a filter) - RESTART (Service restarts) - BAN (IP blocked) - UNBAN (Time elapsed or manual unbanning)
Create a script to alert if Fail2ban is running or IPs are banned:
#!/bin/bash
if ! systemctl is-active --quiet fail2ban; then echo "CRITICAL: Fail2ban is not running!" >> /var/log/fail2ban_alerts.log # Add notification webhook call here fi
* Risk: Banning your own IP when testing remotely. * Fix: Always whitelist your management IP in ignoreip. * Mitigation: Ensure you have console access (IPMI/VNC) before enabling.
* Risk: jail.conf changes during updates, wiping your custom config. * Fix: You must use jail.local. Settings in this file override jail.conf.
* Risk: A legitimate user triggers the ban due to a bad password. * Fix: Adjust maxretry (default 5) and ensure findtime is wide enough to catch legitimate users. Monitor logs to identify high-frequency IPs that aren't malicious.
* Risk: Reading massive log files can slow down the daemon. * Fix: Use backend = inotify for real-time file monitoring (available in newer versions). Edit /etc/fail2ban/jail.local:
[DEFAULT]
backend = inotify
Swiss organizations typically align with BSI IT-Grundschutz (often the basis for Swiss Federal Administration standards) and LINFO (Law on Information Security).
* Requirement: Hosts must be protected against unauthorized access. * Implementation: Fail2ban acts as a "Host Intrusion Prevention System." It prevents unauthorized SSH access by limiting password guessing. * Alignment: Your configuration ensures that only authenticated users access the shell, meeting the "Protection against password guessing" control.
* Requirement: Security-relevant events must be logged. * Implementation: Fail2ban logs all bans, fails, and restarts to /var/log/fail2ban.log. * Action: Ensure log rotation is configured (/etc/logrotate.d/fail2ban). Retain logs for at least 3-6 months depending on organizational policy to meet audit requirements.
* Requirement: Processing personal data (IP addresses are considered personal data in Switzerland). * Implementation: - Limit the scope: ignoreip ensures only internal traffic is trusted; IPs are stored locally. - Access Control: Fail2ban automatically locks out IPs, enforcing the "Principle of Least Privilege" for external access. - Incident Response: The banlist serves as an initial forensic log for analyzing attack vectors.
1. [ ] Log Retention: Configure logrotate for /var/log/fail2ban.log. 2. [ ] Whitelist Review: Document why specific IPs are in ignoreip. 3. [ ] Audit Trail: Verify /var/log/fail2ban.log is writable by the system but not readable by standard users. 4. [ ] Multi-Factor Auth: Fail2ban is a layer, not a silver bullet. For high-security Swiss environments, combine Fail2ban with SSH Keys + 2FA (e.g., Google Authenticator).
Run these commands to ensure a clean state:
# 1. Reload configuration (safe to reload)
sudo fail2ban-client reload
# 2. Check for configuration errors sudo fail2ban-client -x
# 3. Verify iptables rules (Check if chains exist) sudo iptables -L fail2ban-ssh -n
# 4. Verify firewall state sudo systemctl status firewalld # Or ufw status / systemctl status fail2ban
Conclusion
By following this guide, you move beyond basic installation to a hardened, compliant, and maintainable security posture suitable for enterprise Swiss standards.
About SwissLayerSwissLayer provides secure, high-performance hosting in Switzerland - fully aligned with Swiss security standards and data protection laws.
🔒 Learn more: https://www.swisslayer.com