# fail2ban vs SSHGuard

> fail2ban vs SSHGuard compared: Python regex jails vs a small C daemon with attack scores, firewall backends, services covered, BSD support, and when SSHGuard wins.
>
> Source: https://fail2ban.dev/alternatives/sshguard/ · Updated 2026-10-25 · Checked against fail2ban 1.1.1
> fail2ban.dev is an independent guide, not the official fail2ban project.

**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:

```bash
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
```

## 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:

```ini
[sshd]
enabled  = true
backend  = systemd
maxretry = 5
findtime = 10m
bantime  = 1h
bantime.increment = true
```

## 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](/tools/regex-tester/), and drop it in `filter.d/` — see [writing a custom filter](/filters/custom/).

**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`](/config/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](/install/)).
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.
