Background: Access will be brutally swiped, crawlers and malicious attacks from time to time, causing databases, services, etc. to be paralyzed
Requirements: Implement a method of dynamically intercepting IP on Nginx. Specifically, when an IP accesses more than 60 times in 1 minute, it is added to Redis and intercepted. The interception time is 1 day by default.
Technical selection: The method of using Nginx+Lua+Redis. This solution uses Lua script to check the blacklist in Redis when Nginx handles requests, and at the same time counts the access frequency, and blocks it if it exceeds the threshold. This should meet the needs of the user.
It is necessary to combine Lua scripts and Redis counting functions. Install OpenResty, configure Nginx's Lua module, write Lua scripts to count visits, use Redis storage and expiration keys, and set interception logic. Use of connection pools to avoid frequent connections to Redis to affect performance.
1. Environmental preparation
- Install OpenResty
OpenResty integrates Nginx and Lua modules, and supports running Lua scripts directly:
# Ubuntu/Debian sudo apt-get install openresty # CentOS yum install openresty
- Install Redis Service
sudo apt-get install redis-server #Debiansudo yum install redis # RedHat
2. Nginx configuration
Main configuration file ()exist
http
Add shared memory and Lua script paths to the block:
http { lua_package_path "/usr/local/openresty/lualib/?.lua;;"; lua_shared_dict ip_limit 10m; # Shared memory area server { listen 80; server_name _; location / { access_by_lua_file /usr/local/lua/ip_block.lua; # Core intercept script root /var/www/html; } } }
3. Lua script implements dynamic interception
Script pathCreate a Lua script:
/usr/local/lua/ip_block.lua
Script content
local redis = require "" local red = redis:new() -- RedisConnection parameters local redis_host = "127.0.0.1" local redis_port = 6379 local redis_timeout = 1000 -- millisecond local redis_auth = nil -- No password left blank -- Intercept parameters local block_time = 86400 -- Banned time(1sky) local time_window = 60 -- Statistics window(1minute) local max_requests = 60 -- Maximum number of requests -- Get the clientIP local function get_client_ip() local headers = .get_headers() return headers["X-Real-IP"] or headers["x_forwarded_for"] or .remote_addr end -- connectRedis local function connect_redis() red:set_timeout(redis_timeout) local ok, err = red:connect(redis_host, redis_port) if not ok then (, "Redis connection failed: ", err) return nil end if redis_auth then local ok, err = red:auth(redis_auth) if not ok then (, "Redis authentication failed: ", err) end end return ok end -- Main logic local client_ip = get_client_ip() local counter_key = "limit:count:" .. client_ip local block_key = "limit:block:" .. client_ip -- Check if it has been blocked local is_blocked, err = red:get(block_key) if tonumber(is_blocked) == 1 then (ngx.HTTP_FORBIDDEN) -- Return directly403 end -- Statistics the number of requests connect_redis() local current_count = red:incr(counter_key) if current_count == 1 then red:expire(counter_key, time_window) -- Set expiration time for the first time end -- Trigger the ban condition if current_count > max_requests then red:setex(block_key, block_time, 1) -- Block and set1sky过期 red:del(counter_key) -- Delete the counter (ngx.HTTP_FORBIDDEN) end -- releaseRedisconnect red:set_keepalive(10000, 100)
4. Performance optimization
-
Redis connection poolpass
set_keepalive
Multiplex connections to avoid frequent TCP connection establishment
-
Shared memory cacheuse
lua_shared_dict
Cache high-frequency access IP to reduce Redis query pressure
Asynchronous loggingBlock the operation asynchronously writes to log files to avoid blocking request processing:
(0, function() local log_msg = ("%s - IP %s blocked at %s", , client_ip, ()) local log_file = ("/var/log/nginx/blocked_ips.log", "a") log_file:write(log_msg, "\n") log_file:close() end)
V. Verification and testing
- Manually trigger ban
# Simulate high frequency requestsab -n 100 -c 10 / # Check Redisredis-cli keys "limit:block:*"
- Automatic unblocking verification
After waiting for 24 hours, check whether the blocked IP is automatically deleted:
redis-cli ttl "limit:block:1.2.3.4" # Return the remaining seconds
VI. Expansion plan
-
Distributed ban
Sharing Redis blacklists among multiple Nginx servers to achieve cluster-level interception Visual monitoring
Real-time intercept data is displayed through Grafana+Prometheus:
# Collect Redis indicatorsprometheus-redis-exporter --=localhost:6379
-
Dynamically adjust threshold
Storing interception rules for different paths through Redis Hash:
local rule_key = "limit:rule:" .. local custom_rule = red:hget(rule_key, "max_requests")
Quote instructions
- The core intercept logic refers to the classic architecture design of Nginx+Lua+Redis
- Redis key expiration mechanism ensures automatic unblocking
- Performance optimization solutions draw on OpenResty best practices
The above is the detailed content of Nginx's method to dynamically intercept illegal access to IP. For more information about Nginx's dynamic intercepting IP, please pay attention to my other related articles!