Three Production‑Ready Dynamic IP Blocking Solutions for Nginx (No Manual Reload)
This guide presents three practical, production‑grade methods to dynamically block IP addresses in Nginx—using OpenResty with Redis for millisecond response, fail2ban with log analysis for automated bans, and a pure‑shell file‑watch approach—each with step‑by‑step installation, configuration, and usage instructions.
Solution 1: OpenResty + Redis (millisecond‑level dynamic blocking)
Install OpenResty and Redis, then configure Nginx to query Redis for a blacklist and deny matching IPs without reloading.
Install OpenResty and Redis on Ubuntu:
# Ubuntu example
sudo apt install redis-server -y
wget -O - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/openresty-archive-keyring.gpg] http://openresty.org/package/debian $(lsb_release -sc) openresty" | sudo tee /etc/apt/sources.list.d/openresty.list
sudo apt update && sudo apt install -y openrestyConfigure /etc/openresty/nginx.conf to load the Redis library and deny blacklisted IPs:
worker_processes auto;
events { worker_connections 1024; }
http {
server {
listen 80;
location / {
access_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then return end
local ip = ngx.var.remote_addr
if red:get("blacklist:" .. ip) ~= ngx.null then
ngx.exit(403)
end
red:close()
}
proxy_pass http://127.0.0.1:8080;
}
}
}Block or unblock an IP with a single Redis command:
# Block for 1 hour
redis-cli SETEX blacklist:1.2.3.4 3600 "abuse"
# Unblock
redis-cli DEL blacklist:1.2.3.4Solution 2: fail2ban + Nginx logs (automatic analysis)
Use fail2ban to parse Nginx access logs and automatically ban offending IPs via iptables.
Install fail2ban: sudo apt install fail2ban -y Create a filter /etc/fail2ban/filter.d/nginx-bad.conf :
[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (400|403|444|404) .*
ignoreregex =Configure a jail /etc/fail2ban/jail.local :
[nginx-bad]
enabled = true
port = http,https
filter = nginx-bad
logpath = /var/log/nginx/access.log
maxretry = 5
findtime = 600
bantime = 3600
action = iptables-multiport[name=nginx, port="80,443"]Restart fail2ban to apply the rules:
sudo systemctl restart fail2banSolution 3: Pure Shell + File Watch (zero dependencies)
Maintain a plain‑text blacklist file and use a shell script together with inotifywait to regenerate Nginx deny directives automatically.
Install inotify-tools : sudo apt install inotify-tools -y Create the blacklist directory and initial files:
sudo mkdir -p /etc/nginx/dynamic
echo "# Blacklist IP, one per line" | sudo tee /etc/nginx/blacklist.txt
sudo touch /etc/nginx/dynamic/blacklist.confWrite the conversion script /usr/local/bin/gen_nginx_blacklist.sh :
#!/bin/bash
INPUT="/etc/nginx/blacklist.txt"
OUTPUT="/etc/nginx/dynamic/blacklist.conf"
# Header
echo "# Auto‑generated from blacklist.txt. DO NOT EDIT." > "$OUTPUT"
# Generate deny rules
while IFS= read -r line; do
line=$(echo "$line" | xargs) # trim spaces
if [[ -n "$line" && "$line" != \#* ]]; then
echo "deny $line;" >> "$OUTPUT"
fi
done < "$INPUT"
# Test and reload Nginx
nginx -t && systemctl reload nginxMake it executable:
sudo chmod +x /usr/local/bin/gen_nginx_blacklist.shInclude the generated file in the Nginx server block:
server {
listen 80;
include /etc/nginx/dynamic/blacklist.conf; # key line
location / {
proxy_pass http://127.0.0.1:8080;
}
}Start a background watcher that regenerates the file on changes (or create a systemd service):
nohup inotifywait -m -e modify,move,create,delete /etc/nginx/blacklist.txt \
--format '%f' |
while read file; do
echo "[$(date)] blacklist.txt changed, regenerating..."
/usr/local/bin/gen_nginx_blacklist.sh
done &Choosing a solution
High‑concurrency API gateway or any service that needs millisecond response: Solution 1 (OpenResty + Redis)
Brute‑force protection for WordPress or small sites: Solution 2 (fail2ban)
Prefer no extra packages, pure Nginx file‑based workflow: Solution 3 (Shell + file watch)
Xiao Liu Lab
An operations lab passionate about server tinkering 🔬 Sharing automation scripts, high-availability architecture, alert optimization, and incident reviews. Using technology to reduce overtime and experience to avoid major pitfalls. Follow me for easier, more reliable operations!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
