SSH password probes and noisy login scans are much easier to handle when Rocky Linux can block repeat offenders automatically instead of waiting for a manual firewall rule. Fail2Ban watches service logs, counts repeated failures, and adds temporary firewalld rich rules for IP addresses that cross your threshold.
You can install Fail2Ban on Rocky Linux from EPEL, then enable an SSH jail that reads the systemd journal and blocks through Rocky’s default firewalld stack. The same workflow also gives you status checks, manual ban and unban commands, optional web or mail jails, and a clean removal path.
Rocky Linux 10, 9, and 8 use the same EPEL-based Fail2Ban setup. EPEL currently packages Fail2Ban 1.1.0 for Rocky Linux 10 and 9, while Rocky Linux 8 receives Fail2Ban 1.0.2; the SSH jail and firewalld action work on all three releases.
Install Fail2Ban on Rocky Linux
The install path has three parts: refresh DNF metadata, enable EPEL, then install the Fail2Ban package. Rocky Linux does not include Fail2Ban in the base repositories, so EPEL is the package source for this workflow.
Update Rocky Linux Packages
Refresh package metadata and apply available updates before adding the security service:
sudo dnf upgrade --refresh
Commands that start with
sudorequire an account with administrator privileges. Use a sudo-enabled user or switch to an administrative shell before continuing.
Enable EPEL for Fail2Ban
Install the EPEL release package from Rocky’s Extras repository:
sudo dnf install -y epel-release
EPEL may print a note that many packages need CRB or PowerTools. Fail2Ban resolves on Rocky Linux 10, 9, and 8 after installing epel-release, so do not enable extra repositories unless DNF reports a dependency problem for your system. The full EPEL setup guide for Rocky Linux covers CRB and PowerTools in more detail.
Confirm that EPEL is enabled:
dnf repolist --enabled | grep '^epel'
Relevant output on Rocky Linux 10 looks like this:
epel Extra Packages for Enterprise Linux 10 - x86_64
Install the Fail2Ban Packages
Install Fail2Ban from EPEL:
sudo dnf install -y fail2ban
The fail2ban package is a small meta package. DNF also installs the split packages that provide the server, firewalld action, SELinux policy, and sendmail-compatible notification action.
Check the installed package set:
rpm -q fail2ban fail2ban-server fail2ban-firewalld fail2ban-selinux
Rocky Linux 10 returns the current EPEL 10 package series:
fail2ban-1.1.0-6.el10_0.noarch fail2ban-server-1.1.0-6.el10_0.noarch fail2ban-firewalld-1.1.0-6.el10_0.noarch fail2ban-selinux-1.1.0-6.el10_0.noarch
Rocky Linux 9 uses the same 1.1.0 series from EPEL 9. Rocky Linux 8 uses the 1.0.2 series from EPEL 8.
Verify the Fail2Ban Command
Check the client version before starting the service:
fail2ban-client --version
Expected output on Rocky Linux 10 and 9:
Fail2Ban v1.1.0
Enable and Start Fail2Ban
Fail2Ban installs disabled and inactive. Enable it for future boots and start it now:
sudo systemctl enable --now fail2ban
Verify both runtime and boot state:
systemctl is-active fail2ban
systemctl is-enabled fail2ban
A running and enabled service returns:
active enabled
Confirm the client can reach the Fail2Ban socket:
sudo fail2ban-client ping
Server replied: pong
Configure Fail2Ban SSH Protection on Rocky Linux
The safest first jail is SSH, because most internet-facing servers receive password and username probes quickly. If SSH is not installed or not listening yet, finish the SSH setup on Rocky Linux before relying on the jail.
Understand the Fail2Ban Configuration Order
Fail2Ban loads packaged defaults first and local overrides afterward. Use local files for your changes so package updates can replace upstream defaults safely.
/etc/fail2ban/jail.confcontains packaged defaults. Do not edit this file directly./etc/fail2ban/jail.d/*.confcontains packaged override files, including Rocky’s firewalld action file./etc/fail2ban/jail.localcan hold site-wide local overrides./etc/fail2ban/jail.d/*.localis useful for small service-specific local overrides, such as one file for SSH and another for Nginx.
The fail2ban-firewalld package sets the default ban action to firewalld rich rules. The sed command prints the packaged override without editing it:
sudo sed -n '1,8p' /etc/fail2ban/jail.d/00-firewalld.conf
The relevant lines are:
# 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
Create an SSH Jail Override
Create a dedicated local file for the SSH jail. The sudo tee command writes to the root-owned Fail2Ban directory, while > /dev/null keeps the terminal from echoing the file contents a second time.
printf '%s\n' \
'[DEFAULT]' \
'ignoreip = 127.0.0.1/8 ::1' \
'bantime = 10m' \
'findtime = 10m' \
'maxretry = 5' \
'' \
'[sshd]' \
'enabled = true' \
'backend = systemd' \
'port = ssh' \
'maxretry = 3' \
'bantime = 1h' \
'findtime = 10m' | sudo tee /etc/fail2ban/jail.d/sshd.local > /dev/null
This file enables only the SSH jail, reads SSH login events from the systemd journal, and bans an address for one hour after three failed attempts inside a ten-minute window.
Add your current administration IP address to
ignoreipbefore lowering retry limits on a remote server. Keeping your own trusted IP outside the ban logic helps prevent accidental lockout during testing.
Validate and Restart Fail2Ban
Test the configuration before restarting the service:
sudo fail2ban-client -t
OK: configuration test is successful
Restart Fail2Ban and confirm the SSH jail is active:
sudo systemctl restart fail2ban
sudo fail2ban-client status
Status |- Number of jail: 1 `- Jail list: sshd
Inspect the SSH jail details:
sudo fail2ban-client status sshd
Relevant output on Rocky Linux 10 and 9 includes the journal match used by the packaged SSH filter:
Status for the jail: sshd |- Filter | |- Currently failed: 0 | |- Total failed: 0 | `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session `- Actions |- Currently banned: 0 |- Total banned: 0 `- Banned IP list:
Rocky Linux 8 normally shows _SYSTEMD_UNIT=sshd.service + _COMM=sshd instead. Both forms are valid package defaults for their release.
Tune Fail2Ban Ban Settings
The first SSH jail is intentionally conservative. Adjust the following values in /etc/fail2ban/jail.d/sshd.local after you confirm the service is catching the right events.
Set Fixed Ban Durations
The bantime value accepts readable time units. These examples show common formats:
bantime = 10m
bantime = 1h
bantime = 1d
bantime = -1
The final value, -1, creates a permanent ban until you manually unban the IP address. Use permanent bans carefully on services where legitimate users can mistype passwords or change networks.
Increase Ban Times for Repeat Offenders
Incremental bans make repeated abuse more expensive without making every first-time mistake a long outage:
bantime.increment = true
bantime.multipliers = 1 2 4 8 16 32 64
With bantime = 10m, these multipliers ban the same IP for 10 minutes, then 20 minutes, then 40 minutes, and so on when the IP keeps returning.
Allow Trusted IP Addresses
Add trusted administration networks or monitoring addresses to ignoreip so Fail2Ban never blocks them:
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 203.0.113.50
The example keeps localhost, IPv6 loopback, one private LAN, and one documentation-range public address outside Fail2Ban bans. Replace the public address with your real static administration IP if you have one.
After tuning, validate and reload the configuration without clearing current bans:
sudo fail2ban-client -t
sudo fail2ban-client reload
Add Web Server or Mail Jails
Fail2Ban ships filters for common web and mail services, but those jails should only be enabled on servers that actually run the matching service and write the expected logs. Enabling a jail without its log source produces startup errors instead of protection.
Protect Apache Logins
Use Apache jails only on systems that have Apache logs under /var/log/httpd/:
[apache-auth]
enabled = true
port = http,https
logpath = %(apache_error_log)s
maxretry = 3
bantime = 1h
[apache-badbots]
enabled = true
port = http,https
logpath = %(apache_access_log)s
maxretry = 2
bantime = 48h
Protect Nginx Logins and Bot Searches
If you run Nginx on Rocky Linux, enable Nginx jails only after the relevant access and error logs exist:
[nginx-http-auth]
enabled = true
port = http,https
logpath = %(nginx_error_log)s
maxretry = 3
bantime = 1h
[nginx-botsearch]
enabled = true
port = http,https
logpath = %(nginx_access_log)s
maxretry = 2
bantime = 2h
Protect Postfix or Dovecot Authentication
For mail servers, keep the jail names aligned with the packaged definitions and use the systemd backend when the service logs to the journal:
[postfix]
enabled = true
backend = systemd
port = smtp,submission,submissions
maxretry = 3
bantime = 1h
[dovecot]
enabled = true
backend = systemd
port = imap,imaps,pop3,pop3s
maxretry = 5
bantime = 1h
Validate the configuration after adding any service jail:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
Check Fail2Ban Status and Manage Bans
The fail2ban-client command is the normal control tool for jail status, manual bans, unbans, and reloads.
List Active Jails
Show all active jails:
sudo fail2ban-client status
Status |- Number of jail: 1 `- Jail list: sshd
Show Banned IPs for a Jail
View current and total bans for SSH:
sudo fail2ban-client status sshd
The Banned IP list line is empty until the jail blocks an address.
Ban and Unban One IP Address
Manually ban a documentation-range test address in the SSH jail:
sudo fail2ban-client set sshd banip 203.0.113.7
1
The 1 means Fail2Ban accepted one ban action. Remove the test ban afterward:
sudo fail2ban-client set sshd unbanip 203.0.113.7
Unban Every Active Ban
Use the global unban command only when you intentionally want to clear every jail:
sudo fail2ban-client unban --all
For normal account recovery, unban the one affected address instead of clearing all active bans.
Reload Fail2Ban Without Clearing Bans
Reload after minor jail changes when you want to keep current ban state:
sudo fail2ban-client reload
Use systemctl restart fail2ban for service-level changes or recovery from a failed state; use fail2ban-client reload for normal jail edits.
Verify Firewalld Blocking
Rocky Linux uses firewalld by default, and the EPEL Fail2Ban package integrates with it through firewallcmd-rich-rules. A quick manual ban proves that Fail2Ban can create the expected firewall rule.
Check that firewalld is running:
sudo firewall-cmd --state
running
Ban a test IP and list rich rules:
sudo fail2ban-client set sshd banip 203.0.113.7
sudo firewall-cmd --list-rich-rules
Relevant output includes the Fail2Ban-created rich rule:
rule family="ipv4" source address="203.0.113.7" port port="ssh" protocol="tcp" reject type="icmp-port-unreachable"
Remove the test ban:
sudo fail2ban-client set sshd unbanip 203.0.113.7
Review the active firewalld zone if a ban appears in Fail2Ban but traffic still reaches the service:
sudo firewall-cmd --list-all
The zone output is host-specific. Confirm that your SSH service or custom SSH port is allowed for normal access, then check whether Fail2Ban rich rules appear after a ban.
Monitor Fail2Ban Logs
Fail2Ban writes its own activity log to /var/log/fail2ban.log. Use it to review service starts, ban events, unban events, and filter errors. The tail command examples are useful when you need more log-following patterns.
Show the last 20 log lines:
sudo tail -n 20 /var/log/fail2ban.log
Follow the log until you press Ctrl+C:
sudo tail -f /var/log/fail2ban.log
Search for ban events, one IP address, or SSH jail entries with grep command examples:
sudo grep "Ban" /var/log/fail2ban.log
sudo grep "203.0.113.7" /var/log/fail2ban.log
sudo grep "sshd" /var/log/fail2ban.log
Configure Optional Email Alerts
Fail2Ban can send mail when bans occur, but delivery depends on a working local mail transfer agent or relay. The package install includes the Fail2Ban sendmail action; this section adds Postfix, the mail command, and whois lookups for the richer mail action.
Install and start Postfix, then add s-nail for the mail command and whois for sender reports:
sudo dnf install -y postfix s-nail whois
sudo systemctl enable --now postfix
Rocky Linux 10 and 9 provide s-nail from AppStream. Rocky Linux 8 provides s-nail through EPEL, which is already enabled for the Fail2Ban package.
Add these notification settings to the existing [DEFAULT] block in your local Fail2Ban override. If you use a separate site-wide file such as /etc/fail2ban/jail.local, include the section header once.
[DEFAULT]
destemail = admin@example.com
sender = fail2ban@example.com
action = %(action_mwl)s
The action_mwl action sends a message with whois information and relevant log lines. Validate and reload Fail2Ban so the notification action is active:
sudo fail2ban-client -t
sudo fail2ban-client reload
Send a local test message to confirm the mail path works before you wait for a real ban:
echo "Test email from Fail2Ban server" | mail -s "Fail2Ban Test" admin@example.com
Troubleshoot Fail2Ban on Rocky Linux
Use these checks when the package installs but jails do not start, bans do not appear, or the firewall does not block traffic.
Fail2Ban Client Cannot Reach the Socket
If you run a client command immediately after starting the service, you may see this error before the socket is ready:
ERROR Failed to access socket path: /var/run/fail2ban/fail2ban.sock. Is fail2ban running?
Wait a moment, then check the service and socket again:
systemctl is-active fail2ban
sudo fail2ban-client ping
If the ping still fails, inspect the unit log before restarting:
sudo journalctl -u fail2ban -n 30 --no-pager
sudo systemctl restart fail2ban
SSH Jail Is Not Listed
If sudo fail2ban-client status does not list sshd, validate the configuration and check the Fail2Ban logs:
sudo fail2ban-client -t
sudo journalctl -u fail2ban -n 30 --no-pager
Fix the reported file, jail name, or option, then restart Fail2Ban and check the jail list again:
sudo systemctl restart fail2ban
sudo fail2ban-client status
Filter Matches Nothing
When a jail is active but never bans, test the SSH filter against a known failed-login log shape:
printf 'May 16 12:00:00 host sshd[123]: Failed password for invalid user test from 203.0.113.8 port 4242 ssh2\n' > /tmp/sshd-filter-test.log
fail2ban-regex -v /tmp/sshd-filter-test.log /etc/fail2ban/filter.d/sshd.conf
Relevant output should show the documentation IP as a matched host:
Failregex: 1 total | 203.0.113.8 Sat May 16 12:00:00 2026 Lines: 1 lines, 0 ignored, 1 matched, 0 missed
rm -f /tmp/sshd-filter-test.log
For real journal data, copy the Journal matches value from sudo fail2ban-client status sshd and pass it with -m:
sudo fail2ban-regex -v -m "_SYSTEMD_UNIT=sshd.service + _COMM=sshd + _COMM=sshd-session" systemd-journal /etc/fail2ban/filter.d/sshd.conf
Rocky Linux 8 usually omits + _COMM=sshd-session from the journal match. Use the value printed by your jail status instead of forcing the Rocky Linux 10 or 9 example.
Web Jail Reports Missing Log Files
A web jail fails when its configured log path does not exist. Check the service log and the expected directory:
sudo journalctl -u fail2ban -n 30 --no-pager
sudo ls -ld /var/log/httpd /var/log/nginx 2>/dev/null
Install or start the matching web server first, or disable the jail until its log files exist. For Nginx, confirm the active package source and log path before enabling the jail.
Bans Do Not Block Traffic
If Fail2Ban shows a banned IP but the connection still works, check firewalld first:
sudo systemctl is-active firewalld
sudo firewall-cmd --list-rich-rules
Start firewalld if it is inactive, then restart Fail2Ban so the firewalld action reconnects cleanly:
sudo systemctl enable --now firewalld
sudo systemctl restart fail2ban
Remove Fail2Ban from Rocky Linux
Remove Fail2Ban with DNF when you no longer need automatic bans. This stops and removes the service packages while leaving EPEL alone for other packages that may depend on it.
sudo systemctl disable --now fail2ban
sudo dnf remove fail2ban fail2ban-server fail2ban-firewalld fail2ban-sendmail fail2ban-selinux
Verify that the main package is gone:
if rpm -q fail2ban >/dev/null 2>&1; then
echo "Fail2Ban is still installed"
else
echo "Fail2Ban is not installed"
fi
Fail2Ban is not installed
If you added optional email alerts only for Fail2Ban, remove those mail packages separately. Keep them when Postfix already handles other system mail.
sudo systemctl disable --now postfix
sudo dnf remove postfix s-nail whois
Remove EPEL only when Fail2Ban and any optional EPEL-only mail packages were the only reason you enabled it:
sudo dnf remove epel-release
dnf repolist --enabled | grep '^epel' || echo "EPEL is not enabled"
The next cleanup commands permanently delete Fail2Ban configuration, database, and log files, including custom jail files under
/etc/fail2ban/. Back up anything you may need before removing these paths.
sudo rm -rf /etc/fail2ban /var/lib/fail2ban
sudo rm -f /var/log/fail2ban.log*
Confirm the local paths are absent:
test ! -e /etc/fail2ban && test ! -e /var/lib/fail2ban && echo "Fail2Ban configuration and database paths are removed"
Conclusion
Fail2Ban is running on Rocky Linux with an SSH jail that reads the systemd journal and blocks offenders through firewalld rich rules. Keep an eye on fail2ban-client status sshd and the Fail2Ban log as traffic changes, then tighten SSH further with Rocky Linux SSH configuration when password login no longer needs to stay exposed.


Formatting tips for your comment
You can use basic HTML to format your comment. Useful tags currently allowed in published comments:
<code>command</code>command<strong>bold</strong><em>italic</em><blockquote>quote</blockquote>