Fail2ban (Brute-Force Protection)
fail2ban monitors log files for repeated authentication failures and temporarily bans offending IPs by writing firewall rules.
⚠️ The backend isiptables-multiport, not firewalld. Arch'spaths-arch.confsetsbanaction = iptables-multiport, and that is what is in effect unless you change it yourself. So fail2ban does not coordinate with firewalld here, and the two are separate mechanisms: thesshservice you add to a firewalld zone and the rules fail2ban drops are unrelated. If you want them unified, setbanaction = firewallcmd-rich-rulesin ajail.localand reload.
Active from first boot. shani-network enables it unconditionally at install time alongside firewalld — no setup needed to get baseline protection, though tuning the jails below is still recommended for any public-facing service.
Status & Tuning
# Overall status — shows all active jails and ban counts
sudo fail2ban-client status
# Status of the SSH jail specifically
sudo fail2ban-client status sshd
# Watch logs live
sudo journalctl -u fail2ban -f
Manual Ban / Unban
# Ban an IP in the sshd jail
sudo fail2ban-client set sshd banip 1.2.3.4
# Unban an IP
sudo fail2ban-client set sshd unbanip 1.2.3.4
# View all currently banned IPs across all jails
sudo fail2ban-client banned
# View the raw firewalld rules fail2ban has added
# fail2ban's bans are plain iptables rules here, not firewalld rules:
sudo iptables -L -n | grep -i f2b
Configuration
fail2ban ships with a default /etc/fail2ban/jail.conf. Never edit this file directly — it is overwritten on package updates. Instead, create overrides in /etc/fail2ban/jail.d/.
SSH Jail
Create /etc/fail2ban/jail.d/sshd-local.conf:
[sshd]
enabled = true
port = ssh
maxretry = 5
bantime = 1h
findtime = 10m
If you changed SSH to a non-standard port (e.g., 2222), set port = 2222 here.
| Parameter | Meaning |
|---|---|
maxretry | Failures before banning |
findtime | Time window in which failures are counted |
bantime | How long the IP is banned; use -1 for permanent |
Caddy Jail
First, enable JSON logging in your Caddyfile:
{
log {
output file /var/log/caddy/access.log
format json
}
}
Create /etc/fail2ban/filter.d/caddy.conf:
[Definition]
failregex = ^.*"remote_ip":"<HOST>".*"status":(401|403|404|429).*$
ignoreregex =
datepattern = %%Y-%%m-%%dT%%H:%%M:%%S
Create /etc/fail2ban/jail.d/caddy.conf:
[caddy]
enabled = true
port = http,https
filter = caddy
logpath = /var/log/caddy/access.log
maxretry = 10
bantime = 1h
findtime = 10m
Vaultwarden Jail
Create /etc/fail2ban/filter.d/vaultwarden.conf:
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <HOST>\..*$
ignoreregex =
Create /etc/fail2ban/jail.d/vaultwarden.conf:
[vaultwarden]
enabled = true
port = http,https
filter = vaultwarden
logpath = /home/user/vaultwarden/data/vaultwarden.log
maxretry = 5
bantime = 1h
findtime = 10m
Reload After Changes
sudo systemctl restart fail2ban
# Verify the new jail is active
sudo fail2ban-client status caddy
Whitelist Your Own IP
Prevent accidentally locking yourself out. Create /etc/fail2ban/jail.d/local.conf:
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24 100.64.0.0/10
100.64.0.0/10 covers the entire Tailscale CGNAT address range.
Troubleshooting
| Issue | Solution | |
|---|---|---|
| fail2ban won't start | Check journalctl -u fail2ban for syntax errors; validate with sudo fail2ban-client -t | |
| Banned yourself | Unban with sudo fail2ban-client set sshd unbanip YOUR_IP; add your IP to ignoreip | |
| IPs not being banned | Confirm the jail is enabled (sudo fail2ban-client status); verify the log path in the jail config exists and is being written to | |
| bans are not taking effect | The shipped backend is banaction = iptables-multiport in /etc/fail2ban/paths-arch.conf, not a firewalld action — so firewall-cmd will never show these bans. Check `sudo iptables -L -n | grep -i f2b, or switch the backend to firewallcmd-rich-rules in /etc/fail2ban/jail.d/*.local` |
| Caddy jail never triggers | Confirm Caddy is writing JSON logs to logpath; test the regex: sudo fail2ban-regex /var/log/caddy/access.log /etc/fail2ban/filter.d/caddy.conf |
See Also
- Firewall — the firewall that fail2ban writes rules into
- Security Features — overview of all security layers