Type something to search...
How to install and configure Fail2Ban?

How to install and configure Fail2Ban?

To install and configure Fail2Ban, install the package (sudo apt install fail2ban on Ubuntu and Debian, or sudo dnf install fail2ban from EPEL on RHEL-based systems), create a /etc/fail2ban/jail.local file with your default ban settings, enable the jails for the services you want to protect such as sshd, then start the service and check it with sudo fail2ban-client status. Fail2Ban then watches your logs and temporarily blocks IP addresses that show repeated failed logins or other abusive behaviour.

Fail2Ban is a small, reliable tool that adds an automatic defence layer to any Linux server. It won't replace strong authentication, but it cuts down brute-force noise, saves server resources, and slows attackers down. This guide covers installation, the configuration file structure, protecting SSH, Nginx, Apache, and WordPress logins, writing a custom filter, and managing bans day to day.

How Fail2Ban Works

Fail2Ban has three main building blocks:

  1. Filters: Regular expressions that recognise bad log lines, such as "Failed password for root from 198.51.100.23".
  2. Actions: What to do when a filter matches too often, usually adding a firewall rule to block the IP.
  3. Jails: A jail ties a filter and an action together for a specific log source, with settings for how many failures are allowed and how long a ban lasts.

The key settings in every jail are:

  • maxretry: How many failures are allowed.
  • findtime: The time window in which those failures are counted.
  • bantime: How long the IP stays banned.

For example, with maxretry = 5, findtime = 10m, and bantime = 1h, an IP that fails five times within ten minutes is blocked for an hour.

Step 1: Install Fail2Ban

Ubuntu and Debian

sudo apt update
sudo apt install fail2ban

Rocky Linux, AlmaLinux, and RHEL

Fail2Ban is in the EPEL repository:

sudo dnf install epel-release
sudo dnf install fail2ban

Enable and start it:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban

Step 2: Understand the Configuration Files

Fail2Ban's configuration lives in /etc/fail2ban/:

  • jail.conf: The default settings shipped with the package. Don't edit this file, because updates can overwrite it.
  • jail.local: Your overrides. Settings here take precedence over jail.conf.
  • jail.d/: A folder for additional .conf or .local files, handy for keeping each jail in its own file.
  • filter.d/: Filter definitions for many services.
  • action.d/: Action definitions, including firewall integrations.

On Debian and Ubuntu, a file named jail.d/defaults-debian.conf may already enable the sshd jail. Check what's there:

ls /etc/fail2ban/jail.d/

Step 3: Create jail.local

Create your main override file:

sudo nano /etc/fail2ban/jail.local

A good starting point:

[DEFAULT]
# Never ban these addresses. Add your own static IP if you have one.
ignoreip = 127.0.0.1/8 ::1

# Ban for 1 hour after 5 failures within 10 minutes.
bantime  = 1h
findtime = 10m
maxretry = 5

# Read logs from the systemd journal where supported.
backend = systemd

# Increase ban time for repeat offenders.
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 1w

[sshd]
enabled = true

A few notes:

  • ignoreip: Add your own static IP (for example 203.0.113.10) so you never ban yourself. Separate multiple entries with spaces.
  • backend = systemd: On current Ubuntu and Debian releases, SSH logs go to the systemd journal, and on recent Debian there may be no /var/log/auth.log at all. The systemd backend reads the journal directly. You may need the python3-systemd package installed for this backend.
  • bantime.increment: Each repeat ban for the same IP gets longer, up to bantime.maxtime.

Step 4: Choose the Right Ban Action

By default, Fail2Ban uses iptables-based actions. Match the action to the firewall you actually use.

With UFW (Ubuntu and Debian), add this to the [DEFAULT] section:

banaction = ufw
banaction_allports = ufw

With firewalld (RHEL-based systems):

banaction = firewallcmd-rich-rules
banaction_allports = firewallcmd-allports

With nftables directly:

