Compare

fail2ban vs SSHGuard

SSHGuard is the minimalist alternative: a small C daemon with a built-in log parser and almost nothing to configure. fail2ban does more, for more services, with more knobs. Here is where each one fits.

Updated 6 min readChecked against fail2ban 1.1.1

Choose SSHGuard if you want a tiny, dependency-free daemon that blocks brute force against SSH and a fixed list of common services, especially on FreeBSD, OpenBSD or a small appliance where you'd rather not install Python. Choose fail2ban if you need to protect services SSHGuard doesn't recognize, want to write your own detection rules, need per-service settings, or want actions beyond a firewall block (Cloudflare, email, AbuseIPDB reporting).

Both read logs and block offending IPs in the firewall; the difference is flexibility. SSHGuard's attack signatures are compiled into its parser, so you get what the project ships. fail2ban's detection lives in editable regex filters — 96 of them upstream — and each service gets its own jail with its own thresholds.

fail2ban vs SSHGuard at a glance#

Feature fail2ban SSHGuard
Language Python 3 C, plus small shell scripts for firewall backends
Detection source Log files, systemd journal Log files, any command's output (LOGREADER, e.g. journalctl), stdin
Detection logic Editable regex filters, per-jail maxretry / findtime Built-in parser; each attack adds to a score, block when score passes a threshold
Services covered 96 filters: SSH, mail, web apps, VPNs, databases, game servers… Fixed list: OpenSSH, Dropbear, mail servers (Postfix, Exim, Dovecot, Cyrus…), FTP daemons, Cockpit, Proxmox VE, web probes in Common Log Format and more
Response Any shell command: nftables, iptables, firewalld, ufw, pf, ipfw, Cloudflare API, mail, reporting Firewall backends only: nftables, iptables, ipset, firewalld, pf, ipfw, IPFILTER, hosts.allow
Scope Single host Single host
Config style INI files, one jail per service One short sshguard.conf with global settings
Repeat offenders bantime.increment, recidive jail Block time multiplied for each repeat block; optional permanent blacklist file
IPv6 Yes Yes
Platforms Linux, BSD, macOS Linux, FreeBSD, OpenBSD, NetBSD, DragonFly, macOS, Solaris
License GPL-2.0-or-later OpenBSD license (ISC-style)
Maintenance Active, 1.1.1 (Aug 2026) Active, 2.6.0 tagged Oct 2026

How SSHGuard works#

SSHGuard reads log lines from files or from a command you set in LOGREADER, and its parser (sshg-parser) recognizes known attack patterns: failed SSH logins, invalid users, mail authentication failures, FTP brute force, web vulnerability probes and so on. Each attack raises the source address's attack score, usually by 10. When the score passes the THRESHOLD (default 30, so typically after the third attack), SSHGuard tells the firewall backend to block the address.

Blocks are short by default — BLOCK_TIME = 120 seconds — and grow for repeat attackers: each later block is multiplied by BLOCK_TIME_MULTIPLIER (default 2 in current releases). Scores are forgotten after DETECTION_TIME (1800 seconds) without new attacks. If you set a BLACKLIST_FILE with a threshold, addresses that pass it are written there and blocked permanently, even across restarts.

A typical Linux configuration is a handful of lines:

/etc/sshguard/sshguard.conf
BACKEND="/usr/libexec/sshguard/sshg-fw-nft-sets"
LOGREADER="LANG=C /usr/bin/journalctl -afb -p info -n1 -t sshd -t sshd-session -o cat"
THRESHOLD=30
BLOCK_TIME=120
DETECTION_TIME=1800
WHITELIST_FILE=/etc/sshguard/whitelist

The backend path differs by distribution (Debian uses /usr/libexec/sshguard/, FreeBSD /usr/local/libexec/); check what your package installed. On FreeBSD with pf you add the <sshguard> table to pf.conf and SSHGuard fills it.

How fail2ban works#

fail2ban runs one jail per service. A jail names a filter (regexes that recognize a failure and capture the <HOST>), a log or journal match, thresholds and one or more actions:

