IP Blocker Script
A lightweight automatic DDoS protection script for Linux servers. Runs via cron every 10 minutes, scans Apache and Nginx access logs, detects IPs exceeding a configurable request threshold, and blocks them at the kernel level using iptables.
Kernel-Level Blocking
Blocks via iptables -I INPUT 1 — packets dropped before reaching the web server
Cloudflare Aware
Fetches Cloudflare IP ranges dynamically — never accidentally blocks proxy traffic
Weekly Auto-Reset
Clears all blocks every Sunday — persistent attackers get re-blocked within 10 minutes
Dual Log Format
Parses both combined and vhost_combined Apache/Nginx log formats
Installation
# Download and install
sudo cp ip-blocker.sh /usr/local/bin/ip-blocker.sh
sudo chmod +x /usr/local/bin/ip-blocker.sh
# Add to crontab (every 10 minutes)
(crontab -l 2>/dev/null; echo "*/10 * * * * /usr/local/bin/ip-blocker.sh >> /var/log/ip-blocker.log 2>&1") | crontab -
Usage
ip-blocker.sh
Detect and block (normal cron operation):
ip-blocker.sh
Preview without blocking:
ip-blocker.sh --dry-run
Show currently blocked IPs:
ip-blocker.sh --list
Manually unblock an IP:
ip-blocker.sh --unblock 1.2.3.4
Options
| Option | Default | Description |
|---|---|---|
--dry-run |
off | Detect offenders but do not block them |
--list |
— | Show all currently blocked IPs with timestamps |
--unblock IP |
— | Remove a specific IP from the blocklist and iptables |
--threshold N |
250 |
Requests per window that triggers a block |
--window N |
10 |
Analysis window in minutes (should match cron interval) |
How It Works
1. Scan Access Logs
Auto-discovers access log files from standard locations
(/var/log/apache2/, /var/log/nginx/, /var/log/httpd/).
Filters log entries to only the configured time window (default: last 10 minutes).
2. Count Requests Per IP
Parses both combined format (IP is first field) and
vhost_combined format (IP is second field, after host:port).
Counts total requests per unique IP address.
3. Whitelist Check
IPs are checked against a comprehensive whitelist before any blocking:
| Range | Description |
|---|---|
127.0.0.0/8 |
Loopback |
10.0.0.0/8 |
Private network (RFC 1918) |
172.16.0.0/12 |
Private network (RFC 1918) |
192.168.0.0/16 |
Private network (RFC 1918) |
169.254.0.0/16 |
Link-local |
| Cloudflare ranges | Fetched dynamically from cloudflare.com/ips-v4, cached 24h |
4. Block via iptables
Offending IPs are blocked using iptables -I INPUT 1, which inserts the
DROP rule at position 1 in the INPUT chain — before any ALLOW rules. This ensures
packets are dropped at the kernel level before reaching the web server.
5. Weekly Reset
Every Sunday, all blocks are automatically cleared. This prevents false positives from persisting indefinitely. If an attacker is still active, they will be re-detected and re-blocked within 10 minutes by the next cron run.
Files
| File | Purpose |
|---|---|
/etc/ip-blocker.list |
Persistent list of blocked IPs with timestamps |
/var/log/ip-blocker.log |
Log file (when run via cron) |
/tmp/ip-blocker-cloudflare.cache |
Cached Cloudflare IP ranges (refreshed every 24h) |
/tmp/ip-blocker.lock |
Lockfile to prevent concurrent cron runs |
Example: Attack Detected
[2026-02-16 01:30:01] Refreshed Cloudflare IP list (14 ranges)
[2026-02-16 01:30:01] BLOCKED 188.211.233.226 - 672 requests in 10min
[2026-02-16 01:40:01] No offenders detected (threshold: 250 req/10min)
Cloudflare & Direct Connections
Compatibility
| Component | Supported |
|---|---|
| Web Server | Apache 2.x, Nginx |
| Log Formats | combined, vhost_combined, common |
| Firewall | iptables (works alongside UFW, firewalld) |
| OS | Any Linux with iptables and bash |
| Dependencies | iptables, curl, flock, awk (mawk or gawk) |