banaction = nftables-multiport
banaction_allports = nftables-allports

Recent Fail2Ban packages on some distributions already default to nftables. Check your installed jail.conf if you're unsure.

Step 5: Restart and Check

After any change, test the configuration and restart:

sudo fail2ban-client -t
sudo systemctl restart fail2ban

Check overall status and the SSH jail:

sudo fail2ban-client status
sudo fail2ban-client status sshd

The output shows how many failures were detected, how many IPs are currently banned, and the list of banned addresses.

Protecting SSH

The sshd jail is the most common use. If you run SSH on a custom port, tell the jail:

[sshd]
enabled = true
port    = 2222

Remember that Fail2Ban is a supplement to good SSH security, not a replacement. Key-only authentication and disabled root login remain the most important protections.

For more aggressive SSH protection, Fail2Ban's sshd filter supports modes:

[sshd]
enabled = true
mode    = aggressive

Aggressive mode also catches things like connections that disconnect before authenticating, which many scanners do.

Protecting Nginx

Fail2Ban includes several Nginx filters. Web server logs are written to files, so these jails use the auto backend with a log path.

Block Repeated Basic Auth Failures

If you protect an area with HTTP Basic Authentication:

[nginx-http-auth]
enabled  = true
port     = http,https
backend  = auto
logpath  = /var/log/nginx/error.log

Block Bots Probing for Scripts

The nginx-botsearch filter catches requests for common exploit paths that return 404:

[nginx-botsearch]
enabled  = true
port     = http,https
backend  = auto
logpath  = /var/log/nginx/access.log
maxretry = 3

Work With Nginx Rate Limiting

If you use Nginx's limit_req module, the nginx-limit-req filter bans IPs that repeatedly hit the limit:

[nginx-limit-req]
enabled  = true
port     = http,https
backend  = auto
logpath  = /var/log/nginx/error.log
maxretry = 10

Protecting Apache

Apache has similar filters:

[apache-auth]
enabled = true
port    = http,https
backend = auto
logpath = /var/log/apache2/error.log

[apache-badbots]
enabled  = true
port     = http,https
backend  = auto
logpath  = /var/log/apache2/access.log
maxretry = 1

On RHEL-based systems, Apache logs are in /var/log/httpd/ instead of /var/log/apache2/.

Protecting WordPress Logins With a Custom Filter

Fail2Ban doesn't ship a WordPress filter, but you can create one that catches repeated POST requests to wp-login.php and xmlrpc.php in your web server's access log.

Create /etc/fail2ban/filter.d/wordpress-login.conf:

[Definition]
failregex = ^<HOST> -.*"POST /wp-login\.php
            ^<HOST> -.*"POST /xmlrpc\.php
ignoreregex =

This matches the standard combined log format used by Nginx and Apache, where the client IP comes first. <HOST> is Fail2Ban's placeholder for the IP address.

Then add a jail in /etc/fail2ban/jail.d/wordpress.local:

[wordpress-login]
enabled  = true
port     = http,https
filter   = wordpress-login
backend  = auto
logpath  = /var/log/nginx/access.log
maxretry = 6
findtime = 5m
bantime  = 1h

Because this counts every POST to the login page, successful logins count too. A maxretry of 6 in 5 minutes is generous for real users while stopping bots. If your site is behind a CDN or proxy like Cloudflare, the log will show the proxy's IP unless you configure your web server to log the real client IP, so set that up first or you might ban the proxy.

Test the Filter

Before enabling a jail, check that your filter matches the log lines you expect:

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/wordpress-login.conf

The output shows how many lines matched. If it's zero, your log format may differ from the regex.

Security plugins like Wordfence or Limit Login Attempts Reloaded can do something similar inside WordPress. Using Fail2Ban has the advantage of blocking at the firewall, before PHP even runs. The WP fail2ban plugin is another option: it writes WordPress authentication events to the system log so Fail2Ban can act on real failed logins rather than all POST requests.

