range support method 1

This commit is contained in:
he2ss 2022-01-13 09:48:05 +01:00
parent b9529e8a51
commit 4db2cda499
3 changed files with 155 additions and 18 deletions

View file

@ -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

View file

@ -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
View 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