Protection against password-guessing attempts with fail2ban
Installing and configuring fail2ban for SSH, checking bans and unblocking an address.
On this page
fail2ban reads the server's logs and temporarily blocks IP addresses that fail to log in too many times within a short period. You install and configure it on the server itself, connected over SSH as root (Connecting to your server over SSH (Windows, macOS, Linux)). BLACKBOX does not install fail2ban on new servers, and the app.blackbox.md panel has no settings for it.
Available to: anyone with root SSH access to a BLACKBOX server running Ubuntu, Debian, AlmaLinux or CentOS Stream. On servers marked “Managed” in “My Servers”, the BLACKBOX team makes the changes: write to us.
The blackbox.md website is available in Romanian and Russian; this article quotes the Romanian labels with their English meaning.
When you need fail2ban
Bots on the internet try passwords nonstop on the SSH port of every public server. What fail2ban does for you depends on the badge on the server card in “My Servers”:
| Badge | Situation | What fail2ban does |
|---|---|---|
| “Password + key” | The root password works over SSH and can be guessed | Blocks the addresses that try passwords. Recommended. |
| “Key-only” | SSH accepts only keys, so the password can't be guessed | Mainly cuts down the noise in the logs and the load caused by bots. Still recommended. |
The safest option is still key-only login: Enabling and disabling SSH password login. fail2ban adds to it; it does not replace it. Where it fits among the other security steps: Securing a new server: checklist. If the server has a control panel installed (the “VPS hosting” plans), ask support first: the panel may have its own fail2ban.
Installing
Ubuntu and Debian
apt update
apt install -y fail2banAlmaLinux and CentOS Stream
fail2ban comes from the EPEL repository:
dnf install -y epel-release
dnf install -y fail2banConfiguring jail.local
The default settings are in /etc/fail2ban/jail.conf. Don't edit this file: a package update may replace it. Write your settings in /etc/fail2ban/jail.local, which is read after jail.conf and after the .conf files in /etc/fail2ban/jail.d/, and takes priority over them. Each section protects one service and is called a “jail”: [sshd] for SSH, [nginx-http-auth] for nginx, and so on. The [DEFAULT] section holds the shared values.
Find out the public IP address you connect from: open
https://ip.blackbox.mdand click “Copiază” (Copy) (The “Adresa ta IP” (Your IP address) tool). If you work from several places, for example from the office and from home, write down each address.On Ubuntu and Debian, check whether the SSH log file exists:
ls -l /var/log/auth.logIf the response is “No such file or directory”, the system keeps its logs only in the systemd journal (for example, on Debian 12), and you will also do step 5. On AlmaLinux and CentOS Stream, skip this step: there, fail2ban reads the systemd journal by default, so you don't need steps 5 and 7 either.
Open the file in the editor:
nano /etc/fail2ban/jail.localOn AlmaLinux and CentOS Stream, if you get “nano: command not found”, install the editor first:
dnf install -y nanoPaste the content below and replace
YOUR_IPwith the address from step 1 (separate multiple addresses with a space). If the file already exists, for example because you created it while following the checklist, don't duplicate the sections: add the missing lines to the existing sections.[DEFAULT] ignoreip = 127.0.0.1/8 ::1 YOUR_IP bantime = 1h findtime = 10m maxretry = 5 [sshd] enabled = trueOn Ubuntu and Debian only, if the log file was missing in step 2: add the line below to the
[sshd]section, underenabled = true.backend = systemdSave and close: in
nano, press Ctrl + O, Enter, then Ctrl + X.If you did step 5, install the module that
backend = systemdneeds. Usually it is already installed together with fail2ban; in that case, the command just confirms it.apt install -y python3-systemd
| Parameter | What it does | Value in the example |
|---|---|---|
ignoreip |
Addresses and networks that are never blocked. 127.0.0.1/8 ::1 is the server itself. It also accepts networks, for example 198.51.100.0/24. |
your address |
bantime |
How long a ban lasts. Units: m (minutes), h (hours), d (days). |
1 hour (default: 10 minutes) |
findtime |
The time window in which failed attempts are counted. | 10 minutes (same as the default) |
maxretry |
How many failed attempts within findtime lead to a ban. |
5 (same as the default) |
bantime.increment |
Optional, in [DEFAULT]. With true, each new ban of the same address lasts longer than the previous one. |
— |
enabled |
In [sshd]: turns on SSH protection. |
true |
backend |
In [sshd]: systemd means that fail2ban reads the systemd journal. On AlmaLinux and CentOS Stream, this is already the default value. On Ubuntu and Debian, you add it only if the log file is missing. |
only in step 5 |
Important Add your address to
ignoreipbefore you start fail2ban. Otherwise, a few failed logins from your computer will lock you out of the server. Don't close your current SSH session until you have checked that you can connect from a new terminal. Many home and mobile connections have a dynamic address, which changes: if you can no longer connect, check your address again onip.blackbox.md.
AlmaLinux and CentOS Stream: how blocking is applied
On these systems, the fail2ban package also installs firewalld and blocks addresses through it. On a new server, firewalld is not running, and without it bans have no effect. Check:
systemctl is-active firewalld| Response | What to do |
|---|---|
active |
Nothing: bans are added to firewalld. |
inactive or any other response |
Add the two lines below to the [DEFAULT] section of jail.local: fail2ban will then block addresses directly through nftables. Alternatively, start and configure firewalld: Firewall: network filtering and ufw/firewalld on the server. |
banaction = nftables-multiport
banaction_allports = nftables-allportsIf you don't use firewalld, also check whether it is set to start at boot:
systemctl is-enabled firewalldIf the response is enabled, turn off automatic start. Otherwise, after a reboot, firewalld starts with its default rules, which let SSH through but not your websites' ports 80 and 443.
systemctl disable firewalldStarting and checking
Check the configuration. The correct response is “OK: configuration test is successful”; otherwise, the message shows the file and the line with the problem.
fail2ban-client -tEnable automatic start and start the service, then restart it so that it is sure to read
jail.local(on Ubuntu and Debian, it may already be running since installation):systemctl enable --now fail2ban systemctl restart fail2banCheck the active jails.
sshdmust appear in “Jail list”:fail2ban-client statusCheck the SSH protection:
fail2ban-client status sshdStatus for the jail: sshd |- Filter | |- Currently failed: 2 | |- Total failed: 57 | `- File list: /var/log/auth.log `- Actions |- Currently banned: 1 |- Total banned: 9 `- Banned IP list: 203.0.113.45
| Field | What it shows |
|---|---|
| “Currently failed” | How many addresses have failed attempts within the findtime window but are not banned yet |
| “Total failed” | The failed attempts counted since fail2ban started |
| “File list” or “Journal matches” | Where fail2ban reads from: from a file or, with backend = systemd, from the systemd journal |
| “Currently banned”, “Total banned”, “Banned IP list” | How many addresses are banned now, how many bans there have been since fail2ban started, and which addresses are banned now |
The ban history and errors are in the fail2ban log, usually the file /var/log/fail2ban.log. To see the latest bans and unbans:
grep -E "(Ban|Unban) " /var/log/fail2ban.log | tail -n 20If the file is missing, read the service's systemd journal:
journalctl -u fail2ban -n 50Test the ban
Check once that banning really works, using 203.0.113.10, an address reserved for documentation that belongs to no one:
fail2ban-client set sshd banip 203.0.113.10
fail2ban-client status sshd
tail -n 20 /var/log/fail2ban.log
fail2ban-client set sshd unbanip 203.0.113.10The address must appear in “Banned IP list”, and in the log, after the line with Ban 203.0.113.10, there must be no lines with ERROR (if the log file is missing, use the journalctl command above). If errors appear, see “Common problems” below.
Unblocking an address
Remove the address from the SSH ban:
fail2ban-client set sshd unbanip IP_ADDRESSOr from all jails at once:
fail2ban-client unban IP_ADDRESSTo keep the address from being blocked in the future, add it to ignoreip in /etc/fail2ban/jail.local, then restart fail2ban:
systemctl restart fail2banIf you blocked your own address
How to tell: the SSH connection from your computer is refused or times out, although the server responds from another network. You have four options:
- Wait for the ban to expire (
bantime, one hour in the example above). Rebooting the server doesn't help: fail2ban remembers active bans and applies them again at startup. - Connect from another network, for example through your phone's mobile internet, unblock the address as described above and add it to
ignoreip. - If you connected an AI assistant through a token with the “Rulează orice comandă ca root pe serverele mele” (Run any command as root on my servers) permission, ask it to run the unblock command: the command reaches the server through the BLACKBOX connection, not from your address (Running commands on the server through AI).
- Write to us and include the server's IP address and your own IP address: How to contact BLACKBOX support.
Warning Customers have no web console or VNC that would let them get into the server around the ban. That is why you should add your address to
ignoreipbefore you start fail2ban.
Protection for nginx (optional)
If nginx runs on the server (Web server with HTTPS: nginx or Apache and Let's Encrypt), fail2ban has ready-made filters. They read the nginx error logs (/var/log/nginx/*error.log) and block ports 80 and 443.
| Jail | What it blocks | When to enable it |
|---|---|---|
nginx-http-auth |
Addresses that repeatedly enter a wrong username or password on pages protected with HTTP authentication (auth_basic) |
If you have such pages, for example an admin panel |
nginx-limit-req |
Addresses that repeatedly exceed the request limit set in nginx | Only if you have configured limit_req_zone and limit_req; without them, the log has nothing to report |
Add only the sections you need at the end of /etc/fail2ban/jail.local:
[nginx-http-auth]
enabled = true
[nginx-limit-req]
enabled = trueThen check the configuration, restart the service and check the new jail:
fail2ban-client -t
systemctl restart fail2ban
fail2ban-client status nginx-http-authIf your sites write their error log somewhere else, add the line logpath = LOG_PATH to the section.
Note If the domain goes through the Cloudflare proxy (the orange cloud), requests come from Cloudflare's addresses, not directly from visitors. A ban on the server then doesn't stop the attacker and may even block Cloudflare's addresses. For such domains, don't enable the nginx jails; use the protection features in your Cloudflare account.
Common problems
Start with these commands: the first one shows configuration errors, the others show the state of the service.
fail2ban-client -t
systemctl status fail2ban
journalctl -u fail2ban -n 50| Message | Cause | What to do |
|---|---|---|
Failed to access socket path: …/fail2ban.sock. Is fail2ban running? |
The service isn't running, usually because of an error in the configuration | Fix the error shown by the first command above, then restart the service. If you have just started it, wait a few seconds and run the command again |
Have not found any log file for sshd jail |
The SSH log file is missing (Ubuntu, Debian) | Do steps 5 and 7 in “Configuring jail.local” |
Have not found any log file for nginx-http-auth jail (or nginx-limit-req) |
nginx isn't installed, or its logs are somewhere else | Remove the section from jail.local or add logpath |
In the fail2ban log, during a ban: iptables: not found |
The default blocking method uses iptables, which isn't installed (this can happen on Debian) | Install the iptables package and restart fail2ban |
In the fail2ban log, during a ban: FirewallD is not running |
firewalld is stopped on AlmaLinux or CentOS Stream | Follow “AlmaLinux and CentOS Stream: how blocking is applied” |
Frequently asked questions
My server is “Key-only”. Is fail2ban still worth it? Yes. The password can't be guessed, but bots keep connecting and filling up the logs. fail2ban blocks them after a few attempts and reduces the noise and the load.
Does the panel show me whether fail2ban is working? For servers ordered on blackbox.md, no: the “Monitoring” page shows the load of servers with the Monitoring service (CPU, RAM, disk), not the state of fail2ban (The “Monitoring” page). Check on the server, with the commands in “Starting and checking”. For the servers of a company managed by BLACKBOX, the “Overview” page has the “Missing fail2ban” tile and the “fail2ban” column (The “Overview” page).
Does fail2ban protect me from a DDoS attack? No. fail2ban reacts to failed logins and to errors in the logs, one address at a time. If your server or website is under attack, read Your server was hacked or is under attack: what to do and write to us.
Can I use fail2ban together with ufw or firewalld? Yes. fail2ban adds its own blocking rules, separate from your firewall rules. The network-level filtering, managed by BLACKBOX, works independently of both: Firewall: network filtering and ufw/firewalld on the server.