Managing Bans

See Who's Banned

sudo fail2ban-client status sshd
sudo fail2ban-client banned

Unban an IP

If you or a colleague get banned:

sudo fail2ban-client set sshd unbanip 203.0.113.10

To unban an IP from every jail:

sudo fail2ban-client unban 203.0.113.10

Ban an IP Manually

sudo fail2ban-client set sshd banip 198.51.100.23

Reload After Changes

sudo fail2ban-client reload

Check Logs

Fail2Ban writes its own log, usually at /var/log/fail2ban.log:

sudo tail -f /var/log/fail2ban.log

Email Alerts

Fail2Ban can send an email when it bans an IP, if your server can send mail. In [DEFAULT]:

destemail = you@example.com
sender    = fail2ban@example.com
action    = %(action_mw)s

action_mw bans the IP and sends an email with whois information. On busy servers, this can generate a lot of mail, so many administrators prefer to review the log or use a monitoring tool instead.

Common Mistakes to Avoid

  • Editing jail.conf: Always use jail.local or files in jail.d/.
  • Wrong backend or log path: If a jail shows zero failures on a server you know is being probed, check that backend and logpath are correct.
  • Banning yourself: Add your static IP to ignoreip, and make sure you know how to reach your provider's console.
  • Mismatched firewall: Use a ban action that matches the firewall you actually run.
  • Banning your proxy: Behind a CDN or load balancer, log the real client IP first.
  • Relying on Fail2Ban alone: It's an extra layer, not a replacement for strong authentication and updates.

FAQ: Fail2Ban

Fail2Ban monitors log files for signs of abuse, such as repeated failed logins, and temporarily blocks the offending IP addresses using your firewall.

It's not strictly required, because key-only SSH can't realistically be brute-forced. Fail2Ban still reduces log noise and resource use, and it can protect other services like web logins.

Put your settings in /etc/fail2ban/jail.local or in separate files inside /etc/fail2ban/jail.d/. Don't edit jail.conf, because package updates can overwrite it.

Log in from another IP or your provider's console and run sudo fail2ban-client set sshd unbanip followed by your IP address. Add your IP to ignoreip to prevent it happening again.

Yes. Set banaction = ufw in the DEFAULT section of jail.local, and Fail2Ban will add and remove UFW rules when it bans and unbans IPs.

Yes. You can create a custom filter that watches your web server logs for repeated POST requests to wp-login.php and xmlrpc.php, or use the WP fail2ban plugin to log real authentication failures.

The most common causes are the wrong backend or log path, or a filter that doesn't match your log format. Use fail2ban-regex to test the filter against your actual log file.


Conclusion

Fail2Ban is quick to install and easy to configure once you understand filters, actions, and jails. Start with a jail.local file that sets sensible defaults, enable the sshd jail, match the ban action to your firewall, and verify everything with fail2ban-client status. From there, add jails for Nginx, Apache, or a custom WordPress filter to protect your web applications too.

Treat Fail2Ban as a helpful extra layer on top of strong authentication, a firewall, and regular updates. Check its log from time to time, keep your own IP in ignoreip, and test new filters with fail2ban-regex before enabling them. Set up this way, it quietly blocks a large share of automated attacks without getting in your way.

Tags :
Share :

Related Posts

What are the best WordPress security plugins?

What are the best WordPress security plugins?

The best WordPress security plugins for most sites are Wordfence, Sucuri Security, Solid Security, MalCare, All-In-One Security (AIOS), Patchstack, a

Dive Deeper
What are the most common website security threats?

What are the most common website security threats?

The most common website security threats are vulnerable or outdated software, weak and stolen passwords, malware infections, injection attacks like S

Dive Deeper
How does GDPR affect website security?

How does GDPR affect website security?

GDPR affects website security by turning it from a good habit into a legal obligation. If your website collects personal data from people in the EU (

Dive Deeper