Blocking IPs dynamically in Nginx can effectively protect websites or applications from malicious requests, crawlers, or DDoS attacks. Compared to the traditional static method of modifying the configuration file and reloading Nginx, dynamic IP blocking can automatically identify and block malicious IPs in real-time, greatly enhancing security and operational efficiency. This article will elaborate on three mainstream solutions, combined with practical configurations and application scenarios, to help you implement them quickly.

Common Solutions for Dynamic IP Blocking
Fail2ban Tool
- Implementation Method: It monitors Nginx logs, and when a certain threshold is reached, it calls the firewall or modifies the configuration to block the IP.
- Advantages: Easy to configure, has a mature community, and supports multiple services.
- Disadvantages: Depends on log analysis, has a delay, and frequent reloads can affect performance.
- Applicable Scenarios: Protects against brute-force attacks, scanner attacks, and abnormal request attacks.
Nginx Lua + Redis
- Implementation Method: Uses ngx_lua to query the Redis blacklist during the access phase.
- Advantages: High performance, takes effect in real-time, and can be shared distributively.
- Disadvantages: Requires OpenResty/Lua, and the architecture is complex.
- Applicable Scenarios: High-concurrency scenarios, distributed shared blacklists, and refined strategies.
Nginx Built-in Modules
- Implementation Method: Uses the limit_req_zone and limit_conn_zone to limit the request frequency and concurrency.
- Advantages: Native support, no third-party dependencies required.
- Disadvantages: Only limits traffic and connections, and cannot truly block IPs.
- Applicable Scenarios: Protects against CC attacks and prevents single-IP abuse.
Configuration Key Points for Each Solution
Dynamic Blocking with Fail2ban
Fail2ban monitors Nginx logs (such as 403/401/404 error codes, IPs with overly frequent access) and dynamically calls iptables or firewalld to block IPs. The core steps are as follows:
- Install Fail2ban:
- On Debian/Ubuntu:
sudo apt-get install fail2ban - On CentOS/RHEL:
sudo yum install fail2ban
- On Debian/Ubuntu:
- Configure Nginx Logs:
log_format main '$remote_addr - $remote_user [$time_local]"$request"''$status $body_bytes_sent "$http_referer" ''"$http_user_agent""$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
- Create a Filter Rule
/etc/fail2ban/filter.d/nginx-cc.conf:
[Definition]
failregex = ^<HOST> -.*"(GET|POST).*HTTP.*" 403
ignoreregex =
- Configure Jail
/etc/fail2ban/jail.local:
[nginx-cc]
enabled = true
port = http,https
filter = nginx-cc
logpath = /var/log/nginx/access.log
maxretry = 100
findtime = 60
bantime = 3600
action = iptables[name=NGINX, port=http, protocol=tcp]
- Start the Service:
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
Dynamic Blocking with Nginx Lua + Redis
This solution depends on OpenResty (which integrates Nginx + LuaJIT) and queries the Redis blacklist immediately when a request arrives, with extremely high efficiency. The core steps are as follows:
- Install OpenResty:
sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum install openresty
- Configure Nginx:
http {
lua_shared_dict ip_blacklist 10m;
server {
listen 80;
location / {access_by_lua_file /etc/nginx/lua/ip_blacklist.lua;}
}
}
- Write the Lua Script
/etc/nginx/lua/ip_blacklist.lua:
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
ngx.log(ngx.ERR, "Redis connection failed:", err)
return
end
local client_ip = ngx.var.remote_addr
local is_banned = red:sismember("ip_blacklist", client_ip)
if is_banned == 1 then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
red:set_keepalive(10000, 100)
- Manage the Blacklist:
- To ban an IP:
redis-cli SADD ip_blacklist 192.168.1.100 - To unban an IP:
redis-cli SREM ip_blacklist 192.168.1.100
- To ban an IP:
Rate Limiting with Nginx Built-in Modules
Nginx has built-in limit_req_zone and limit_conn_zone modules, which can limit the request rate and the number of concurrent connections. Although they cannot truly block IPs, they can effectively mitigate CC attacks. The configuration example is as follows:
http {
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location / {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 10;
}
}
}
Effect: Requests exceeding the limit will return a 503 Service Temporarily Unavailable response.
Practical Experience and Precautions
- Ensure Obtaining the Real IP: In the case of having a CDN or proxy, remember to configure the following:
set_real_ip_from 0.0.0.0/0;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
- Combined Measures are More Effective:
- Fail2ban → Blocks IPs with malicious behaviors.
- Nginx built-in rate limiting → Protects against instantaneous high-frequency attacks.
- Lua + Redis → Enables distributed real-time blacklists.
- Layered Blocking Strategies:
- Instant protection: Use limit_req/limit_conn.
- Short-term blocking: Employ Fail2ban (from minutes to hours).
- Long-term global blocking: Utilize Lua + Redis (for days or even permanently).
Conclusion
There are mainly three ways to implement dynamic IP blocking in Nginx:
- Fail2ban: Log-driven, suitable for single-machine and simple scenarios.
- Nginx Lua + Redis: High-performance real-time blacklist, suitable for distributed and large-scale businesses.
- Nginx built-in modules: Native rate limiting and connection limiting, suitable for dealing with CC attacks.It is recommended to implement the following in practice: For single machines, use Fail2ban + built-in rate limiting; for distributed/high-concurrency scenarios, use Lua + Redis + built-in rate limiting. This can not only achieve quick results but also take into account long-term scalability.