range support method 1
This commit is contained in:
parent
b9529e8a51
commit
4db2cda499
3 changed files with 155 additions and 18 deletions
|
@ -1,8 +1,9 @@
|
|||
ok, err = require "crowdsec".allowIp(ngx.var.remote_addr)
|
||||
local cs = require "crowdsec"
|
||||
ok, remediation, err = cs.allowIp(ngx.var.remote_addr)
|
||||
if err ~= nil then
|
||||
ngx.log(ngx.ERR, "[Crowdsec] bouncer error: " .. err)
|
||||
end
|
||||
if not ok then
|
||||
ngx.log(ngx.ALERT, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "'")
|
||||
ngx.log(ngx.ALERT, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "' with '"..remediation.."'")
|
||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||
end
|
||||
|
|
|
@ -1,13 +1,20 @@
|
|||
package.path = package.path .. ";./?.lua"
|
||||
|
||||
local config = require "plugins.crowdsec.config"
|
||||
local iputils = require "plugins.crowdsec.iputils"
|
||||
local http = require "resty.http"
|
||||
local cjson = require "cjson"
|
||||
local cidr = require "libcidr-ffi"
|
||||
local ipmatcher = require "resty.ipmatcher"
|
||||
local bit = require 'bitop.funcs'
|
||||
cjson.decode_array_with_array_mt(true)
|
||||
|
||||
|
||||
-- contain runtime = {}
|
||||
local runtime = {}
|
||||
runtime.remediations = {}
|
||||
runtime.remediations["1"] = "ban"
|
||||
runtime.remediations["2"] = "captcha"
|
||||
|
||||
|
||||
function ipToInt( str )
|
||||
|
@ -56,7 +63,7 @@ function http_request(link)
|
|||
end
|
||||
|
||||
function parse_duration(duration)
|
||||
local match, err = ngx.re.match(duration, "((?<hours>[0-9]+)h)?((?<minutes>[0-9]+)m)?(?<seconds>[0-9]+)")
|
||||
local match, err = ngx.re.match(duration, "^((?<hours>[0-9]+)h)?((?<minutes>[0-9]+)m)?(?<seconds>[0-9]+)")
|
||||
local ttl = 0
|
||||
if not match then
|
||||
if err then
|
||||
|
@ -78,11 +85,52 @@ function parse_duration(duration)
|
|||
return ttl, nil
|
||||
end
|
||||
|
||||
function get_remediation_id(remediation)
|
||||
for key, value in pairs(runtime.remediations) do
|
||||
if value == remediation then
|
||||
return tonumber(key)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function item_to_string(item)
|
||||
local ip, err = cidr.from_str(item)
|
||||
if ip == nil then
|
||||
return "normal_"..item
|
||||
end
|
||||
|
||||
local ip_version, ip_netmask, ip_network_address
|
||||
local res = ipmatcher.parse_ipv4(cidr.to_str(ip, cidr.flags.ONLYADDR))
|
||||
if res ~= false then
|
||||
ip_version = "ipv4"
|
||||
ip_network_address = res
|
||||
end
|
||||
local res = ipmatcher.parse_ipv6(cidr.to_str(ip, cidr.flags.ONLYADDR))
|
||||
if res ~= false then
|
||||
ip_version = "ipv6"
|
||||
ip_network_address = res
|
||||
end
|
||||
|
||||
local netmask_str = cidr.to_str(ip, cidr.flags.NETMASK)
|
||||
for i in netmask_str.gmatch(netmask_str, "([^\\/]+)") do
|
||||
netmask_str = i
|
||||
end
|
||||
if ip_version == "ipv4" then
|
||||
ip_netmask = ipmatcher.parse_ipv4(netmask_str)
|
||||
else
|
||||
ip_netmask = ipmatcher.parse_ipv6(netmask_str)
|
||||
end
|
||||
|
||||
return ip_version.."_"..ip_netmask.."_"..ip_network_address
|
||||
end
|
||||
|
||||
function stream_query()
|
||||
-- As this function is running inside coroutine (with ngx.timer.every),
|
||||
-- we need to raise error instead of returning them
|
||||
ngx.log(ngx.DEBUG, "Stream Query from worker : " .. tostring(ngx.worker.id()) .. " with startup "..tostring(runtime.cache:get("startup")))
|
||||
local link = runtime.conf["API_URL"] .. "/v1/decisions/stream?startup=" .. tostring(runtime.cache:get("startup"))
|
||||
local is_startup = runtime.cache:get("startup")
|
||||
ngx.log(ngx.DEBUG, "Stream Query from worker : " .. tostring(ngx.worker.id()) .. " with startup "..tostring(is_startup))
|
||||
local link = runtime.conf["API_URL"] .. "/v1/decisions/stream?startup=" .. tostring(is_startup)
|
||||
local res, err = http_request(link)
|
||||
if not res then
|
||||
error("request failed: ".. err)
|
||||
|
@ -97,9 +145,12 @@ function stream_query()
|
|||
local decisions = cjson.decode(body)
|
||||
-- process deleted decisions
|
||||
if type(decisions.deleted) == "table" then
|
||||
for i, decision in pairs(decisions.deleted) do
|
||||
runtime.cache:delete(decision.value)
|
||||
ngx.log(ngx.DEBUG, "Deleting '" .. decision.value .. "'")
|
||||
if not is_startup then
|
||||
for i, decision in pairs(decisions.deleted) do
|
||||
local key = item_to_string(decision.value)
|
||||
runtime.cache:delete(key)
|
||||
ngx.log(ngx.DEBUG, "Deleting '" .. key .. "'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -111,14 +162,19 @@ function stream_query()
|
|||
if err ~= nil then
|
||||
ngx.log(ngx.ERR, "[Crowdsec] failed to parse ban duration '" .. decision.duration .. "' : " .. err)
|
||||
end
|
||||
local succ, err, forcible = runtime.cache:set(decision.value, false, ttl)
|
||||
local remediation_id = get_remediation_id(decision.type)
|
||||
if remediation_id == nil then
|
||||
remediation_id = 1
|
||||
end
|
||||
local key = item_to_string(decision.value)
|
||||
local succ, err, forcible = runtime.cache:set(key, false, ttl, remediation_id)
|
||||
if not succ then
|
||||
ngx.log(ngx.ERR, "failed to add ".. decision.value .." : "..err)
|
||||
end
|
||||
if forcible then
|
||||
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
|
||||
end
|
||||
ngx.log(ngx.DEBUG, "Adding '" .. decision.value .. "' in cache for '" .. ttl .. "' seconds")
|
||||
ngx.log(ngx.DEBUG, "Adding '" .. key .. "' in cache for '" .. ttl .. "' seconds")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -167,7 +223,7 @@ end
|
|||
|
||||
function csmod.allowIp(ip)
|
||||
if runtime.conf == nil then
|
||||
return true, "Configuration is bad, cannot run properly"
|
||||
return true, runtime.conf["BOUNCING_ON_TYPE"], "Configuration is bad, cannot run properly"
|
||||
end
|
||||
|
||||
-- if it stream mode and startup start timer
|
||||
|
@ -180,24 +236,43 @@ function csmod.allowIp(ip)
|
|||
end
|
||||
if not ok then
|
||||
runtime.cache:set("first_run", true)
|
||||
return true, "Failed to create the timer: " .. (err or "unknown")
|
||||
return true, runtime.conf["BOUNCING_ON_TYPE"], "Failed to create the timer: " .. (err or "unknown")
|
||||
end
|
||||
runtime.cache:set("first_run", false)
|
||||
ngx.log(ngx.DEBUG, "Timer launched")
|
||||
end
|
||||
|
||||
local data = runtime.cache:get(ip)
|
||||
if data ~= nil then -- we have it in cache
|
||||
ngx.log(ngx.DEBUG, "'" .. ip .. "' is in cache")
|
||||
return data, nil
|
||||
local key = item_to_string(ip)
|
||||
local key_parts = {}
|
||||
for i in key.gmatch(key, "([^_]+)") do
|
||||
table.insert(key_parts, i)
|
||||
end
|
||||
local key_type = key_parts[1]
|
||||
if key_type == "normal" then
|
||||
local in_cache, remediation_id = runtime.cache:get(key)
|
||||
if in_cache ~= nil then -- we have it in cache
|
||||
ngx.log(ngx.DEBUG, "'" .. key .. "' is in cache")
|
||||
return in_cache, runtime.remediations[tostring(remediation_id)], nil
|
||||
end
|
||||
end
|
||||
|
||||
local ip_network_address = tonumber(key_parts[3])
|
||||
local netmasks = iputils.netmasks_by_key_type[key_type]
|
||||
for _, netmask in pairs(netmasks) do
|
||||
local item = key_type.."_"..netmask.."_"..tostring(bit.band(ip_network_address, netmask))
|
||||
in_cache, remediation_id = runtime.cache:get(item)
|
||||
if in_cache ~= nil then -- we have it in cache
|
||||
ngx.log(ngx.DEBUG, "'" .. key .. "' is in cache")
|
||||
return in_cache, runtime.remediations[tostring(remediation_id)], nil
|
||||
end
|
||||
end
|
||||
|
||||
-- if live mode, query lapi
|
||||
if runtime.conf["MODE"] == "live" then
|
||||
local ok, err = live_query(ip)
|
||||
return ok, err
|
||||
return ok, runtime.conf["BOUNCING_ON_TYPE"], err
|
||||
end
|
||||
return true, nil
|
||||
return true, runtime.conf["BOUNCING_ON_TYPE"], nil
|
||||
end
|
||||
|
||||
|
||||
|
|
61
nginx/iputils.lua
Normal file
61
nginx/iputils.lua
Normal file
|
@ -0,0 +1,61 @@
|
|||
local _M = {}
|
||||
|
||||
local ipv4_netmasks = {
|
||||
4294967295, 4294967294, 4294967292, 4294967288, 4294967280, 4294967264, 4294967232, 4294967168, 4294967040, 4294966784,
|
||||
4294966272, 4294965248, 4294963200, 4294959104, 4294950912, 4294934528, 4294901760, 4294836224, 4294705152, 4294443008,
|
||||
4293918720, 4292870144, 4290772992, 4286578688, 4278190080, 4261412864, 4227858432, 4160749568, 4026531840, 3758096384, 3221225472, 2147483648, 0
|
||||
}
|
||||
|
||||
local ipv6_netmasks = {
|
||||
340282366920938463463374607431768211455, 340282366920938463463374607431768211454, 340282366920938463463374607431768211452,
|
||||
340282366920938463463374607431768211448, 340282366920938463463374607431768211440, 340282366920938463463374607431768211424,
|
||||
340282366920938463463374607431768211392, 340282366920938463463374607431768211328, 340282366920938463463374607431768211200,
|
||||
340282366920938463463374607431768210944, 340282366920938463463374607431768210432, 340282366920938463463374607431768209408,
|
||||
340282366920938463463374607431768207360, 340282366920938463463374607431768203264, 340282366920938463463374607431768195072,
|
||||
340282366920938463463374607431768178688, 340282366920938463463374607431768145920, 340282366920938463463374607431768080384,
|
||||
340282366920938463463374607431767949312, 340282366920938463463374607431767687168, 340282366920938463463374607431767162880,
|
||||
340282366920938463463374607431766114304, 340282366920938463463374607431764017152, 340282366920938463463374607431759822848,
|
||||
340282366920938463463374607431751434240, 340282366920938463463374607431734657024, 340282366920938463463374607431701102592,
|
||||
340282366920938463463374607431633993728, 340282366920938463463374607431499776000, 340282366920938463463374607431231340544,
|
||||
340282366920938463463374607430694469632, 340282366920938463463374607429620727808, 340282366920938463463374607427473244160,
|
||||
340282366920938463463374607423178276864, 340282366920938463463374607414588342272, 340282366920938463463374607397408473088,
|
||||
340282366920938463463374607363048734720, 340282366920938463463374607294329257984, 340282366920938463463374607156890304512,
|
||||
340282366920938463463374606882012397568, 340282366920938463463374606332256583680, 340282366920938463463374605232744955904,
|
||||
340282366920938463463374603033721700352, 340282366920938463463374598635675189248, 340282366920938463463374589839582167040,
|
||||
340282366920938463463374572247396122624, 340282366920938463463374537063024033792, 340282366920938463463374466694279856128,
|
||||
340282366920938463463374325956791500800, 340282366920938463463374044481814790144, 340282366920938463463373481531861368832,
|
||||
340282366920938463463372355631954526208, 340282366920938463463370103832140840960, 340282366920938463463365600232513470464,
|
||||
340282366920938463463356593033258729472, 340282366920938463463338578634749247488, 340282366920938463463302549837730283520,
|
||||
340282366920938463463230492243692355584, 340282366920938463463086377055616499712, 340282366920938463462798146679464787968,
|
||||
340282366920938463462221685927161364480, 340282366920938463461068764422554517504, 340282366920938463458762921413340823552,
|
||||
340282366920938463454151235394913435648, 340282366920938463444927863358058659840, 340282366920938463426481119284349108224,
|
||||
340282366920938463389587631136930004992, 340282366920938463315800654842091798528, 340282366920938463168226702252415385600,
|
||||
340282366920938462873078797073062559744, 340282366920938462282782986714356908032, 340282366920938461102191365996945604608,
|
||||
340282366920938458741008124562122997760, 340282366920938454018641641692477784064, 340282366920938444573908675953187356672,
|
||||
340282366920938425684442744474606501888, 340282366920938387905510881517444792320, 340282366920938312347647155603121373184,
|
||||
340282366920938161231919703774474534912, 340282366920937859000464800117180858368, 340282366920937254537554992802593505280,
|
||||
340282366920936045611735378173418799104, 340282366920933627760096148915069386752, 340282366920928792056817690398370562048,
|
||||
340282366920919120650260773364972912640, 340282366920899777837146939298177613824, 340282366920861092210919271164587016192,
|
||||
340282366920783720958463934897405820928, 340282366920628978453553262363043430400, 340282366920319493443731917294318649344,
|
||||
340282366919700523424089227156869087232, 340282366918462583384803846881969963008, 340282366915986703306233086332171714560,
|
||||
340282366911034943149091565232575217664, 340282366901131422834808523033382223872, 340282366881324382206242438634996236288,
|
||||
340282366841710300949110269838224261120, 340282366762482138434845932244680310784, 340282366604025813406317257057592410112,
|
||||
340282366287113163349259906683416608768, 340282365653287863235145205935065006080, 340282364385637263006915804438361800704,
|
||||
340282361850336062550457001444955389952, 340282356779733661637539395458142568448, 340282346638528859811704183484516925440,
|
||||
340282326356119256160033759537265639424, 340282285791300048856692911642763067392, 340282204661661634250011215853757923328,
|
||||
340282042402384805036647824275747635200, 340281717883831146609921041119727058944, 340281068846723829756467474807685906432,
|
||||
340279770772509196049560342183603601408, 340277174624079928635746076935438991360, 340271982327221393808117546439109771264,
|
||||
340261597733504324152860485446451331072, 340240828546070184842346363461134450688, 340199290171201906221318119490500689920,
|
||||
340116213421465348979261631549233168384, 339950059921992234495148655666698125312, 339617752923046005526922703901628039168,
|
||||
338953138925153547590470800371487866880, 337623910929368631717566993311207522304, 334965454937798799971759379190646833152,
|
||||
329648542954659136480144150949525454848, 319014718988379809496913694467282698240, 297747071055821155530452781502797185024,
|
||||
255211775190703847597530955573826158592, 170141183460469231731687303715884105728, 0
|
||||
}
|
||||
|
||||
local netmasks_by_key_type = {}
|
||||
netmasks_by_key_type["ipv4"] = ipv4_netmasks
|
||||
netmasks_by_key_type["ipv6"] = ipv6_netmasks
|
||||
|
||||
_M.netmasks_by_key_type = netmasks_by_key_type
|
||||
|
||||
return _M
|
Loading…
Add table
Reference in a new issue