Web

Fail2ban Setup Guide: Protect Your Server From Brute Force

Talha Aslan 20 min read 3 views

What is fail2ban and how does it protect a server?

Fail2ban is open source software that reads your server log files and temporarily blocks IP addresses that make too many failed login attempts in a short time. It uses a firewall rule to do the blocking. It slows down password guessing bots, but it does not fix a weak password or an exposed service on its own.

We are a digital marketing and web team, not a hosting company. This guide follows the official fail2ban documentation and project files. If you own a website or an online store, you will learn how the decision works. If you manage your own VPS, you will also find the commands step by step.

However, the logic is simple. The service reads the log line by line, counts failed login traces, and keeps the source out for a while once a limit is crossed. When the time ends, the block ends. So a legitimate user who gets blocked by mistake is not locked out for good.

Marketing is affected too. If a site that pays for ads or SEO slows down under heavy login attempts, visitors leave. Also, landing pages open late when server resources run out. That is why infrastructure security, speed and conversion are directly linked. We covered the speed side in our guide on how site speed affects SEO.

How do fail2ban jails, filters and actions work together?

Fail2ban works with three concepts. A jail defines which service to watch, which log file to read and which limits apply. A filter is a set of regular expressions that spots a failed attempt in a log line. An action is the blocking command that runs once the limit is crossed.

  • Jail: the service, the log path and the limits.
  • Filter: failregex defines a failed attempt, and ignoreregex defines lines you want to skip.
  • Action: in most setups it adds a block rule to the firewall.

For example, the file layout mirrors this. Filters live in /etc/fail2ban/filter.d/ and actions live in action.d. You write jail definitions in jail.conf, jail.d and jail.local. The ready-made filters cover most common services, so you rarely need to write one from scratch.

A filter also pulls the attacker's address out of the line. It uses tags such as <HOST> for that. For example, the sshd jail reads the SSH log, matches lines with the sshd filter and then runs the block action.

Which attacks does fail2ban stop, and which does it miss?

Fail2ban works against repeated attempts that reach a log from the same source. SSH password guessing, admin panel logins and HTTP basic authentication failures are typical examples. It has limited effect on attacks that never reach a log or that come from thousands of sources.

SituationFail2ban effectExtra defense
Heavy SSH password guessing from one IPStrongKey based login, password login off
Repeated POST requests to a login page from one IPGood, needs a custom filterTwo step verification
Slow attempts from thousands of IPsWeakApplication layer protection, WAF
Weak or leaked passwordNonePassword policy, password manager
Request that exploits an application bugNoneUpdates, WAF, code fix

The last two rows matter. Many site owners install fail2ban and assume they are safe. However, if an attacker knows the right password, the log shows no failed login. Then fail2ban has nothing to act on.

In short, fail2ban is one security layer, not the whole answer. We cover application level flaws in our OWASP Top 10 guide.

What is the difference between brute force, password spraying and credential stuffing?

People often mix up these three terms, but each one behaves differently against fail2ban. OWASP describes them under authentication attacks. The difference lies in what the attacker tries and how fast.

  • Brute force: the attacker tries many passwords on one account. It is easy to catch from a single source.
  • Password spraying: the attacker tries a few common passwords on many accounts. The failure count per account stays low.
  • Credential stuffing: the attacker tries username and password pairs from another breach.

Fail2ban suits the first type very well. In the other two, the attacker slows down or rotates addresses. So the attacker stays under the limits. For that reason, two step verification and unique passwords are a stronger defense than log based blocking.

What should you check before you install fail2ban?

First, settle five things before you start. Do you have root or sudo access? Can you reach the console from your provider's panel? Which firewall backend runs on the machine? Are the logs in files or in the systemd journal? Does traffic arrive directly, or does it pass through a CDN or reverse proxy?

  1. Write down your own IP address. You can use our IP lookup tool for that.
  2. Test that your provider's console or rescue access works.
  3. Confirm that you can restore your backup. Our website backup strategy guide explains how.
  4. Try the new rule on a test server or in a maintenance window first.

However, console access is the most valuable item on this list. Because if you block yourself over SSH, the provider's panel may be the only way back in. On the other hand, if you write a jail without knowing where the logs live, fail2ban sees nothing and gives you a false sense of safety.

