Connecting to a server through SSH is very secure, but the SSH daemon itself must be exposed to the internet in order to work. Any service exposed publicly becomes a natural target for attackers. If you spend time reading server logs, you will quickly notice repeated login attempts against SSH. WordPress, because of its popularity, is targeted in the same way every day.
Fail2ban is a Linux service that watches application logs, identifies brute-force behavior, and then automatically updates firewall rules to block the attacking IP addresses. Once it is configured properly, the whole process becomes largely automatic. This article uses CentOS 7 to explain how to install and use it.
Install Fail2ban on CentOS 7
Fail2ban is not included in the default CentOS repositories. It is provided through the EPEL project, so the first step is to enable the EPEL repository.
sudo yum install epel-release
After that, install the Fail2ban package itself:
sudo yum install fail2ban
Once the installation finishes, enable the Fail2ban service with systemd:
sudo systemctl enable fail2ban
Customize Fail2ban settings
Fail2ban stores its configuration files in /etc/fail2ban. There is a default configuration file named jail.conf, but that file can be overwritten by package upgrades, so it should not be edited directly. Instead, create a custom file named jail.local. Values defined there override the defaults from jail.conf.
There is one more layer to be aware of. Service-specific configuration files in /etc/fail2ban/jail.d/ can also override values from the main files. The precedence is roughly:
/etc/fail2ban/jail.conf/etc/fail2ban/jail.d/*.conf, in alphabetical order/etc/fail2ban/jail.local/etc/fail2ban/jail.d/*.local, in alphabetical order
Any of those files can contain a [DEFAULT] section, followed by jail-specific sections for individual services.
To create a simple local configuration, open a new file like this:
sudo vi /etc/fail2ban/jail.local
Then paste something like the following:
[DEFAULT]
# Ban hosts for one hour:
bantime = 3600
# Override /etc/fail2ban/jail.d/00-firewalld.conf:
banaction = iptables-multiport
[sshd]
enabled = true
This small configuration changes three things: it sets a new default ban duration, tells Fail2ban to use iptables as the ban action, and enables the SSH jail. After saving the file, restart the service:
sudo systemctl restart fail2ban
If the restart succeeds, it usually produces no output.
Other useful Fail2ban settings
You may still want to adjust other parameters. Open jail.conf to inspect the defaults, but copy any values you want to change into jail.local instead of editing the default file directly.
sudo vi /etc/fail2ban/jail.conf
Default jail settings
The [DEFAULT] section contains the core settings that many jails inherit.
ignoreip = 127.0.0.1/8
This tells Fail2ban to ignore traffic from the local machine. Additional IPs can be appended here, separated by spaces, if you want to exempt other trusted addresses.
bantime = 600
The bantime value controls how long an IP remains blocked, in seconds. The default is 600 seconds, or 10 minutes.
findtime = 600
maxretry = 3
These two settings define when an IP should be banned. maxretry sets how many failures are allowed inside the findtime window before the IP is blocked.
destemail = root@localhost
sendername = Fail2Ban
mta = sendmail
If you want email alerts, these settings control the notification address, the visible sender name, and the mail transport agent used to send the alert.
action = %(action_)s
This determines what action Fail2ban takes once an IP qualifies for a ban. By default it manipulates firewall rules to reject traffic until the ban period ends.
Other jail-specific settings
After the [DEFAULT] section, the configuration defines individual jails for specific services. They usually include a port and a log path. For SSH, the relevant section looks like this:
[sshd]
port = ssh
logpath = %(sshd_log)s
In some cases a jail also needs a custom filter definition that tells Fail2ban what failure pattern to match in the logs. Those filter files live in /etc/fail2ban/filter.d. The WordPress example below uses exactly that mechanism.
To see which filters are already available, list that directory:
ls /etc/fail2ban/filter.d
If you find a filter that matches a service you are already using, you can enable it in jail.local. For example, if Nginx is in use:
[DEFAULT]
# Ban hosts for one hour:
bantime = 3600
# Override /etc/fail2ban/jail.d/00-firewalld.conf:
banaction = iptables-multiport
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
Then restart Fail2ban again:
sudo systemctl restart fail2ban
Check Fail2ban status and firewall rules
After the setup is in place, it is important to confirm that the service is working as expected. The fail2ban-client command can show overall service status or the state of a particular jail:
sudo fail2ban-client status
sudo fail2ban-client status jail_name
You can also inspect the active iptables rules to see which addresses Fail2ban has blocked:
sudo iptables -L
Use Fail2ban to block WordPress brute-force attacks
If the WordPress site has access logs enabled, Fail2ban can also monitor those logs and block repeated brute-force attempts against wp-login.php. In many cases, repeated POST requests to that endpoint are a strong sign of a brute-force attack.
Create a filter file named wordpress.conf in /etc/fail2ban/filter.d/ with content like this:
# WP brute force attacks filter
[Definition]
failregex =.*-.*-.*POST.*/wp-login$
ignoreregex =
Then add a matching jail to jail.local, adjusting logpath to the real web-server log path on your system:
[wordpress]
enabled = true
filter = wordpress
logpath = /home/wwwlogs/*.log
maxretry = 3
port = http,https
CentOS 7 uses firewalld by default instead of plain iptables, and in some environments Fail2ban cannot update iptables rules as expected while firewalld is active. In that case, stop and mask firewalld first:
systemctl stop firewalld
systemctl mask firewalld
Unban an IP address that was blocked by mistake
If one of your own IPs gets blocked accidentally, you can unban it with a command like this:
fail2ban-client set wordpress unbanip 8.8.8.8
Add an IP address to the whitelist
If a particular address needs to log in frequently, you can whitelist it to avoid triggering the ban rules unnecessarily:
fail2ban-client set wordpress addignoreip 8.8.8.8 # Add IP to whitelist
fail2ban-client set wordpress delignoreip 8.8.8.8 # Remove IP from whitelist
With these settings in place, the server can block a large share of routine brute-force traffic automatically. Even so, basic habits still matter: use strong passwords, store them carefully, and treat security as an ongoing practice rather than a one-time configuration task.
