Fail2Ban protects Rocky Linux servers from brute-force attacks by monitoring log files and automatically banning IP addresses that show malicious behavior. When an attacker attempts repeated failed SSH logins, password guessing, or exploit scanning, Fail2Ban blocks their IP address through firewalld rules, preventing further access attempts. For internet-facing servers, this automated response stops most automated attacks before they succeed.
This guide covers installing and configuring Fail2Ban on Rocky Linux 10, 9, and 8. You will set up the EPEL repository, install Fail2Ban with firewalld integration, configure jails for SSH and web server protection, and learn commands to monitor bans and troubleshoot issues. By the end, your server will have automated intrusion prevention running alongside the firewalld rules you already use.
Fail2Ban installation steps are identical across Rocky Linux 10, 9, and 8. Version 10 and 9 include Fail2Ban 1.1.0 from EPEL, while version 8 provides Fail2Ban 1.0.2. Both versions support the configurations in this guide.
Update Rocky Linux Before Installation
Before installing Fail2Ban, update your system packages to ensure you have the latest security patches and avoid dependency conflicts. Run the following command to refresh package metadata and upgrade all installed packages:
sudo dnf upgrade --refresh
Install the EPEL Repository
Fail2Ban is not available in the default Rocky Linux repositories. The EPEL (Extra Packages for Enterprise Linux) repository provides Fail2Ban and thousands of other production-ready packages maintained by the Fedora Project.
Install the EPEL release package:
sudo dnf install -y epel-release
Verify EPEL is enabled:
dnf repolist | grep epel
Expected output on Rocky Linux 10:
epel Extra Packages for Enterprise Linux 10 - x86_64
Install Fail2Ban on Rocky Linux
With EPEL enabled, install Fail2Ban. The installation automatically includes the fail2ban-firewalld package, which configures Fail2Ban to work with Rocky Linux’s default firewall:
sudo dnf install -y fail2ban
This command installs Fail2Ban along with its firewalld integration and the sendmail action for email notifications. The package dependencies include firewalld itself, so the firewall will be available even on minimal installations.
Verify Installation
Confirm Fail2Ban installed correctly by checking the version:
fail2ban-client --version
Expected output on Rocky Linux 10:
Fail2Ban v1.1.0
Rocky Linux 8 shows version 1.0.2. Both versions work with all configurations in this guide.
Enable and Start Fail2Ban Service
Unlike some packages, Fail2Ban does not start automatically after installation. Enable the service to start at boot and launch it immediately:
sudo systemctl enable --now fail2ban
Verify the service is running:
systemctl status fail2ban
When running correctly, the output shows an active status:
● fail2ban.service - Fail2Ban Service
Loaded: loaded (/usr/lib/systemd/system/fail2ban.service; enabled; preset: disabled)
Active: active (running) since Wed 2026-01-15 10:30:00 UTC; 5s ago
Docs: man:fail2ban(1)
Process: 12345 ExecStartPre=/bin/mkdir -p /run/fail2ban (code=exited, status=0/SUCCESS)
Main PID: 12346 (fail2ban-server)
Tasks: 3 (limit: 4915)
Memory: 12.0M
CPU: 123ms
CGroup: /system.slice/fail2ban.service
└─12346 /usr/bin/python3 -s /usr/bin/fail2ban-server -xf start
Understand Fail2Ban Configuration Structure
Fail2Ban uses a layered configuration system where local files override defaults without being overwritten during package updates. Understanding this structure prevents common configuration mistakes.
Configuration File Hierarchy
Fail2Ban reads configuration files in a specific order, with later files overriding earlier ones:
/etc/fail2ban/jail.confcontains default jail definitions and settings (never edit this file directly)/etc/fail2ban/jail.d/*.confprovides distribution-specific overrides, including00-firewalld.conffor firewalld integration/etc/fail2ban/jail.localholds your custom settings (create this file for overrides)/etc/fail2ban/jail.d/*.localprovides additional local customizations
The fail2ban-firewalld package creates /etc/fail2ban/jail.d/00-firewalld.conf, which sets the default ban action to use firewalld’s rich rules:
cat /etc/fail2ban/jail.d/00-firewalld.conf
# This file is part of the fail2ban-firewalld package to configure the use of # the firewalld actions as the default actions. You can remove this package # (along with the empty fail2ban meta-package) if you do not use firewalld [DEFAULT] banaction = firewallcmd-rich-rules banaction_allports = firewallcmd-rich-rules
This configuration ensures Fail2Ban bans work correctly with firewalld without additional setup.
Create a Local Configuration File
Create jail.local for your custom settings. This file persists through package updates while jail.conf may be overwritten:
sudo nano /etc/fail2ban/jail.local
Start with a basic configuration that enables SSH protection:
[DEFAULT]
# Fail2Ban reads logs from systemd journal on Rocky Linux
backend = systemd
# IPs that should never be banned (add your admin IPs here)
ignoreip = 127.0.0.1/8 ::1
# Ban duration (10 minutes default)
bantime = 10m
# Time window for counting failures
findtime = 10m
# Number of failures before ban
maxretry = 5
[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 1h
findtime = 10m
This configuration protects SSH with stricter settings than the defaults: banning IPs for 1 hour after 3 failed login attempts within 10 minutes. The backend = systemd setting ensures Fail2Ban reads logs from the systemd journal, which Rocky Linux uses by default.
Save the file and restart Fail2Ban to apply changes:
sudo systemctl restart fail2ban
Configure Ban Time Settings
Fail2Ban offers several ways to configure ban durations, from simple fixed times to progressive escalation for repeat offenders.
Fixed Ban Times
The simplest approach sets a fixed ban duration for all offenses. Adjust the bantime value in your jail configuration:
# Examples of ban time formats
bantime = 10m # 10 minutes
bantime = 1h # 1 hour
bantime = 1d # 1 day
bantime = -1 # Permanent ban (until manual unban)
Incremental Ban Times for Repeat Offenders
Fail2Ban can increase ban duration each time an IP triggers another offense. Add these settings to the [DEFAULT] section in jail.local:
# Enable incremental bans
bantime.increment = true
# Multiplier values for each subsequent ban
bantime.multipliers = 1 2 4 8 16 32 64
With a base bantime = 10m and these multipliers, an IP is banned for 10 minutes on first offense, 20 minutes on second, 40 minutes on third, and so on up to 640 minutes (about 10.5 hours) for persistent attackers.
Allowlist Trusted IP Addresses
Prevent specific IP addresses or networks from being banned by adding them to the ignoreip setting. This is essential for admin workstations and monitoring systems:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 203.0.113.50
This example allowlists localhost, IPv6 loopback, an entire local network (192.168.1.0/24), and a specific external IP. Always include your own IP address when working on remote servers to prevent accidental lockout.
Configure Additional Service Jails
Beyond SSH protection, Fail2Ban includes pre-configured filters for web servers, mail services, and other common attack vectors. Enable only the jails that match services running on your server to avoid unnecessary log monitoring overhead.
Apache Web Server Protection
If you run Apache on Rocky Linux, add these jails to jail.local:
# Protect against authentication failures
[apache-auth]
enabled = true
port = http,https
logpath = %(apache_error_log)s
maxretry = 3
bantime = 1h
# Block malicious bot scanning
[apache-badbots]
enabled = true
port = http,https
logpath = %(apache_access_log)s
maxretry = 2
bantime = 48h
The apache-auth jail catches failed basic authentication attempts, while apache-badbots blocks automated scanners looking for vulnerabilities. Apache log paths on Rocky Linux default to /var/log/httpd/*error_log and /var/log/httpd/*access_log.
Nginx Web Server Protection
For Nginx servers, enable these jails:
# Protect against HTTP authentication failures
[nginx-http-auth]
enabled = true
port = http,https
logpath = %(nginx_error_log)s
maxretry = 3
bantime = 1h
# Block bots scanning for exploits
[nginx-botsearch]
enabled = true
port = http,https
logpath = %(nginx_access_log)s
maxretry = 2
bantime = 2h
Web server jails use file-based logging because Apache and Nginx write to /var/log/httpd/ and /var/log/nginx/ by default. These log directories only exist after the respective web server is installed. Enabling a web server jail before installing the web server causes Fail2Ban to report log file not found errors.
Mail Server Protection
For Postfix and Dovecot mail servers, add authentication protection:
# Protect Postfix SMTP authentication
[postfix-sasl]
enabled = true
port = smtp,submission,smtps
backend = systemd
maxretry = 3
bantime = 1h
# Protect Dovecot IMAP/POP3
[dovecot]
enabled = true
port = imap,imaps,pop3,pop3s
backend = systemd
maxretry = 5
bantime = 1h
Apply Configuration Changes
After modifying jail.local, validate the syntax before restarting:
sudo fail2ban-client -t
When the configuration passes validation:
OK: configuration test is successful
Restart Fail2Ban to apply the new configuration:
sudo systemctl restart fail2ban
Manage Bans with Fail2Ban-Client
The fail2ban-client command provides tools to view jail status, manually ban or unban IPs, and reload configuration without restarting the service.
View Active Jails
Check which jails are currently running and their status:
sudo fail2ban-client status
Example output with SSH jail enabled:
Status |- Number of jail: 1 `- Jail list: sshd
View Jail Details and Banned IPs
Get detailed information about a specific jail, including currently banned IP addresses:
sudo fail2ban-client status sshd
Example output showing active bans:
Status for the jail: sshd |- Filter | |- Currently failed: 3 | |- Total failed: 15 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd `- Actions |- Currently banned: 1 |- Total banned: 2 `- Banned IP list: 203.0.113.7
The output shows that 15 failed attempts have been logged, 2 IPs have been banned in total, and 1 IP (203.0.113.7) is currently banned. The “Journal matches” line confirms Fail2Ban is reading from the systemd journal.
Ban an IP Address Manually
Block an IP address in a specific jail immediately without waiting for failed attempts:
sudo fail2ban-client set sshd banip 203.0.113.7
Manual bans follow the same duration as automatic bans unless you specify otherwise.
Unban an IP Address
Remove a ban from a specific IP address when you need to restore access:
sudo fail2ban-client set sshd unbanip 203.0.113.7
Use this when a legitimate user or service has been accidentally banned.
Reload Configuration Without Restart
Apply configuration changes without losing current ban states:
sudo fail2ban-client reload
A full restart with systemctl restart fail2ban clears all active bans, while reload preserves them while applying new jail configurations.
Verify Firewalld Integration
Fail2Ban on Rocky Linux uses firewalld’s rich rules to implement bans. Verify this integration is working correctly.
Test Ban Functionality
Confirm firewalld is running before testing bans:
sudo firewall-cmd --state
running
Ban a test IP address and verify the firewall rule is created:
sudo fail2ban-client set sshd banip 203.0.113.7
sudo firewall-cmd --list-rich-rules
Expected output showing the Fail2Ban-created rich rule:
rule family="ipv4" source address="203.0.113.7" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
Unban the test IP to clean up:
sudo fail2ban-client set sshd unbanip 203.0.113.7
Check Firewalld Active Zones
View your current firewalld configuration to ensure SSH is allowed:
sudo firewall-cmd --list-all
Sample output on a Rocky Linux server:
public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: cockpit dhcpv6-client ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules:
The services: ssh entry confirms SSH traffic is allowed through the firewall. When Fail2Ban adds a ban, the rich rules section shows the blocked IP addresses.
Monitor Fail2Ban Logs
Fail2Ban logs activity to /var/log/fail2ban.log by default. Use these logs to verify jails are working and investigate ban activity. The tail command provides several ways to view log files in real-time or review recent entries.
View Recent Log Activity
Check the last 20 lines of the Fail2Ban log:
sudo tail -20 /var/log/fail2ban.log
Monitor Log Activity in Real Time
Watch for ban and unban events as they happen:
sudo tail -f /var/log/fail2ban.log
Press Ctrl+C to stop following the log.
Search Logs for Specific Information
Use grep to search for specific IP addresses, jail names, or events:
# Find all ban events
grep "Ban" /var/log/fail2ban.log
# Search for a specific IP address
grep "203.0.113.7" /var/log/fail2ban.log
# Find SSH-related entries
grep "sshd" /var/log/fail2ban.log
Configure Email Notifications
Fail2Ban can send email notifications when bans occur. This requires a mail transfer agent capable of sending outbound email.
Install Mail Support
Install Postfix as a local mail relay and the s-nail utility for sending mail from the command line:
sudo dnf install -y postfix s-nail
sudo systemctl enable --now postfix
The s-nail package provides the mail command on Rocky Linux 9 and 10. On Rocky Linux 8, this package was called mailx, but s-nail works across all versions because it provides the same command interface.
Configure Email Alerts
Add email notification settings to the [DEFAULT] section in jail.local:
[DEFAULT]
destemail = admin@example.com
sender = fail2ban@example.com
# Send email with whois data and relevant log lines
action = %(action_mwl)s
The action_mwl action sends email alerts with whois information about the banned IP and the log lines that triggered the ban. Test email delivery before relying on it for critical alerts:
echo "Test email from Fail2Ban server" | mail -s "Fail2Ban Test" admin@example.com
Troubleshoot Common Issues
This section covers common problems encountered when setting up or running Fail2Ban on Rocky Linux.
Jails Not Starting or No Bans Occurring
If a jail is not working, check if it is enabled and running:
sudo fail2ban-client status
If the jail is not listed, verify the configuration syntax:
sudo fail2ban-client -t
Check the Fail2Ban log for startup errors:
sudo journalctl -xeu fail2ban
Filter Not Matching Log Entries
If a jail is running but not catching attacks, test the filter regex against actual log data. Rocky Linux uses the systemd journal for SSH logs by default, so use the systemd-journal source:
sudo fail2ban-regex systemd-journal /etc/fail2ban/filter.d/sshd.conf
Add the -v flag for verbose output that shows exactly which regex patterns matched and what IP addresses were captured:
sudo fail2ban-regex -v systemd-journal /etc/fail2ban/filter.d/sshd.conf
The verbose output reveals whether the filter captured the HOST value (the attacker IP) from each log line. If you see None instead of an IP address, the filter pattern is matching but not extracting the IP correctly, and no bans will occur.
The
/var/log/securefile only exists if you have rsyslog installed and configured. Default Rocky Linux installations write SSH logs to the systemd journal only. Usesystemd-journalas the log source unless you have specifically configured rsyslog.
Firewalld Connection Problems
If bans are occurring in Fail2Ban but not blocking traffic, check firewalld status:
sudo systemctl status firewalld
If firewalld is not running, start and enable it:
sudo systemctl enable --now firewalld
Restart Fail2Ban after starting firewalld to reinitialize the ban action:
sudo systemctl restart fail2ban
Backend Configuration Errors
Rocky Linux uses the systemd journal for most service logs instead of traditional text files. If Fail2Ban reports log file not found errors for SSH or similar services, your jail configuration needs the systemd backend:
[DEFAULT]
backend = systemd
[sshd]
enabled = true
Setting backend = systemd in the [DEFAULT] section applies it to all jails. Jails for services that write to traditional log files (Apache, Nginx) automatically fall back to backend = auto when you specify a logpath instead of relying on the systemd journal.
The default backend = auto works well in most cases. It detects systemd and reads from the journal when appropriate, falling back to file monitoring when a logpath is specified. The explicit backend = systemd configuration guarantees journal-based monitoring even if auto-detection fails.
Remove Fail2Ban
If you no longer need Fail2Ban on your Rocky Linux system, follow these steps to remove it completely.
Stop and disable the service:
sudo systemctl stop fail2ban
sudo systemctl disable fail2ban
Remove the packages:
sudo dnf remove fail2ban fail2ban-firewalld fail2ban-sendmail fail2ban-server
DNF removes unused dependencies automatically. Configuration files in /etc/fail2ban/ remain after package removal by default.
The following command permanently deletes all Fail2Ban configuration files, including your custom jail settings in jail.local. If you might reinstall Fail2Ban later, skip this step to preserve your configurations.
sudo rm -rf /etc/fail2ban/
Remove the Fail2Ban log file and database:
sudo rm -f /var/log/fail2ban.log*
sudo rm -rf /var/lib/fail2ban/
Verify removal by checking for the package:
rpm -qa | grep fail2ban
No output confirms successful removal.
Conclusion
Your Rocky Linux server now has Fail2Ban protecting against brute-force attacks, with firewalld integration handling the actual traffic blocking. The SSH jail provides immediate protection, and you can extend coverage to web servers and mail services by enabling additional jails. For servers exposed to the public internet, consider combining Fail2Ban with SSH key-based authentication and disabling password login entirely for comprehensive protection. Regular log review with fail2ban-client status and tail -f /var/log/fail2ban.log helps identify attack patterns and tune ban thresholds to match your environment.