fix IP usage in csmod.Allow(ip) and repair captcha for bouncing (#53)
--------- Co-authored-by: Laurence Jones <laurence.jones@live.co.uk>
This commit is contained in:
parent
cb0d72bdf1
commit
535f009e59
2 changed files with 21 additions and 30 deletions
|
@ -495,7 +495,7 @@ function csmod.allowIp(ip)
|
|||
end
|
||||
|
||||
|
||||
function csmod.AppSecCheck()
|
||||
function csmod.AppSecCheck(ip)
|
||||
local httpc = http.new()
|
||||
httpc:set_timeouts(runtime.conf["APPSEC_CONNECT_TIMEOUT"], runtime.conf["APPSEC_SEND_TIMEOUT"], runtime.conf["APPSEC_PROCESS_TIMEOUT"])
|
||||
|
||||
|
@ -503,7 +503,7 @@ function csmod.AppSecCheck()
|
|||
local headers = ngx.req.get_headers()
|
||||
|
||||
-- overwrite headers with crowdsec appsec require headers
|
||||
headers["x-crowdsec-appsec-ip"] = ngx.var.remote_addr
|
||||
headers["x-crowdsec-appsec-ip"] = ip
|
||||
headers["x-crowdsec-appsec-host"] = ngx.var.http_host
|
||||
headers["x-crowdsec-appsec-verb"] = ngx.var.request_method
|
||||
headers["x-crowdsec-appsec-uri"] = uri
|
||||
|
@ -602,7 +602,7 @@ function csmod.Allow(ip)
|
|||
-- that user configured the remediation component to always check on the appSec (even if there is a decision for the IP)
|
||||
if ok == true or runtime.conf["ALWAYS_SEND_TO_APPSEC"] == true then
|
||||
if runtime.conf["APPSEC_ENABLED"] == true and ngx.var.no_appsec ~= "1" then
|
||||
local appsecOk, appsecRemediation, err = csmod.AppSecCheck()
|
||||
local appsecOk, appsecRemediation, err = csmod.AppSecCheck(ip)
|
||||
if err ~= nil then
|
||||
ngx.log(ngx.ERR, "AppSec check: " .. err)
|
||||
end
|
||||
|
@ -630,13 +630,13 @@ function csmod.Allow(ip)
|
|||
|
||||
if captcha_ok then -- if captcha can be use (configuration is valid)
|
||||
-- we check if the IP need to validate its captcha before checking it against crowdsec local API
|
||||
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ngx.var.remote_addr)
|
||||
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ip)
|
||||
local source, state_id, err = flag.GetFlags(flags)
|
||||
if previous_uri ~= nil and state_id == flag.VERIFY_STATE then
|
||||
ngx.req.read_body()
|
||||
local captcha_res = ngx.req.get_post_args()[csmod.GetCaptchaBackendKey()] or 0
|
||||
if captcha_res ~= 0 then
|
||||
local valid, err = csmod.validateCaptcha(captcha_res, ngx.var.remote_addr)
|
||||
local valid, err = csmod.validateCaptcha(captcha_res, ip)
|
||||
if err ~= nil then
|
||||
ngx.log(ngx.ERR, "Error while validating captcha: " .. err)
|
||||
end
|
||||
|
@ -646,11 +646,11 @@ function csmod.Allow(ip)
|
|||
-- we will not propose a captcha until the 'CAPTCHA_EXPIRATION'.
|
||||
-- But for the Application security component, we serve the captcha each time the user trigger it.
|
||||
if source == flag.APPSEC_SOURCE then
|
||||
ngx.shared.crowdsec_cache:delete("captcha_"..ngx.var.remote_addr)
|
||||
ngx.shared.crowdsec_cache:delete("captcha_"..ip)
|
||||
else
|
||||
local succ, err, forcible = ngx.shared.crowdsec_cache:set("captcha_"..ngx.var.remote_addr, previous_uri, runtime.conf["CAPTCHA_EXPIRATION"], bit.bor(flag.VALIDATED_STATE, source) )
|
||||
local succ, err, forcible = ngx.shared.crowdsec_cache:set("captcha_"..ip, previous_uri, runtime.conf["CAPTCHA_EXPIRATION"], bit.bor(flag.VALIDATED_STATE, source) )
|
||||
if not succ then
|
||||
ngx.log(ngx.ERR, "failed to add key about captcha for ip '" .. ngx.var.remote_addr .. "' in cache: "..err)
|
||||
ngx.log(ngx.ERR, "failed to add key about captcha for ip '" .. ip .. "' in cache: "..err)
|
||||
end
|
||||
if forcible then
|
||||
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
|
||||
|
@ -661,23 +661,23 @@ function csmod.Allow(ip)
|
|||
ngx.redirect(previous_uri)
|
||||
return
|
||||
else
|
||||
ngx.log(ngx.ALERT, "Invalid captcha from " .. ngx.var.remote_addr)
|
||||
ngx.log(ngx.ALERT, "Invalid captcha from " .. ip)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not ok then
|
||||
if remediation == "ban" then
|
||||
ngx.log(ngx.ALERT, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "' with '"..remediation.."' (by " .. flag.Flags[remediationSource] .. ")")
|
||||
ngx.log(ngx.ALERT, "[Crowdsec] denied '" .. ip .. "' with '"..remediation.."' (by " .. flag.Flags[remediationSource] .. ")")
|
||||
ban.apply()
|
||||
return
|
||||
end
|
||||
-- if the remediation is a captcha and captcha is well configured
|
||||
if remediation == "captcha" and captcha_ok and ngx.var.uri ~= "/favicon.ico" then
|
||||
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ngx.var.remote_addr)
|
||||
source, state_id, err = flag.GetFlags(flags)
|
||||
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ip)
|
||||
local source, state_id, err = flag.GetFlags(flags)
|
||||
-- we check if the IP is already in cache for captcha and not yet validated
|
||||
if previous_uri == nil or remediationSource == flag.APPSEC_SOURCE then
|
||||
if previous_uri == nil or state_id ~= flag.VALIDATED_STATE or remediationSource == flag.APPSEC_SOURCE then
|
||||
ngx.header.content_type = "text/html"
|
||||
ngx.header.cache_control = "no-cache"
|
||||
ngx.say(csmod.GetCaptchaTemplate())
|
||||
|
@ -691,14 +691,14 @@ function csmod.Allow(ip)
|
|||
end
|
||||
end
|
||||
end
|
||||
local succ, err, forcible = ngx.shared.crowdsec_cache:set("captcha_"..ngx.var.remote_addr, uri , 60, bit.bor(flag.VERIFY_STATE, remediationSource))
|
||||
local succ, err, forcible = ngx.shared.crowdsec_cache:set("captcha_"..ip, uri , 60, bit.bor(flag.VERIFY_STATE, remediationSource))
|
||||
if not succ then
|
||||
ngx.log(ngx.ERR, "failed to add key about captcha for ip '" .. ngx.var.remote_addr .. "' in cache: "..err)
|
||||
ngx.log(ngx.ERR, "failed to add key about captcha for ip '" .. ip .. "' in cache: "..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.ALERT, "[Crowdsec] denied '" .. ngx.var.remote_addr .. "' with '"..remediation.."'")
|
||||
ngx.log(ngx.ALERT, "[Crowdsec] denied '" .. ip .. "' with '"..remediation.."'")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,28 +25,19 @@ function M.GetFlags(flags)
|
|||
return source, state, err
|
||||
end
|
||||
|
||||
if bit.band(flags, M.BOUNCER_SOURCE) then
|
||||
if bit.band(flags, M.BOUNCER_SOURCE) ~= 0 then
|
||||
source = M.BOUNCER_SOURCE
|
||||
elseif bit.band(flags, M.APPSEC_SOURCE) then
|
||||
elseif bit.band(flags, M.APPSEC_SOURCE) ~= 0 then
|
||||
source = M.APPSEC_SOURCE
|
||||
end
|
||||
|
||||
if bit.band(flags, M.VERIFY_STATE) then
|
||||
if bit.band(flags, M.VERIFY_STATE) ~= 0 then
|
||||
state = M.VERIFY_STATE
|
||||
elseif bit.band(flags, M.VALIDATED_STATE) then
|
||||
elseif bit.band(flags, M.VALIDATED_STATE) ~= 0 then
|
||||
state = M.VALIDATED_STATE
|
||||
end
|
||||
return source, state, err
|
||||
|
||||
end
|
||||
|
||||
function M.GetStateID(state)
|
||||
for k, v in pairs(M.State) do
|
||||
if v == state then
|
||||
return tonumber(k)
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
return M
|
||||
return M
|
||||
|
|
Loading…
Reference in a new issue