/etc/fail2ban/jail.local
[sshd]
enabled  = true
backend  = systemd
maxretry = 5
findtime = 10m
bantime  = 1h
bantime.increment = true

That's five failures in ten minutes for a one-hour ban that grows for repeat offenders (incremental bans). The sshd filter has normal, ddos, extra and aggressive modes, and every other service gets its own jail with its own numbers. More in the SSH protection guide.

Key differences that matter#

Coverage you can extend. If SSHGuard doesn't recognize a log line, you can't add a rule without patching and rebuilding the parser (or post-processing with a custom PARSER command). In fail2ban you write a regex, test it with fail2ban-regex or the regex tester, and drop it in filter.d/ — see writing a custom filter.

One policy vs per-service policy. SSHGuard's threshold and block time are global. fail2ban lets you be strict with SSH (maxretry = 3), lenient with a web login that users mistype, and permanent for a recidive jail.

Defaults. SSHGuard's two-minute first block is deliberately gentle — it slows bots without locking out a user who fat-fingers a password. fail2ban's stock bantime = 10m is longer, and most guides raise it further.

Footprint. SSHGuard is a few small processes written in C; fail2ban needs a Python 3 interpreter. On a normal VPS the difference rarely matters, but on embedded systems, minimal containers or routers it can.

Actions. fail2ban can do more than block: send email with whois data, report to AbuseIPDB, block at Cloudflare, or run any script. SSHGuard only blocks in the local firewall.

Can you run fail2ban and SSHGuard together?#

You can, but there is little reason to. Both protect SSH from the same log lines, so you'd get two bans for one attacker in two different firewall sets. If you want SSHGuard's lightweight SSH protection plus fail2ban for services SSHGuard doesn't know, disable the sshd jail in fail2ban (or the SSH signatures' log source in SSHGuard) so each attack is handled once, and whitelist your admin addresses in both.

Migrating from SSHGuard to fail2ban#

  1. Install fail2ban from your distribution (install guides).
  2. Create /etc/fail2ban/jail.local with an [sshd] jail and one jail for each other service SSHGuard was protecting (Postfix, Dovecot, vsftpd…).
  3. Copy your SSHGuard whitelist into ignoreip.
  4. Stop SSHGuard: sudo systemctl disable --now sshguard. Its backend removes its firewall table on a clean stop.
  5. Start fail2ban and confirm the jails are reading logs: sudo fail2ban-client status sshd.

FAQ#

Is SSHGuard better than fail2ban?#

SSHGuard is lighter and simpler, and needs almost no configuration, which makes it a good choice for SSH on BSD systems and small devices. fail2ban is more capable: editable filters for far more services, per-service thresholds and actions beyond firewall blocks. For most Linux servers fail2ban is the more flexible choice.

Does SSHGuard protect services other than SSH?#

Yes, despite the name. Its built-in parser recognizes attacks on Dropbear, several mail servers (Postfix, Exim, Dovecot, Cyrus and others), common FTP daemons, Cockpit, Proxmox VE and web vulnerability probes in Common Log Format logs. You can't add new services through configuration the way you can with fail2ban filters.

Does SSHGuard work with nftables?#

Yes. SSHGuard has an nftables backend (sshg-fw-nft-sets) that creates its own table with sets for IPv4 and IPv6 attackers. It also supports iptables, ipset, firewalld, pf, ipfw and IPFILTER, plus a hosts.allow fallback.

How long does SSHGuard block an IP?#

By default 120 seconds for a first block. Each later block for the same attacker is multiplied by BLOCK_TIME_MULTIPLIER (2 by default in current releases), and attack scores reset after 1800 seconds of quiet. Addresses that exceed an optional blacklist threshold are blocked permanently.

Should I use fail2ban or SSHGuard on FreeBSD?#

Both work with pf. SSHGuard is in the ports tree, written in C and integrates with a single <sshguard> pf table, so many FreeBSD admins prefer it for SSH. fail2ban also supports pf and is the better choice if you need custom filters or protect less common services.

Spotted something wrong or out of date? Tell us — every page is checked against the current fail2ban release.