This list may look boring. Still, most people who lock themselves out skipped one of these steps.

How do you install and start fail2ban?

In practice, the package is called fail2ban on most distributions. On the Debian and Ubuntu family, the commands below are enough. On Red Hat based systems the package often comes from an extra repository, so check your own distribution's documentation.

sudo apt update
sudo apt install fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status

The last command lists the running jails. Which jails come enabled after installation depends on the distribution. In the official jail.conf file, jails are off by default, and the file tells you to enable only the ones that fit your setup. So check the list with your own eyes.

Once the service is up, read /var/log/fail2ban.log. The first lines show which jails started. If something is wrong, you usually find the first hint there. Also, do not change settings right after installation. Watch the current state first, then move in small steps.

Why do you edit jail.local instead of jail.conf in fail2ban?

The official documentation says to leave .conf files unchanged. A package update can overwrite them. You put your customizations in .local files instead. Fail2ban also defines the load order clearly.

  1. jail.conf
  2. jail.d/*.conf (in alphabetical order)
  3. jail.local
  4. jail.d/*.local (in alphabetical order)

A later file overrides an earlier one. So you only need to put the lines you want to change into jail.local. Do not copy the whole file. A copy goes stale over time, so it causes odd behavior after updates.

For example, if you only want to change bantime, you write one line. Also, you do not need the headers or comments. After the change, sudo fail2ban-client reload loads the settings again and warns you about errors. Testing the configuration with sudo fail2ban-client -t before you go live is also a good habit.

What do bantime, findtime and maxretry mean?

These three settings are the heart of fail2ban. You can write times in seconds or with short forms such as 10m, 1h and 1d. In the current jail.conf file the defaults are bantime = 10m, findtime = 10m and maxretry = 5.

  • bantime: how long a block lasts.
  • findtime: the time window in which failures count.
  • maxretry: how many failures inside that window trigger a block.

Read it like this: if maxretry failures pile up within the last findtime, fail2ban blocks the address for bantime. The three values work together, so rethink the others when you change one.

For example, picture a small case. If you set maxretry = 3 and findtime is very short, a slow attacker is never caught. On the other hand, if findtime is very long, a legitimate user who typed a wrong password days ago can hit the limit. So pick values that match how your team actually logs in. Also, if several people share one account, keep the limit a little looser.

Which fail2ban settings are a reasonable starting point?

Instead of a fixed rule, the right value depends on your traffic and how your team works. The table below is a starting range, not a guarantee. So watch your own logs and adjust.

ProfilebantimefindtimemaxretryFits
Close to default10m10m5First trial, low risk
Balanced start1h10m5General purpose VPS
Strict1d10m3Server with key only login

Example calculation: say maxretry = 5 and bantime = 1h. If a bot returns the moment a block ends, it goes through at most 24 block periods a day. It can make 5 attempts in each, so the upper limit is about 120 attempts. Progressive ban times lower that number further, as you will see below.

Instead, think of these numbers as a test bench. Start with a profile close to the default for the first week, watch the logs and confirm there are no false blocks. Then raise the time step by step. It sounds slow, but it cuts the risk of blocking your own team.

Also, the strict profile is only for servers where login needs a key. Legitimate users never type a password there, so the chance of crossing the limit by accident is low. But if password login is open, very short limits can block your own team.

How do you protect SSH logins with fail2ban?

Because SSH is the door attackers try the most, we start there. The official jail.conf already includes an sshd section, so you only enable it and tune the limits. Create the file as /etc/fail2ban/jail.local.

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

[sshd]
enabled  = true
port     = ssh
maxretry = 4
findtime = 10m
bantime  = 1h

If you moved SSH to a non standard port, update the port line with the same value. Otherwise fail2ban applies the block to the wrong port. If your logs live in the journal instead of a file, you may need backend = systemd. Also, most packages set this for you. Still, run sudo fail2ban-client status sshd to confirm that the jail really works.

Is fail2ban enough on its own for SSH?

No. The first defense is to turn off password login. The PasswordAuthentication and PermitRootLogin options in the OpenSSH sshd_config file are described in the official man page. Once key based login works, you can switch password login off.

  1. Test key based login in a second session.
  2. Check the configuration with sudo sshd -t.
  3. Reload the service. The service name can be ssh or sshd.
  4. Keep your current session open and test a new connection.

If you break this order, you can lock yourself out. Even then, fail2ban stays as a second layer and quiets any attempt that does not use a key. On a server where only key login is open, password guessing bots turn away at the door anyway. Still, the logs stay clean and wasted resources drop. For the option details, see the sshd_config man page.

How do you protect web login pages with fail2ban?

The official jail.conf includes ready jails such as nginx-http-auth and apache-auth. They read HTTP basic authentication failures from the error logs. For the own login form of an application like WordPress, you write a custom filter.

First create /etc/fail2ban/filter.d/wp-login.conf. The example assumes the combined access log format. If your log format differs, adapt the expression.

[Definition]
failregex = ^<HOST> .* "POST /wp-login\.php HTTP/[0-9.]+" 200
ignoreregex =

Then add the jail to jail.local. The log path depends on your web server and distribution.

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

This filter counts only POST requests that return 200. WordPress shows the form again after a failed login and usually redirects after a good one. The approach has a limit, though. If the attacker hits another address, the filter does not see it. XML-RPC, for example, needs its own filter. Still, verify it on your own site; the test tool in the next section is for that.

How do you test a custom filter with fail2ban-regex?

Test your filter with the fail2ban-regex tool before you go live. The tool takes a log file and a filter file and reports how many lines match. It also shows the lines that did not match, so fixing the expression is easy.

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

If the match count is zero, there are three possible reasons. The log format differs from what you expected, the expression is wrong, or the log has no failed logins at all. On the other hand, if too many lines match, the expression is too broad and may block legitimate users too.

You do not need a real attack to test. Existing log lines are enough, because the tool runs them through the filter and shows the result. Also, you can change the expression and run the test again to compare results.

So before you go live, check whether your own IP address appears in the matched list. If it does, add it to the ignoreip list.

How do you check the fail2ban ban list and jail status?

You do most daily work with the fail2ban-client command. We took the syntax from the official man page. The examples below use only reserved documentation IP blocks.

CommandWhat it does
sudo fail2ban-client statusLists the running jails
sudo fail2ban-client status sshdShows jail status and banned IPs
sudo fail2ban-client bannedLists banned IPs per jail
sudo fail2ban-client set sshd unbanip 203.0.113.50Removes the block on an IP
sudo fail2ban-client set sshd banip 198.51.100.7Blocks an IP by hand
sudo fail2ban-client reloadReloads settings without stopping the service

To see the firewall side, sudo iptables -L -n or sudo nft list ruleset lists the rules, depending on your backend. That way you confirm the block is really in place. When you read the output, look at the spread of addresses, not only the count. If one address shows up again and again, progressive ban times make sense. If you see many different addresses, the attack is distributed, and blocking alone will not be enough.

Fail2ban writes its own records to /var/log/fail2ban.log by default. If you wonder who owns a blocked address, our WHOIS lookup tool can help.

How do you use progressive ban times and the recidive jail for repeat offenders?

If the same address returns after a block, you can lengthen the time on every round. The official jail.conf describes the bantime.increment setting for this. Fail2ban looks up earlier blocks in its database and grows the time by doubling it: 1, 2, 4, 8 and so on. The bantime.maxtime setting sets the upper limit.

[DEFAULT]
bantime.increment = true
bantime.maxtime   = 604800

The value 604800 seconds equals one week. You can also choose the growth factor with bantime.factor, and you can decide with bantime.overalljails whether the history of all jails is searched.

As an alternative, the recidive jail watches fail2ban's own log and blocks repeat offenders for a long time. The section in the official file has bantime = 1w and findtime = 1d. Before you enable it, think about whether these values are too harsh for you.

How do you reduce the risk of locking yourself out with fail2ban?

However, the most common mistake is blocking your own IP. Typing a wrong password several times, running a deploy script with a wrong key, or having colleagues behind the same office address make mistakes can all cause it.

  • If you have a fixed IP, add it to the ignoreip list.
  • Keep a second SSH session open while you change the configuration.
  • Test your provider's console or rescue access beforehand.
  • Use a short bantime during tests, then raise it.
  • If you suspect a configuration error, test it with sudo fail2ban-client -t.

Should you get locked out, remove your own block from the console with fail2ban-client set sshd unbanip. If you have no console access, provider support may be the only way out. In that case, tell the support team your address and the time you were locked out. That way the fix comes faster. Also, write down the cause so it does not happen again.

How do you write the fail2ban whitelist (ignoreip) correctly?

According to the official documentation, ignoreip is the list of addresses that are never blocked. You can enter a single IP, a CIDR block or a host name. You separate the entries with spaces.

ignoreip = 127.0.0.1/8 ::1 203.0.113.10 198.51.100.0/24

Keep the list short. If you add a whole office network, everyone on it can try without limit. Also, if you use a host name, you depend on the lookup working. With a dynamic IP, the rule breaks when the address changes.

To add an address on a running system for a short time, the fail2ban-client set sshd addignoreip command exists. However, this change does not last, so write it into jail.local to keep it. Also, instead of every team member adding their own address, a secure VPN exit address is easier to manage.

How does fail2ban behave behind a CDN or reverse proxy?

If a CDN or reverse proxy sits in front of your site, the web server may log the proxy's address, not the visitor's. In that case fail2ban blocks the wrong address. Worse, thousands of legitimate visitors stand behind the same proxy address.

  • First, confirm that the log shows the real visitor address.
  • If it does not, set up the web server's real IP module as your proxy provider's documentation describes.
  • Or do the blocking in the CDN's own security rules.

There is a subtle point too. If traffic comes through the CDN, a firewall block on the origin server does not stop the visitor, because the connecting address is the CDN. So in this setup, solve log and IP visibility first, then write rules.

An easy way to check is to try a login from your own phone on mobile data and see which address appears in the log. If your phone's address shows up, the real IP arrives correctly.

Can fail2ban block legitimate bots such as Googlebot?

Yes, it can, because a filter that is too broad catches more than you intend. For example, a filter that treats many 404 responses as an attack can also catch a search engine bot. Then crawl problems start and your search visibility suffers.

  • Limit the filter to sensitive addresses such as login forms.
  • Avoid broad rules such as a general 404 counter.
  • If a blocked address looks like a search engine bot, verify its identity.

Google describes how to verify Googlebot in its official documentation. See the Googlebot verification guide for the details. You can also inspect a suspicious address with our IP lookup tool. That way you avoid blocking a legitimate bot by mistake.

Is fail2ban enough, and how do CSF and ModSecurity complement it?

However, fail2ban is reactive. It sees a behavior after it lands in a log and then blocks it. It does not inspect request content. A web application firewall, or WAF, does that job. CSF is a tool that makes firewall rules easier to manage.

You can compare layered defense to an apartment building. The firewall is the building door, the WAF is the camera at the desk, and fail2ban is the guard who walks away anyone who keeps forcing the same door. None of them closes every risk alone. So knowing each layer's job helps you invest in the right place.

We cover CSF Firewall and ModSecurity in separate sibling guides, so we will not repeat them here. In short: fail2ban looks at behavior, a WAF looks at request content, and the firewall decides which doors stay open.

On top of these you need current software, strong passwords and regular backups. For the HTTPS side, see our SSL certificate guide.

How do you troubleshoot fail2ban when it does not work?

Narrow the problem down layer by layer. First confirm the service is running, then that the jail loaded, then that the filter matches lines, and finally that the block reaches the firewall. Apply changes one at a time. Otherwise you cannot tell which step helped.

  1. Check the service with sudo systemctl status fail2ban.
  2. Look for errors in sudo journalctl -u fail2ban and in /var/log/fail2ban.log.
  3. See whether your jail appears in the sudo fail2ban-client status output.
  4. Then, if the jail is missing, check the enabled = true line and look for typos.
  5. Confirm with fail2ban-regex that the filter really matches.
  6. Review the logpath and backend values for your distribution.
  7. Check that the block rule exists in the firewall. The command depends on the backend.

If no block rule appears, look at the banaction value. The official default is iptables-multiport. If your system uses a different firewall, choose the matching action from the action.d folder.

How do you review a fail2ban setup on a regular basis?

Also, installation is not a job you do once and forget. A distribution update, a web server change or a log format change can break filters without any warning. So set up a small maintenance routine.

  1. Once a month, run fail2ban-client status to confirm that the jails are up.
  2. Review the blocked addresses and look for false blocks.
  3. After updates, run the fail2ban-regex test again.
  4. Keep a copy of jail.local in a safe place.
  5. Remove addresses from ignoreip that are no longer valid.

That way you notice a problem on a calm day, not in the middle of an attack.

When should you leave fail2ban to your hosting provider?

However, not every owner needs to configure this on their own server. The honest test is this: can you roll back when you make a mistake? If you cannot, leave the job to the provider.

  • On shared hosting you have no root access, so you cannot install fail2ban. The provider manages security.
  • If you buy a managed VPS or server service, ask the provider first, because clashing rules cause trouble.
  • Without console or rescue access, do not accept the lockout risk.
  • Do not change a critical online store without a maintenance window.
  • If you cannot solve real IP visibility behind a CDN, do not go further.

The right hosting choice takes most of this load off you. For the criteria, see our guide to choosing web hosting. For work on the software of your site, we support you with our custom software development and web design services. We still advise leaving server management to the right specialist. That approach protects both your security and your business continuity. Also, the cost of a wrong configuration is usually higher than the cost of maintenance.

What is the best order to follow for fail2ban in the end?

Here is a short roadmap. Apply each step after the previous one, one at a time, and test it.

  1. Confirm your console access and your backup.
  2. Set up key based SSH login and consider turning password login off.
  3. Install fail2ban and write only the settings you need into jail.local.
  4. Enable the sshd jail first and confirm with status that it works.
  5. If needed, write a custom filter for web login and test it with fail2ban-regex.
  6. Review progressive ban times and the ignoreip list.
  7. Read /var/log/fail2ban.log on a regular basis.

Remember one more thing: security is not a project you finish once. Software gets updates, attack styles change and teams grow. So keep the steps in this guide as a checklist and review them from time to time. If you are unsure about a step, stop, go back to the official documentation or ask your provider.

For official sources, see the fail2ban project repository, the jail.conf file and the jail.conf man page. To inspect your domain and DNS records, our DNS lookup tool can also help.

Frequently Asked Questions

Is fail2ban free?
Yes, fail2ban is free, open source software. It sits in the package repository of most Linux distributions, and you need no extra license. However, you need root or sudo access to install and maintain it, and you must write your own settings after installation. Shared hosting usually does not give you that access, so the provider manages security there.
Does fail2ban slow down a server?
Fail2ban reads log files, so it uses only a small amount of resources. However, very large logs and many jails can raise that use, so it makes sense to watch resource use. The best approach is to switch off unneeded jails and enable only the ones you need. It often relieves the server because it cuts attack traffic.
Does fail2ban work with both iptables and nftables?
Fail2ban does not block anything itself. It runs an action that adds a rule to the firewall. The official default action is based on iptables. If your system uses another backend, you pick the matching action from the action.d folder with banaction. What matters is to confirm that the rule really reaches the firewall, and you can list the rules with a command.
How do you unban an IP address in fail2ban?
Use the set command of fail2ban-client with the unbanip subcommand. First find the jail name, for example sshd, then add the address: sudo fail2ban-client set sshd unbanip 203.0.113.50. An unban all command exists as well. However, run it only when you truly need it, because it also frees real attackers.
What should you do if fail2ban blocks your own IP?
First log in to the server through your provider's console or rescue access. Then remove the block on your address with the unbanip command and add the address to the ignoreip list. Without console access you need to contact provider support. That is why testing console access before any change matters so much. Also, write down why the lockout happened.
Does fail2ban protect WordPress sites?
Partly. It can catch repeated failed attempts on the login page with a custom filter and block them. However, it does not solve plugin flaws, weak passwords or distributed attacks on its own. So use it as one layer together with current software, strong passwords, two step verification and backups. That way one missing defense does not bring everything down.
  • fail2ban
  • server security
  • SSH security
  • jail.local
  • brute force
  • VPS security
  • Linux firewall
Share:
Talha Aslan

Google Partner digital marketing expert. Hands-on with SEO, Google Ads, web design and e-commerce projects since 2012; every post here comes from that experience.

Next project

Let's talk about your project.

Your brief goes straight to Talha Aslan and team: strategy led by Talha, delivery by an experienced team. The first consultation is free; we listen and come back with a clear roadmap.