A lightweight bash toolkit that automatically firewall-blocks vulnerability scanners on Linux servers. It monitors nginx and Apache access logs for known malicious URL patterns and bans offending IPs using ipset + iptables.
Built for HestiaCP multi-domain hosting environments but works on any server running nginx and/or Apache with combined log format.
- A cron job runs
autoban.shevery minute - It reads only new log lines since the last scan (byte-offset tracking per log file)
- Each request URL is checked against ~1,189 known scanner patterns (
banned.txt) using awk's O(1) hash table lookup - Any IP that hits 3 or more banned URLs gets added to an ipset hash table
- A single iptables rule drops all traffic from IPs in the ipset
- Bans auto-expire after 24 hours (configurable)
A single iptables rule + ipset handles up to 65,536 banned IPs with O(1) lookup per packet. This is far more efficient than individual iptables/UFW rules per IP.
- Linux (tested on Ubuntu 20.04)
ipset(apt install ipset)iptablesawk,tail,flock,md5sum(standard on most distros)- nginx and/or Apache with combined log format
- Root access
git clone https://github.com/andyg2/autoban.git /tmp/autoban
sudo bash /tmp/autoban/install.shThe installer will:
- Copy scripts to
/etc/autoban/ - Seed log positions (only new requests are scanned, not historical logs)
- Create the ipset and iptables DROP rule
- Set up cron jobs (scan every minute, persist ipset every 6 hours, restore on reboot)
- Set up log rotation
- Create the
autobanCLI shortcut
After install, add your own IP to the whitelist:
echo "YOUR.IP.HERE" >> /etc/autoban/whitelist.txtautoban # Show status summary
autoban list # List all currently banned IPs with timeout remaining
autoban test 1.2.3.4 # Check if a specific IP is banned
autoban why 1.2.3.4 # Show ban history and matched URLs for an IP
autoban unban 1.2.3.4 # Manually unban an IP
autoban top # Show top repeat offenders from the ban log
autoban flush # Remove ALL banstail -f /var/log/autoban.logOutput looks like:
2026-03-28 04:55:01 BANNED 91.92.243.236 (hits=12, duration=86400s) urls=/.env(5),/.git/config(4),/wp-login.php(3)
2026-03-28 04:56:01 BANNED 141.98.11.239 (hits=5, duration=86400s) urls=/xmlrpc.php(3),/admin.php(2)
Edit the variables at the top of /etc/autoban/autoban.sh:
| Variable | Default | Description |
|---|---|---|
THRESHOLD |
3 |
Banned URL hits before an IP is blocked |
BAN_DURATION |
86400 |
Ban duration in seconds (24h). Use 0 for permanent |
LOG_DIRS |
nginx + apache domains | Space-separated log directories to scan |
/etc/autoban/
autoban.sh # Main scanner (runs via cron)
autoban-persist.sh # Save/restore ipset across reboots
autoban-status.sh # CLI management tool
banned.txt # Banned URL patterns (one per line)
whitelist.txt # IPs that should never be banned
state/ # Log position tracking (managed automatically)banned.txt contains one URL path per line. Matching is exact (after stripping query strings) -- /wp-admin/css/ only matches requests for that exact directory, not /wp-admin/css/login.min.css.
Add a pattern:
echo "/evil-scanner-path.php" >> /etc/autoban/banned.txtThe included list covers ~1,189 common scanner probes: WordPress exploit paths, shell uploaders, config file probes, debug endpoints, and directory enumeration attempts.
Autoban expects combined log format (the default for nginx and Apache):
IP - - [date] "METHOD /path HTTP/x.x" status size "referer" "user-agent"
It extracts $1 (IP) and $7 (URL path) using awk field splitting.
- Each log file's byte offset is tracked in
/etc/autoban/state/ - When a file shrinks (rotation), the offset resets and the new file is scanned from the beginning
- Rotated files (
.log.1,.log.2.gz, etc.) are automatically skipped
# Remove cron jobs
crontab -l | grep -v '/etc/autoban/' | crontab -
# Remove iptables rule and ipset
iptables -D INPUT -m set --match-set autoban src -j DROP
ipset destroy autoban
# Remove files
rm -rf /etc/autoban
rm -f /usr/local/bin/autoban
rm -f /etc/logrotate.d/autoban
rm -f /var/log/autoban.logMIT