Installing and Configuring Fail2ban to Protect SSH on RHEL
Brute-force attacks on SSH are constant, and Australia is no exception. The Australian Cyber Security Centre's Essential Eight calls for limiting administrator access and detecting attacks on internet-facing services, which is what Fail2ban does. Whether your server sits in a Sydney data centre or a cloud region in Melbourne, the threat is the same: relentless credential guessing.
Fail2ban scans log files for repeated authentication failures and triggers a firewall rule to block the offending IP. It is lightweight, written in Python, and runs on RHEL, CentOS Stream, and Fedora without exotic dependencies. The default SSH jail reads /var/log/secure, applies a regex, and bans hosts that exceed the retry threshold.
This guide walks through a practical install on RHEL-based distributions, from the EPEL repository to a working jail.local. The commands below are tested on RHEL 9, CentOS Stream 9, and Fedora 39 or later, and they should work on older releases with minimal changes.
We will also verify the service, unban legitimate addresses, and apply Australian-specific hardening. By the end, you will have a tailored configuration that survives package upgrades and integrates with the local firewalld zone.
Prerequisites and Base System Preparation
Before installing anything, confirm the host is up to date and SSH is running. On RHEL and CentOS Stream, run sudo dnf update -y; on Fedora the command is the same. Verify the OpenSSH daemon with systemctl status sshd and check from another terminal that you can reach it, so you do not lock yourself out.
You need the EPEL repository on RHEL and CentOS, because Fail2ban lives there. Install it with sudo dnf install epel-release -y and enable CodeReady Linux Builder on RHEL 9; Fedora users can skip this step. Confirm your firewall uses firewalld with sudo firewall-cmd --state. If behind a Telstra Business-grade link in Adelaide, ensure the SSH service is in the public zone.
Installing the Package
Install Fail2ban and optional mail dependencies if you want email alerts. On RHEL 9 and CentOS Stream, run sudo dnf install fail2ban fail2ban-firewalld fail2ban-systemd -y. On Fedora, sudo dnf install fail2ban is usually enough because firewalld and systemd are already in place.
Enable and start the daemon with sudo systemctl enable --now fail2ban.service. The included jail.conf is a template, and the recommended pattern in Australian enterprise estates is to leave it untouched and create a jail.local override so future package upgrades do not clobber your customisations. Verify the version with fail2ban-client -V; on a fresh install no jails are active yet.
Building a Local jail.local Override
Run sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local and open the new file. Set backend = systemd on RHEL 9 and CentOS Stream 9 where journald is the primary log source, or leave it as auto for a hands-off configuration.
Adjust the global defaults near the top: bantime is the ban duration, findtime is the failure-counting window, and maxretry is the threshold. A reasonable starting point is bantime = 1h, findtime = 10m, and maxretry = 5. The ACSC recommends shorter findtime values, and you can lower the threshold to three with key-based authentication.
For persistent ban storage across restarts, use a database backend. The walkthrough for installing and configuring mariadb on fedora covers the database setup, after which you can set dbfile = /var/lib/fail2ban/fail2ban.sqlite3 or point Fail2ban at a remote MariaDB instance using dbpurgeage to retire old records.
| Distribution | Config Path | Log File | Service |
|---|---|---|---|
| RHEL 9 | /etc/fail2ban | /var/log/secure | systemd |
| CentOS Stream 9 | /etc/fail2ban | /var/log/secure | systemd |
| Fedora 39+ | /etc/fail2ban | /var/log/secure | systemd |
| RHEL 7 (legacy) | /etc/fail2ban | /var/log/secure | systemd |
Enabling the SSH Jail and Verifying Behaviour
With jail.local in place, add a dedicated section for the SSH jail:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/secure
maxretry = 4
findtime = 10m
bantime = 1h
Save the file and restart Fail2ban with sudo systemctl restart fail2ban.service, then confirm the jail with sudo fail2ban-client status sshd. To prove it works, mistype the SSH password three or four times from another machine on a different network; after the threshold is reached, your test IP should appear under "Banned IP list."
To avoid banning a colleague in the Brisbane office while testing, whitelist your home address with ignoreip = 203.0.113.42/32 in the global section of jail.local. You can confirm the log scanner is not overloading the disk by following the how to monitor disk i/o with iostat and iotop walkthrough.
Managing Bans, Filters and Maintenance
Day to day, you will interact with Fail2ban through fail2ban-client. To unban an address, run sudo fail2ban-client set sshd unbanip 203.0.113.42. To tail the log, use sudo tail -f /var/log/fail2ban.log. The default recidive jail, which bans repeat offenders for a longer period, can be enabled by setting enabled = true under its section in jail.local.
If you run a mixed fleet, a lightweight developer project hub can receive parsed log lines, giving your operations team a single dashboard across data centres in Sydney, Melbourne, and Perth. Organisations under the Notifiable Data Breaches scheme should retain at least 90 days of history, since ban events help when reporting to the Office of the Australian Information Commissioner.
Hardening SSH Beyond Fail2ban
Fail2ban is one layer in a defence-in-depth strategy. The single most effective change is to disable password authentication and require SSH keys. Edit /etc/ssh/sshd_config, set PasswordAuthentication no, PermitRootLogin no, and ChallengeResponseAuthentication no, then sudo systemctl restart sshd. Moving SSH off port 22 reduces drive-by scanning but only delays attackers; Fail2ban still works on a non-standard port as long as the jail's port directive matches.
Align with the Essential Eight maturity level your organisation targets. A practical next step is to schedule a weekly cron job that runs sudo fail2ban-client status sshd and emails the output to your security distribution list, then verify the report arrives before your Monday stand-up in Sydney.