Malware & Rootkit Scanning: rkhunter and ClamAV Guide
Protect your Linux server against malware and rootkits. rkhunter and ClamAV installation, scan configuration, result interpretation, scheduled scans, and incident response guide.
Protect your server against SSH brute-force attacks with Fail2Ban. Installation, jail.local configuration, Nginx/Apache jails, IP whitelisting, ban monitoring, and email alerts.
SSH brute-force attacks are among the most common threats faced by every internet-facing server. Fail2Ban is a powerful tool that monitors failed login attempts and automatically blocks attacker IP addresses. This guide walks you through setting up Fail2Ban with comprehensive protection for SSH, Nginx, and Apache.
Fail2Ban is a security tool that monitors log files and blocks IP addresses that make too many failed login attempts within a given time window using iptables/nftables rules. Written in Python, it includes ready-made filters for many services.
# Ubuntu/Debian
sudo apt update
sudo apt install fail2ban -y
# CentOS/AlmaLinux/Rocky Linux
sudo dnf install epel-release -y
sudo dnf install fail2ban -y
# Start Fail2Ban service
sudo systemctl start fail2ban
sudo systemctl enable fail2ban
# Check status
sudo systemctl status fail2ban
Fail2Ban's main configuration file is jail.conf. However, don't edit this file directly — it may be overwritten during updates. Instead, create a jail.local file:
# Copy jail.conf
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
# Edit configuration
sudo nano /etc/fail2ban/jail.local
# /etc/fail2ban/jail.local
[DEFAULT]
# Ban duration (seconds) — 1 hour
bantime = 3600
# Detection window (seconds) — 10 minutes
findtime = 600
# Maximum failed attempts
maxretry = 5
# Backend (auto, pyinotify, gamin, polling, systemd)
backend = auto
# DNS resolution (warn, no, yes)
usedns = warn
# Log level (CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG)
loglevel = INFO
# Log target
logtarget = /var/log/fail2ban.log
# Email notification
destemail = admin@example.com
sender = fail2ban@example.com
mta = sendmail
# Action — ban and send email
action = %(action_mwl)s
# Ban only (no email):
# action = %(action_)s
# Whitelist — these IPs are never banned
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
# Inside /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
# For Ubuntu 20.04+:
# logpath = %(sshd_log)s
maxretry = 3
bantime = 86400 # 24 hours
findtime = 600
# If using systemd journal:
# backend = systemd
For SSH, maxretry = 3 and bantime = 86400 (24 hours) are recommended. This allows attackers only 3 attempts per day.
# Nginx HTTP authentication failure
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = /var/log/nginx/error.log
maxretry = 5
bantime = 3600
# Nginx rate limiting violation
[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 10
bantime = 600
# Nginx bad bot blocking
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = /var/log/nginx/access.log
maxretry = 2
bantime = 86400
# Nginx 404 flood protection
[nginx-404]
enabled = true
port = http,https
filter = nginx-404
logpath = /var/log/nginx/access.log
maxretry = 20
findtime = 60
bantime = 3600
sudo nano /etc/fail2ban/filter.d/nginx-404.conf
[Definition]
failregex = ^<HOST> .* "(GET|POST|HEAD) .* HTTP/.*" 404
ignoreregex =
# Apache authentication failure
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/apache2/error.log
maxretry = 5
bantime = 3600
# Apache bad bots
[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/apache2/access.log
maxretry = 2
bantime = 86400
# Apache nuke/scan
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/apache2/error.log
maxretry = 6
bantime = 3600
# Add to DEFAULT section in jail.local
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
# You can add multiple IPs or subnets
ignoreip = 127.0.0.1/8 ::1 10.0.0.0/8 192.168.0.0/16 203.0.113.1
# Reload configuration
sudo fail2ban-client reload
# Verify whitelist
sudo fail2ban-client get sshd ignoreip
# View status of all jails
sudo fail2ban-client status
# View status of a specific jail
sudo fail2ban-client status sshd
# List banned IPs
sudo fail2ban-client status sshd | grep "Banned IP"
# Show all banned IPs
sudo iptables -L f2b-sshd -n --line-numbers
# Monitor log file
sudo tail -f /var/log/fail2ban.log
# Filter recent ban events
sudo grep "Ban" /var/log/fail2ban.log | tail -20
# Manually ban an IP
sudo fail2ban-client set sshd banip 1.2.3.4
# Unban an IP
sudo fail2ban-client set sshd unbanip 1.2.3.4
# Remove all bans (use with caution!)
sudo fail2ban-client unban --all
# Restart a specific jail
sudo fail2ban-client restart sshd
# Install Postfix or sendmail
sudo apt install postfix -y
[DEFAULT]
destemail = admin@example.com
sender = fail2ban@yourdomain.com
mta = sendmail
# Action options:
# action_ = ban only
# action_mw = ban + email
# action_mwl = ban + email + whois + log lines
action = %(action_mwl)s
# Service status
sudo systemctl status fail2ban
# Test configuration
sudo fail2ban-client -t
# List all jails
sudo fail2ban-client status
# Restart Fail2Ban
sudo systemctl restart fail2ban
# Reload configuration (without restarting service)
sudo fail2ban-client reload
By default, Fail2Ban resets bans when the server restarts. For persistent banning:
[DEFAULT]
# Permanent ban (-1 = forever)
bantime = -1
# Or very long duration:
bantime = 604800 # 7 days
Very aggressive settings (low maxretry, long bantime) can also block legitimate users. For SSH, maxretry=3-5 and bantime=3600-86400 is a balanced approach.
Fail2Ban is an indispensable part of server security. When properly configured for SSH, Nginx, and Apache, it significantly reduces brute-force attacks. Regularly monitor log files and whitelist any false-positive blocks.
You may have forgotten to whitelist your own IP address. Connect to the server via console access and run 'sudo fail2ban-client set sshd unbanip YOUR_IP'. Then add your IP to the ignoreip line in jail.local.
Yes. Set 'banaction = ufw' in jail.local to have Fail2Ban create UFW rules. By default it uses iptables, but it works seamlessly with UFW as well.
3-5 attempts is recommended for SSH. 5-10 may be more appropriate for web services. Too low values can block legitimate users, while too high values provide insufficient protection against attacks.
The default log file is /var/log/fail2ban.log. Monitor it in real time with 'sudo tail -f /var/log/fail2ban.log'. On systemd systems you can also use 'sudo journalctl -u fail2ban -f'.
Fail2Ban is effective against brute-force attacks but is not sufficient on its own. It should be used together with SSH key-based authentication, strong passwords, and firewall rules. It provides limited protection against distributed attacks (few attempts from many different IPs).
Protect your Linux server against malware and rootkits. rkhunter and ClamAV installation, scan configuration, result interpretation, scheduled scans, and incident response guide.
Set up a WireGuard VPN server: key generation, server and client configuration, IP forwarding, firewall rules, and Windows/Linux/Android client setup guide.
Zero Trust network security principles and practical implementation: never trust always verify, micro-segmentation, identity-based access, and implementation with existing Linux tools.