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
|
end
|
||||||
|
|
||||||
|
|
||||||
function csmod.AppSecCheck()
|
function csmod.AppSecCheck(ip)
|
||||||
local httpc = http.new()
|
local httpc = http.new()
|
||||||
httpc:set_timeouts(runtime.conf["APPSEC_CONNECT_TIMEOUT"], runtime.conf["APPSEC_SEND_TIMEOUT"], runtime.conf["APPSEC_PROCESS_TIMEOUT"])
|
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()
|
local headers = ngx.req.get_headers()
|
||||||
|
|
||||||
-- overwrite headers with crowdsec appsec require 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-host"] = ngx.var.http_host
|
||||||
headers["x-crowdsec-appsec-verb"] = ngx.var.request_method
|
headers["x-crowdsec-appsec-verb"] = ngx.var.request_method
|
||||||
headers["x-crowdsec-appsec-uri"] = uri
|
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)
|
-- 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 ok == true or runtime.conf["ALWAYS_SEND_TO_APPSEC"] == true then
|
||||||
if runtime.conf["APPSEC_ENABLED"] == true and ngx.var.no_appsec ~= "1" 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
|
if err ~= nil then
|
||||||
ngx.log(ngx.ERR, "AppSec check: " .. err)
|
ngx.log(ngx.ERR, "AppSec check: " .. err)
|
||||||
end
|
end
|
||||||
|
@ -630,13 +630,13 @@ function csmod.Allow(ip)
|
||||||
|
|
||||||
if captcha_ok then -- if captcha can be use (configuration is valid)
|
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
|
-- 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)
|
local source, state_id, err = flag.GetFlags(flags)
|
||||||
if previous_uri ~= nil and state_id == flag.VERIFY_STATE then
|
if previous_uri ~= nil and state_id == flag.VERIFY_STATE then
|
||||||
ngx.req.read_body()
|
ngx.req.read_body()
|
||||||
local captcha_res = ngx.req.get_post_args()[csmod.GetCaptchaBackendKey()] or 0
|
local captcha_res = ngx.req.get_post_args()[csmod.GetCaptchaBackendKey()] or 0
|
||||||
if captcha_res ~= 0 then
|
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
|
if err ~= nil then
|
||||||
ngx.log(ngx.ERR, "Error while validating captcha: " .. err)
|
ngx.log(ngx.ERR, "Error while validating captcha: " .. err)
|
||||||
end
|
end
|
||||||
|
@ -646,11 +646,11 @@ function csmod.Allow(ip)
|
||||||
-- we will not propose a captcha until the 'CAPTCHA_EXPIRATION'.
|
-- 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.
|
-- But for the Application security component, we serve the captcha each time the user trigger it.
|
||||||
if source == flag.APPSEC_SOURCE then
|
if source == flag.APPSEC_SOURCE then
|
||||||
ngx.shared.crowdsec_cache:delete("captcha_"..ngx.var.remote_addr)
|
ngx.shared.crowdsec_cache:delete("captcha_"..ip)
|
||||||
else
|
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
|
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
|
end
|
||||||
if forcible then
|
if forcible then
|
||||||
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
|
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)
|
ngx.redirect(previous_uri)
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
ngx.log(ngx.ALERT, "Invalid captcha from " .. ngx.var.remote_addr)
|
ngx.log(ngx.ALERT, "Invalid captcha from " .. ip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not ok then
|
if not ok then
|
||||||
if remediation == "ban" 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()
|
ban.apply()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- if the remediation is a captcha and captcha is well configured
|
-- if the remediation is a captcha and captcha is well configured
|
||||||
if remediation == "captcha" and captcha_ok and ngx.var.uri ~= "/favicon.ico" then
|
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)
|
local previous_uri, flags = ngx.shared.crowdsec_cache:get("captcha_"..ip)
|
||||||
source, state_id, err = flag.GetFlags(flags)
|
local source, state_id, err = flag.GetFlags(flags)
|
||||||
-- we check if the IP is already in cache for captcha and not yet validated
|
-- 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.content_type = "text/html"
|
||||||
ngx.header.cache_control = "no-cache"
|
ngx.header.cache_control = "no-cache"
|
||||||
ngx.say(csmod.GetCaptchaTemplate())
|
ngx.say(csmod.GetCaptchaTemplate())
|
||||||
|
@ -691,14 +691,14 @@ function csmod.Allow(ip)
|
||||||
end
|
end
|
||||||
end
|
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
|
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
|
end
|
||||||
if forcible then
|
if forcible then
|
||||||
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
|
ngx.log(ngx.ERR, "Lua shared dict (crowdsec cache) is full, please increase dict size in config")
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,28 +25,19 @@ function M.GetFlags(flags)
|
||||||
return source, state, err
|
return source, state, err
|
||||||
end
|
end
|
||||||
|
|
||||||
if bit.band(flags, M.BOUNCER_SOURCE) then
|
if bit.band(flags, M.BOUNCER_SOURCE) ~= 0 then
|
||||||
source = M.BOUNCER_SOURCE
|
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
|
source = M.APPSEC_SOURCE
|
||||||
end
|
end
|
||||||
|
|
||||||
if bit.band(flags, M.VERIFY_STATE) then
|
if bit.band(flags, M.VERIFY_STATE) ~= 0 then
|
||||||
state = M.VERIFY_STATE
|
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
|
state = M.VALIDATED_STATE
|
||||||
end
|
end
|
||||||
return source, state, err
|
return source, state, err
|
||||||
|
|
||||||
end
|
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