使用 NGINX & Lua 限制每个 IP 的请求频率
Limit requests frequency of each IP using NGINX & Lua
我的目标是防止基于用户IP的高频率请求,我google了openresty,发现可以玩Lua。所以我写了下面的脚本,我是 Lua 的新手,谁能给我一些关于这个脚本的建议,甚至纠正我。
此脚本用于拦截100秒内请求次数超过3次的请求
local limit_request_times = 3
local expire_time = 100
local user_ip = ngx.var.remote_addr
-- ngx.say("user_ip: ", user_ip)
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.say("failed to connect: ", err)
return
end
local res, err = red:get(user_ip)
if res == ngx.null then
ngx.say("no request record, add this user_ip to redis")
ok, err = red:set(user_ip, 1)
if not ok then
-- ngx.say("add user_ip failed")
ngx.exit(ngx.HTTP_FORBIDDEN)
return
else
red:expire(user_ip, expire_time)
end
else
if tonumber(res) == limit_request_times then
-- ngx.say("request reach max limit times")
ngx.exit(403)
return
else
ok, err = red:incr(user_ip)
if not ok then
ngx.say("failed to increment request times")
return
else
ngx.say("increment request times: ", res + 1)
end
end
end
为什么不直接使用内置的 nginx ngx_http_limit_req_module?
例如我们限制来自一个 IP 地址的请求每分钟不超过 2 个。
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;
...
server {
...
location /search/ {
limit_req zone=one burst=3 nodelay;
}
您也可以通过 Lua https://nginx-extras.getpagespeed.com/lua/limit-traffic/
使用 resty.limit.conn
and/or resty.limit.req
模块
我的目标是防止基于用户IP的高频率请求,我google了openresty,发现可以玩Lua。所以我写了下面的脚本,我是 Lua 的新手,谁能给我一些关于这个脚本的建议,甚至纠正我。
此脚本用于拦截100秒内请求次数超过3次的请求
local limit_request_times = 3
local expire_time = 100
local user_ip = ngx.var.remote_addr
-- ngx.say("user_ip: ", user_ip)
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.say("failed to connect: ", err)
return
end
local res, err = red:get(user_ip)
if res == ngx.null then
ngx.say("no request record, add this user_ip to redis")
ok, err = red:set(user_ip, 1)
if not ok then
-- ngx.say("add user_ip failed")
ngx.exit(ngx.HTTP_FORBIDDEN)
return
else
red:expire(user_ip, expire_time)
end
else
if tonumber(res) == limit_request_times then
-- ngx.say("request reach max limit times")
ngx.exit(403)
return
else
ok, err = red:incr(user_ip)
if not ok then
ngx.say("failed to increment request times")
return
else
ngx.say("increment request times: ", res + 1)
end
end
end
为什么不直接使用内置的 nginx ngx_http_limit_req_module?
例如我们限制来自一个 IP 地址的请求每分钟不超过 2 个。
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m;
...
server {
...
location /search/ {
limit_req zone=one burst=3 nodelay;
}
您也可以通过 Lua https://nginx-extras.getpagespeed.com/lua/limit-traffic/
使用resty.limit.conn
and/or resty.limit.req
模块