Locking Out the Bots: Fail2ban and CrowdSec on a Modern Linux Server

Turning brute-force noise into a quiet log

Stand up a server, give it a public IP address, and within minutes complete strangers will start trying to log in. They are not people; they are tireless scripts sweeping the entire internet, guessing usernames and passwords, probing for known vulnerabilities, and hammering login forms in the hope that one in a million lands. Your authentication logs fill with failed attempts from places you have never been. This background radiation of automated attacks is simply the weather of the modern internet, and the question is not whether you will be probed but how cheaply you can make the probing fail. Two tools dominate the answer: the venerable Fail2ban and the newer, crowd-sourced CrowdSec. This guide covers both, and how they fit together.

It is tempting to assume that a small, obscure server is too unimportant to attack. The bots disagree. They do not target you specifically; they target every address that answers, indiscriminately and continuously. Scanning the entire IPv4 internet is cheap enough that anyone can do it, and the attackers are playing a numbers game where your box is just one of billions of lottery tickets.

The overwhelming majority of this traffic is dumb and repetitive: the same handful of common usernames, the same lists of leaked passwords, the same exploit signatures fired at every door. Because it is so mechanical, it is also eminently blockable. The defensive principle is simple. Watch the logs for the unmistakable pattern of an attack, and when you see it, slam the door on the source address for a while. Do that automatically, around the clock, and the noise drops to near silence.

Fail2ban is a log-watching daemon with a beautifully simple model. It tails your log files, matches lines against patterns called filters, and when a single source address trips a filter too many times within a window, it triggers an action, almost always a firewall rule that bans that address. The bundle of filter, thresholds, and action for a given service is called a jail.

The flow is: a log line such as a failed SSH password arrives, a filter’s regular expression recognises it, Fail2ban increments a counter for that IP, and when the counter crosses maxretry within findtime, the action fires and the address is banned for bantime. After the ban expires, the slate is wiped. The genius is that it needs no special integration with your services; if a service writes failures to a log, Fail2ban can defend it. SSH, web servers, mail servers, FTP, almost anything that logs.

On a Debian or Ubuntu system, installation is a single command:

sudo apt update
sudo apt install fail2ban -y

Never edit the shipped jail.conf directly, because package upgrades will overwrite it. Instead, create a local override that takes precedence:

sudo nano /etc/fail2ban/jail.local

A solid starting configuration for protecting SSH looks like this:

[DEFAULT]
bantime  = 1h
findtime = 10m
maxretry = 5
backend  = systemd

[sshd]
enabled = true

This bans any address that fails SSH authentication five times within ten minutes, and keeps it banned for an hour. The backend = systemd line reads from the systemd journal, which is correct on modern distributions where SSH no longer writes to a plain text log. Enable and start the service:

sudo systemctl enable --now fail2ban

Confirm the jail is active and watch it work:

sudo fail2ban-client status sshd

The output lists the number of failures seen and the addresses currently banned. To unban an address you blocked by mistake:

sudo fail2ban-client set sshd unbanip 203.0.113.45

For longer-running offenders, raise bantime dramatically, even to days, and consider a [recidive] jail that watches Fail2ban’s own log to apply much longer bans to addresses that keep coming back.

Fail2ban defends one server in isolation. It only knows what its own logs have shown it, so every server learns about every attacker the hard way, on its own. CrowdSec asks a better question: what if servers shared what they learned?

CrowdSec keeps the log-parsing idea but rebuilds it around collaboration and a cleaner architecture. It parses logs and evaluates them against scenarios, which describe attack behaviours such as a brute-force pattern or aggressive crawling. When a scenario fires, CrowdSec records a decision, but the enforcement is deliberately separated out into a component called a bouncer. The engine decides; the bouncer blocks. That separation means one detection engine can drive many enforcement points, a firewall, a web server, a reverse proxy, each running its own bouncer.

The headline feature is the community angle. When CrowdSec instances detect malicious addresses, they can contribute those signals to a shared, curated community blocklist. In return, your server can consume that blocklist and pre-emptively block addresses that have attacked other people, before they ever reach you. It is herd immunity for servers: an attacker that hits one participant gets flagged for everyone.

CrowdSec provides a repository script that configures your package manager, after which installation is straightforward:

curl -s https://install.crowdsec.net | sudo sh
sudo apt install crowdsec -y

On installation it detects running services and enrols sensible collections of parsers and scenarios automatically. The engine alone only detects; to actually block, install a bouncer. The firewall bouncer is the natural counterpart to Fail2ban’s behaviour:

sudo apt install crowdsec-firewall-bouncer-iptables -y

Verify the moving parts. List active decisions, inspect the metrics, and confirm the bouncer registered:

sudo cscli decisions list
sudo cscli metrics
sudo cscli bouncers list

To subscribe to the community blocklist and the central console, enrol your instance with a free account:

sudo cscli console enroll <your-enrollment-key>

From then on your server both contributes signals and benefits from the collective, blocking known-bad addresses proactively rather than only reacting to attacks against itself.

Neither tool is simply better; they sit at different points on a curve. Fail2ban’s strengths are its simplicity, its ubiquity, and its decades of battle-testing. It is a single daemon, configured with plain text files, present in every distribution’s repositories, and understood by every sysadmin. For a single box that needs SSH and a web server protected, it is hard to beat for sheer directness, and it has no external dependencies or accounts.

CrowdSec’s strengths are architecture and scale. The split between detection and enforcement suits fleets of servers and layered defences, and the shared blocklist means you benefit from attacks that never even reached you. It scales more gracefully across many machines and brings a polished console for visibility. The cost is a little more conceptual overhead, a few more moving parts, and, for the community features, an account and a dependence on an external service.

A reasonable rule of thumb: a lone hobby server is perfectly well served by Fail2ban; a growing fleet, or anyone who values pre-emptive community intelligence, will appreciate CrowdSec. There is also no rule against running both, with Fail2ban handling a specific local jail while CrowdSec provides the broader, crowd-sourced shield.

Automated banning is one layer, not the whole castle, and it works best on top of a properly hardened SSH configuration. The single most effective change is to disable password authentication entirely and rely on keys, which removes the very thing the brute-force bots are trying to guess. In /etc/ssh/sshd_config:

PasswordAuthentication no
PermitRootLogin no

With password login disabled, the relentless guessing attempts cannot succeed regardless, and Fail2ban or CrowdSec then exists chiefly to evict the noisy probers and keep your logs readable rather than to be your last line of defence. Layer the measures: key-only authentication closes the door, a banning tool stops the knocking, and the community blocklist keeps known troublemakers off the street entirely. If you have read this blog’s earlier guide to hardening SSH, these tools are the natural companion to it, automating the punishment for the attacks that hardening already renders futile.

The constant probing of your server is not a sign that something is wrong; it is simply the ambient condition of being online. The right response is not alarm but automation. Fail2ban watches your logs and bans the obvious offenders with a configuration you can read at a glance, while CrowdSec extends that idea into a collaborative defence where every server’s bad day makes every other server safer. Pair either with key-only SSH, and the brute-force racket that fills a fresh server’s logs fades to a quiet, well-defended hum.