Securing Linux with fail2ban
Fail2ban monitors log files for patterns indicating failed authentication attempts and bans offending IPs by updating firewall rules. It’s one of the easiest security improvements you can make on any Linux server.
Installation
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
Configuration
Don’t edit /etc/fail2ban/jail.conf directly. Create a local override:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
Or better, create a file in /etc/fail2ban/jail.d/:
sudo nano /etc/fail2ban/jail.d/custom.conf
Protecting SSH
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
maxretry— number of failures before banningfindtime— the window for counting failuresbantime— how long the ban lasts (in seconds)
This bans an IP for 1 hour after 3 failed SSH attempts within 10 minutes.
For persistent bans, set bantime = -1. For incremental bans (each offense gets longer):
bantime = 10m
bantime.increment = true
bantime.factor = 2
bantime.maxtime = 4w
Protecting other services
Fail2ban has filters for many services out of the box:
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 3
bantime = 3600
[postfix]
enabled = true
port = smtp,ssmtp
filter = postfix
logpath = /var/log/mail.log
maxretry = 5
bantime = 3600
Custom filters
Filters define what patterns to look for. They live in /etc/fail2ban/filter.d/.
Create a custom filter for your application:
sudo nano /etc/fail2ban/filter.d/myapp.conf
[Definition]
failregex = ^.*Failed login from <HOST>.*$
^.*Authentication error from <HOST>.*$
ignoreregex =
Test the filter against a log file:
sudo fail2ban-regex /var/log/myapp.log /etc/fail2ban/filter.d/myapp.conf
This shows matching lines and helps debug your regex.
Ban actions
The default action updates iptables. You can also:
Send email on ban:
action = %(action_mwl)s
This sends an email with the relevant log lines.
Custom actions:
action = %(action_)s
sendmail-whois[name=sshd, dest=you@example.com]
Managing bans
Check status:
sudo fail2ban-client status
sudo fail2ban-client status sshd
Manually ban an IP:
sudo fail2ban-client set sshd banip 192.168.1.100
Manually unban:
sudo fail2ban-client set sshd unbanip 192.168.1.100
List banned IPs:
sudo fail2ban-client set sshd banip list
Recidive jail
Ban repeat offenders across all jails:
[recidive]
enabled = true
filter = recidive
logpath = /var/log/fail2ban.log
bantime = 604800 ; 1 week
findtime = 86400 ; 1 day
maxretry = 3
If an IP gets banned 3 times in a day across any jail, it gets banned for a week.
Common mistakes
Editing jail.conf directly. Package updates overwrite it. Use jail.local or files in jail.d/.
Not checking log paths. The logpath must match where your service actually logs. Different distros put logs in different places.
Banning yourself. If your IP is dynamic or you connect from the same IP you’re protecting, add it to the ignore list:
[DEFAULT]
ignoreip = 127.0.0.1/8 your.trusted.ip
Too aggressive settings. Three retries in 10 minutes is reasonable for SSH. For web login forms, users mistype passwords — give them more chances.
Remarks
Fail2ban is set-it-and-forget-it security. Install it, configure SSH protection, and you’ve already dramatically reduced brute-force exposure. The custom filters let you protect any service that logs authentication failures. It’s not a firewall replacement — it’s a complement that reacts to patterns in your logs.
Related Posts
Vim survival guide for Linux admins
The minimum vim knowledge you need to survive on a Linux server. Editing config files without wanting to throw your keyboard.
Linux memory management: free, vmstat, and /proc
Understanding how Linux uses memory. Reading free correctly, using vmstat, and what /proc/meminfo actually tells you.
tmux: terminal multiplexing made simple
Using tmux to manage terminal sessions. Panes, windows, and why your SSH sessions should survive disconnects.