Create ip_blacklist_conf.lua

This commit is contained in:
Mikhail Che 2014-02-24 09:34:04 +05:00
parent 1577643763
commit 94d8f0ed6b
1 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,151 @@
--[[
¡ ¡ ¡ ALL GLORY TO GLORIA ! ! !
===========================
--]]
local _M = {
author='Mikhail Che <mche@cpan.org>',
version='0.14',
redis_sock = 'unix:/tmp/redis.sock', -- redis.conf: unixsocketperm 777!!!
--~ or
--~ redis_host = "127.0.0.1",
--~ redis_port = 6379,
redis_timeout = 200,-- connection timeout for redis in ms. don't set this too high!
redis_poolsize = 15, -- maximal size of the pool. Puts the current Redis connection immediately into the ngx_lua cosocket connection pool.
redis_keepalive = 0, -- ms. (0 - persistent) You can specify the max idle timeout (in ms) when the connection is in the pool and the maximal size of the pool every nginx worker process.
prefix = "ip_blacklist", -- for Redis keys and for log strings
key_delim = ':', -- for join Redis keys
--[[
There are four types of Redis keys:
1. Counter: <prefix>:count:<time range>:<ip>:<uri>
2. Locker: <prefix>:lock:<ip>:<uri>
3. Saved content: <prefix>:content:<host>:<uri>
4. Log of locking: <prefix>
--]]
time_range = 3, -- seconds of timeline sewgments разбивает временную линию на отрезки секунд и использует для ключа
req_limit = 20, -- max count of requests on time_range столько раз может обратиться IP в текущем временном отрезке
time_lock = 60, -- seconds for locking IP. If IP still make request then prolong lock time (expire Redis key) секунд держать в ловушке, если продолжает дергаться - пролонгировать expire этого ключа
mode='count',
--[[
nil or <whatever>- full mode: monitoring, locking and getout content from the Redis or capture content once and self save to Redis for next one locked IP requests
'count' - without lock IPs on blacklist, i.e. monitoring only. To see log of bad IPs on redis-cli: lrange <prefix> 0 -1
'forbidden' - monitoring + 403 page for locked IP
'nocapture' - disable self save content, i.e. monitoring + content from the Redis only. If content not found in Redis then 403
Note: chunked content when ngx.location.capture() bad?
--]]
log_lock = true, -- (false not) push locked IPs in persistent list <prefix> when count of requests exceeded limit (see by redis-cli: lrange <prefix> 0 -1)
["debug"]=true,-- false disable ngx.INFO log to nginx.log (errors always enabled as ngx.ERR level)
redis = require "resty.redis"
}
--------------------------------- END CONFIG -----------------------------------------------------------------
--=================== REDIS FUNCS =============================================
_M.redis_connect = function ()
local redis = _M.redis:new()
if not redis then
_M.log_err("Failed new redis")
ngx.exit(ngx.OK)
end
redis:set_timeout(_M.redis_timeout)
local connected, err
if _M.redis_sock then connected, err = redis:connect(_M.redis_sock)
elseif _M.redis_host and _M.redis_port then connected, err = redis:connect(_M.redis_host, _M.redis_port)
end
if not connected then
_M.log_err(string.format("could not connect to redis host=[%s:%s] sock=[%s] : %s", _M.redis_host, _M.redis_port, _M.redis_sock, err))
ngx.exit(ngx.OK)
end
--~ _M.log_info("success connect to redis")
return redis
end
----------------------------------------------------------------------------------------------------------------------------
_M.redis_expire = function (redis, key, time)
local result, err = redis:expire(key, time)
if not result then
_M.log_err(string.format("[redis:expire] failed for key=[%s]: %s", key, err))
_M.redis_end(redis)
ngx.exit(ngx.OK)
end
end
-------------------------------------------------------------------------------------------------------------------------------
_M.redis_exists = function (redis, key)
local key_ex, err = redis:exists(key)
if err then
_M.log_err(string.format("[redis:exists] failed for key=[%s]: %s", key, err))
_M.redis_end(redis)
ngx.exit(ngx.OK)
end
--~ _M.log_info(string.format("key=[%s] exists", key))
return key_ex == 1
end
------------------------------------------------------------------------------------------------------------------------------
_M.redis_incr = function (redis, key)
local count, err = redis:incr(key)
if err then
_M.log_err(string.format("[redis:incr] failed for key=[%s]: %s", key, err))
_M.redis_end(redis)
ngx.exit(ngx.OK)
end
return count
end
-----------------------------------------------------------------------------------------------------------------------------
_M.redis_end = function (redis)
--[[
syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size)
Puts the current Redis connection immediately into the ngx_lua cosocket connection pool.
You can specify the max idle timeout (in ms) when the connection is in the pool and the maximal size of the pool every nginx worker process.
In case of success, returns 1. In case of errors, returns nil with a string describing the error.
Only call this method in the place you would have called the close method instead. Calling this method will immediately turn the current redis object into the closed state. Any subsequent operations other than connect() on the current objet will return the closed error.
]]
local ok, err = redis:set_keepalive(_M.redis_keepalive, _M.redis_poolsize)
if not ok then _M.log_err(string.format("failed to set set_keepalive: %s", err)) end
end
--======================= OTHER FUNCS =====================================
_M.redis_keys = function ()
-- counter <prefix>:count:<time range>:<ip>:<host>:<uri>
local now = os.time()
local time_range = now % _M.time_range
local key_count = _M.join(_M.prefix, 'count', now - time_range, ngx.var.remote_addr, ngx.var.host, ngx.var.uri)
-- content <prefix>:content:<host>:<uri>
local key_content = _M.join(_M.prefix, 'content', ngx.var.host, ngx.var.uri)
--locker <prefix>:lock:<ip>:<host>:<uri>
local key_lock = _M.join(_M.prefix, 'lock', ngx.var.remote_addr, ngx.var.host, ngx.var.uri)
return key_count, key_lock, key_content, time_range
end
--------------------------------------------------------------------------------------------------------------------
_M.log_info = function (msg)
--~ if _M.debug then ngx.log(ngx.INFO, (string.format("%s: %s", _M.prefix, msg))) end
if _M.debug then ngx.log(ngx.INFO, msg) end
end
_M.log = _M.log_info
--------------------------------------------------------------------------------------------------------------------
_M.log_err = function (msg)
--~ ngx.log(ngx.ERR, (string.format("%s: %s", _M.prefix, msg)))
ngx.log(ngx.ERR, msg)
end
--------------------------------------------------------------------------------------------------------------------
_M.join = function (...) -- a,b,c
local t = {}
--~ for _,v in pairs(list) do
--~ for i = 1, arg.n do -- bad
--~ t[#t+1] = tostring(arg[i]) -- v
for i=1, select("#",...) do
t[#t+1] = (select(i,...))
end
return table.concat(t,_M.key_delim)
end
---------------------------------------------------------------------------------------------------------------------
return _M