2015-07-31 1 views
2

Моя цель - предотвратить частой запрос на основе IP-адреса пользователя, а также google openresty и найти, что он может быть воспроизведен с помощью Lua. Поэтому я написал следующий сценарий, я новичок в Lua, может ли кто-нибудь дать мне несколько советов по этому сценарию или даже исправить меня.Предельная частота запросов каждого IP-адреса с использованием NGINX & Lua

этот скрипт, чтобы блокировать запрос, который запрашивает более 3 раз в 100s

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 

ответ

8

Почему бы просто не использовать Nginx строить в ngx_http_limit_req_module?

например. Мы ограничиваем не более 2 запросов в минуту от одного IP-адреса.

http { 
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/m; 

... 

server { 

    ... 

    location /search/ { 
     limit_req zone=one burst=3 nodelay; 
    } 
+0

Thx @xfeep, это то, что мне нужно. Но он все еще не может полностью удовлетворить мое требование. Мне нужно ограничить запрос не только на основе IP, но и на основе параметра запроса, например/test? Guid = blahblah, нам нужны лимитные запросы на основе «guid». –

+1

@ yunfeng.guo попробуйте limit_req_zone $ arg_guid zone = one: 10m rate = 2r/m; и мы также можем попытаться объединить IP и guid, например. limit_req_zone $ binary_remote_addr $ arg_guid zone = one: 10m rate = 2r/m; мы можем определить серверные зоны для разных местоположений. – xfeep

+0

@ yunfeng.guo. Обратите внимание: «До версии 1.7.6 ключ limit_req_zone может содержать ровно одну переменную». Поэтому, если ваша версия nginx меньше 1.7.6, вам нужно определить переменную и установить ее в местоположении, например. установить $ myzonekey $ binary_remote_addr $ arg_guid; – xfeep