How to install Fail2ban on Ubuntu to block brute-force attacks
Look at the login log of any server on the public internet and you will see the same thing: hundreds of failed attempts a day from strangers guessing usernames and passwords. Fail2ban watches those logs and, when an address fails too many times, blocks it for a while. It does not replace good security, such as keys instead of passwords, but it cuts noise, reduces load and slows down the persistent.
What Fail2ban does
It reads log files for patterns that mean "someone is trying to break in", counts how often each address triggers them, and when one crosses a limit, it adds a temporary firewall rule banning it. After the ban time, the rule is removed.
It works for SSH out of the box, and for many other services, such as web servers and mail, with extra settings.
Install it
sudo apt update
sudo apt install fail2ban
It starts automatically. Check with:
sudo systemctl status fail2ban
Configure it in a separate file
The main file, /etc/fail2ban/jail.conf, is overwritten when the package updates, so never edit it. Instead, create /etc/fail2ban/jail.local, which overrides it and survives updates:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IP
[sshd]
enabled = true
What the settings mean:
maxretryis the number of failures that triggers a ban.findtimeis the window in which those failures must happen. Five failures within ten minutes means a ban.bantimeis how long the ban lasts. Start with an hour, and raise it if attacks keep coming.ignoreiplists addresses that are never banned, such as your own. Add your home or office address, so a typo does not lock you out.
On recent Ubuntu versions, SSH logs go to the system journal, and Fail2ban reads them from there. If it does not detect failures, add backend = systemd under [sshd].
Restart to apply:
sudo systemctl restart fail2ban
Check what it is doing
sudo fail2ban-client status
sudo fail2ban-client status sshd
The second shows how many failures it has seen and which addresses are currently banned. On a public server, you will probably see entries within the hour.
Unban an address
If you get locked out by mistake, from another connection:
sudo fail2ban-client set sshd unbanip 203.0.113.50
If you are completely locked out, use the console in your provider's dashboard, and run the same command. Keep that option in mind, and set ignoreip before you test.
Make bans stricter
For repeat offenders, add the recidive jail, which watches Fail2ban's own log and bans addresses that keep coming back for much longer, such as a week. Add it to jail.local:
[recidive]
enabled = true
bantime = 1w
findtime = 1d
maxretry = 3
Protect other services
Fail2ban ships with ready-made filters for many programs, such as nginx-http-auth for password-protected pages and nginx-botsearch for scanners hitting missing pages. Enable them by adding a section with enabled = true. Make sure the log path matches where your service writes its logs.
What Fail2ban cannot do
Be honest about its limits:
- It does not make weak passwords safe. A guessed password on the first or second attempt gets through. Use keys. See How to set up SSH key authentication.
- It reacts after the fact. It blocks after failures, rather than preventing them.
- It is not protection against floods of traffic. Large attacks need other measures. See DDoS attacks explained for server owners.
- Attackers can change address. Bans slow them but do not stop them.
It is one useful layer, together with a firewall, keys and updates, not a complete defence. Basic security for a new VPS lists the layers, and Set up a firewall on your VPS with UFW covers the firewall.
Check that it keeps working
- After updates, confirm the service is still running.
- Look at the status every so often, and check the ban count.
- If you use a custom SSH port, make sure Fail2ban knows it, with
port = YOURPORTin the[sshd]section.
Still stuck? Open a ticket on Discord - run /ticket in any channel, pick a department, and include your Server ID or Invoice ID so we can jump straight in.