3.8 KiB
title, description, section, order
| title | description | section | order |
|---|---|---|---|
| Set Up Fail2ban for SSH Brute-Force Protection | Protect your Arcline VPS from SSH brute-force attacks with fail2ban. | vps | 7 |
Set Up Fail2ban for SSH Brute-Force Protection
Fail2ban monitors system logs for repeated failed login attempts and temporarily bans the offending IP addresses using the firewall. It's essential for any internet-facing server.
Prerequisites
- A VPS with SSH access and sudo privileges
- UFW or iptables already installed (see Initial VPS Setup)
Step 1 — Install fail2ban
sudo apt update
sudo apt install fail2ban -y
Step 2 — Configure fail2ban for SSH
The default configuration file is /etc/fail2ban/jail.conf. Don't edit it directly — it gets overwritten on updates. Instead, create a local override:
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
# Ban IPs for 1 hour after 5 failed attempts within 10 minutes
bantime = 3600
findtime = 600
maxretry = 5
# Send email alerts (optional)
# destemail = you@example.com
# action = %(action_mwl)s
[sshd]
enabled = true
port = ssh
logpath = %(sshd_log)s
If you changed your SSH port, specify it:
[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
Step 3 — Start fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Check the status:
sudo systemctl status fail2ban
Step 4 — Monitor banned IPs
View the SSH jail status:
sudo fail2ban-client status sshd
This shows the total bans and currently active bans.
View the ban log:
sudo tail -f /var/log/fail2ban.log
Step 5 — Unban an IP
If you accidentally lock yourself out (you should have tested SSH key access before enabling, but just in case):
sudo fail2ban-client set sshd unbanip 203.0.113.42
Or from the console (if you still have a root session open):
sudo iptables -D f2b-sshd -s 203.0.113.42 -j DROP
Step 6 — Additional jails (optional)
Nginx
[nginx-http-auth]
enabled = true
logpath = /var/log/nginx/error.log
Nginx bot protection (repeat offenders)
[nginx-botsearch]
enabled = true
logpath = /var/log/nginx/access.log
maxretry = 2
findtime = 86400
bantime = 86400
This bans IPs that hit common admin paths (wp-admin, etc.) that don't exist on your server.
Wordpress
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/auth.log
You may need to create a custom filter for your specific application logs.
Step 7 — Whitelist IPs
To exclude trusted IPs from bans (your office IP, for example):
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.100
Permanent bans with recidive jail
Habitual offenders get progressively longer bans:
[recidive]
enabled = true
logpath = /var/log/fail2ban.log
maxretry = 3
findtime = 604800 # 1 week
bantime = 604800 # 1 week
An IP that triggers bans 3 times in a week gets banned for a week.
Testing fail2ban
From a different machine (or after whitelisting your IP), intentionally fail SSH login a few times:
ssh nonexistent@your.vps.ip.address
After 5 failures, further attempts should hang or be refused. Check with:
sudo fail2ban-client status sshd
Performance notes
Fail2ban uses minimal resources — typically under 50MB of RAM with a few jails enabled. It reads log files using Python's pyinotify (if available) or polls every second.
If you have high-traffic sites with aggressive bots, increase findtime and lower maxretry to catch them sooner:
[nginx-botsearch]
maxretry = 2
findtime = 3600
bantime = 86400
What's next
- Deploy a Go binary as a systemd service
- Set up automated backups with restic