How to Configure Fail2Ban to Protect SSH on RHEL 7
Even with SSH key-based authentication enabled, your server’s port 22 (or whatever port SSH is listening on) is constantly targeted by automated bots scanning the internet for open SSH services. These bots attempt thousands of login combinations per hour. While they cannot succeed against key-only authentication, the log noise and the minor CPU/network overhead of handling rejected connections adds up. Fail2Ban is a log-monitoring daemon that watches authentication logs in real time and automatically bans IP addresses that show signs of malicious behaviour — typically multiple failed login attempts within a defined time window. This tutorial walks through installing Fail2Ban from the EPEL repository on RHEL 7, configuring an SSH jail, and using the management client to inspect and manage bans.
Prerequisites
- RHEL 7 system with root or
sudoaccess - SSH configured and running (see the SSH hardening tutorial)
- Active Red Hat subscription for base repositories
- Firewall managed by
firewalld(Fail2Ban’sfirewallcmd-ipsetaction integrates natively)
Step 1: Enable the EPEL Repository
Fail2Ban is not available in the standard RHEL 7 repositories. It is distributed through the Extra Packages for Enterprise Linux (EPEL) repository, maintained by the Fedora project. Install the EPEL release package first:
sudo yum install -y epel-release
Verify that the EPEL repository is now enabled:
yum repolist | grep epel
You should see a line like epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 with a package count. If EPEL does not appear, you may need to install it directly from the Fedora project:
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
Step 2: Install Fail2Ban
With EPEL enabled, install Fail2Ban and the optional firewalld integration component:
sudo yum install -y fail2ban fail2ban-firewalld
The fail2ban-firewalld package provides action scripts that use firewall-cmd to apply and remove bans, which integrates cleanly with the firewalld zones already in place on your server.
After installation, enable and start the Fail2Ban service:
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
Step 3: Understand the Configuration Structure
Fail2Ban separates its configuration into two layers to make upgrades safe:
- /etc/fail2ban/jail.conf — the upstream default configuration. Do not edit this file. It is overwritten on package upgrades.
- /etc/fail2ban/jail.local — your local overrides. This file does not exist by default; you create it. Settings here take precedence over
jail.conf.
Similarly, filter definitions live in /etc/fail2ban/filter.d/ and action definitions in /etc/fail2ban/action.d/. Default filters ship with the package; custom ones should be placed in these directories with .local variants.
Step 4: Create the jail.local Configuration
Create your local configuration file:
sudo vi /etc/fail2ban/jail.local
Add the following content. The [DEFAULT] section sets global values that apply to all jails unless overridden:
[DEFAULT]
# IP addresses and CIDR ranges to never ban (whitelist):
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
# How long (in seconds) a banned IP is blocked (3600 = 1 hour):
bantime = 3600
# The time window (in seconds) within which failed attempts are counted:
findtime = 600
# Number of failures before an IP is banned:
maxretry = 5
# Use firewalld for ban/unban actions:
banaction = firewallcmd-ipset
banaction_allports = firewallcmd-allports
# Send email alerts on ban events (optional; requires a local MTA):
# action = %(action_mwl)s
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 3
bantime = 86400
findtime = 600
Key settings explained:
- ignoreip — a space-separated list of IPs and subnets that will never be banned. Always include your own management IP or subnet here to avoid locking yourself out.
- bantime — how long a ban lasts in seconds. The
[sshd]jail overrides the default with 86400 seconds (24 hours) for more aggressive protection. - findtime — the sliding time window in which
maxretryfailures trigger a ban. - maxretry — number of failures allowed before a ban is issued. The
[sshd]jail uses 3 to be very strict. - logpath — on RHEL 7, SSH authentication failures are logged to
/var/log/secure. - filter — the filter definition in
/etc/fail2ban/filter.d/sshd.confthat defines the log patterns to match.
If you changed the SSH port to something other than 22, update the port line:
port = 2222
After saving, restart Fail2Ban to apply the configuration:
sudo systemctl restart fail2ban
Step 5: Verify the SSH Jail Is Running
Use the fail2ban-client command to interact with the running daemon:
# Check the overall status of all jails:
sudo fail2ban-client status
# Check the status of the sshd jail specifically:
sudo fail2ban-client status sshd
Example output from the sshd jail status:
Status for the jail: sshd
|- Filter
| |- Currently failed: 2
| |- Total failed: 47
| `- Journal matches: _SYSTEMD_UNIT=sshd.service + _COMM=sshd
`- Actions
|- Currently banned: 1
|- Total banned: 5
`- Banned IP list: 203.0.113.42
The output shows how many IPs are currently banned, total historical bans, and the list of currently banned addresses.
Step 6: Manually Banning and Unbanning IPs
You can manually manage bans with fail2ban-client without editing configuration files.
Manually ban an IP address in the sshd jail:
sudo fail2ban-client set sshd banip 203.0.113.99
Unban an IP address:
sudo fail2ban-client set sshd unbanip 203.0.113.42
Unban all IPs across all jails:
sudo fail2ban-client unban --all
Step 7: Viewing Banned IPs via firewall-cmd
Because the firewallcmd-ipset action adds bans to a firewalld IP set, you can also inspect active bans through firewall-cmd:
# List all IP sets managed by firewalld:
sudo firewall-cmd --get-ipsets
# View the contents of the fail2ban-sshd set:
sudo firewall-cmd --ipset=fail2ban-sshd --get-entries
Step 8: Viewing Fail2Ban Logs
Fail2Ban writes its own log to /var/log/fail2ban.log. This is the best place to see ban and unban events:
sudo tail -f /var/log/fail2ban.log
Example log entries showing a ban event:
2026-05-17 14:22:01,453 fail2ban.filter [1234]: INFO [sshd] Found 203.0.113.42 - 2026-05-17 14:22:01
2026-05-17 14:22:11,571 fail2ban.filter [1234]: INFO [sshd] Found 203.0.113.42 - 2026-05-17 14:22:11
2026-05-17 14:22:21,693 fail2ban.filter [1234]: INFO [sshd] Found 203.0.113.42 - 2026-05-17 14:22:21
2026-05-17 14:22:21,901 fail2ban.actions [1234]: NOTICE [sshd] Ban 203.0.113.42
You can also search the system authentication log directly to see what failed logins look like before they trigger a ban:
sudo grep "Failed password" /var/log/secure | tail -20
sudo grep "Invalid user" /var/log/secure | tail -20
Step 9: Whitelisting Your Management IPs
The most important safety step when using Fail2Ban is ensuring your own management IP addresses are in the ignoreip whitelist. If you accidentally trigger the ban threshold from your own IP (for example, by mistyping your key passphrase multiple times), you will lock yourself out of the server.
Edit /etc/fail2ban/jail.local and update the ignoreip line with your static IP, your office network range, and any VPN egress IPs:
ignoreip = 127.0.0.1/8 ::1 203.0.113.5 192.168.10.0/24 10.8.0.0/16
Restart Fail2Ban after making changes:
sudo systemctl restart fail2ban
Fail2Ban is a lightweight but highly effective addition to your RHEL 7 server’s security posture. Combined with SSH key-based authentication and firewall rules, it creates multiple overlapping layers of defence against unauthorised access. The key to running it safely is keeping your own IPs in the whitelist, setting a reasonable bantime that discourages attackers without permanently blocking legitimate users, and periodically reviewing the ban log to understand the threat landscape your server faces. Once deployed, Fail2Ban largely manages itself — quietly blocking thousands of attacks in the background while you focus on running your applications.