bw - init work on detect only mode

This commit is contained in:
fl0ppy-d1sk 2024-11-15 14:47:21 +01:00
parent 826631291f
commit 14a0b7dc1c
No known key found for this signature in database
GPG key ID: 93EE47CC3D061500
7 changed files with 57 additions and 12 deletions

View file

@ -289,8 +289,9 @@ end
utils.get_reason = function(ctx)
-- ngx.ctx
if ctx and ctx.bw and ctx.bw.reason then
return ctx.bw.reason, ctx.bw.reason_data or {}
return ctx.bw.reason, ctx.bw.reason_data or {}, ctx.bw.security_mode
end
local security_mode = utils.get_security_mode(ctx)
-- ngx.var
local var_reason = var.reason
if var_reason and var_reason ~= "" then
@ -302,11 +303,11 @@ utils.get_reason = function(ctx)
reason_data = data
end
end
return var_reason, reason_data
return var_reason, reason_data, security_mode
end
-- os.getenv
if os.getenv("REASON") == "modsecurity" then
return "modsecurity", {}
return "modsecurity", {}, security_mode
end
-- datastore ban
local ip
@ -321,7 +322,7 @@ utils.get_reason = function(ctx)
if ok then
banned = ban_data["reason"]
end
return banned, {}
return banned, {}, security_mode
end
-- unknown
if ngx.status == utils.get_deny_status() then
@ -330,10 +331,11 @@ utils.get_reason = function(ctx)
return nil
end
utils.set_reason = function(reason, reason_data, ctx)
utils.set_reason = function(reason, reason_data, ctx, security_mode)
if ctx and ctx.bw then
ctx.bw.reason = reason or "unknown"
ctx.bw.reason_data = reason_data or {}
ctx.bw.security_mode = security_mode
end
if var.reason then
var.reason = reason
@ -572,6 +574,14 @@ utils.get_deny_status = function()
return 444
end
utils.get_security_mode = function(ctx)
local security_mode, err = utils.get_variable("SECURITY_MODE", true, ctx)
if not security_mode then
return "block"
end
return security_mode
end
utils.get_session = function(ctx)
-- Return session from ctx if already there
if ctx.bw.sessions_session then

View file

@ -13,6 +13,7 @@ access_by_lua_block {
local INFO = ngx.INFO
local WARN = ngx.WARN
local NOTICE = ngx.NOTICE
local OK = ngx.OK
local HTTP_MOVED_TEMPORARILY = ngx.HTTP_MOVED_TEMPORARILY
local fill_ctx = helpers.fill_ctx
local save_ctx = helpers.save_ctx
@ -24,6 +25,7 @@ access_by_lua_block {
local set_reason = utils.set_reason
local get_deny_status = utils.get_deny_status
local save_session = utils.save_session
local get_security_mode = utils.get_security_mode
local tostring = tostring
-- Don't process internal requests
@ -49,6 +51,9 @@ access_by_lua_block {
end
logger:log(INFO, "ngx.ctx filled (ret = " .. ret .. ")")
-- Get security mode
local security_mode = get_security_mode(ctx)
-- Process bans as soon as possible
if not is_whitelisted(ctx) then
local banned, reason, ttl = is_banned(ctx.bw.remote_addr)
@ -56,11 +61,16 @@ access_by_lua_block {
logger:log(ERR, "can't check if IP " .. ctx.bw.remote_addr .. " is banned : " .. reason)
elseif banned then
ctx.bw.is_banned = true
set_reason(reason, {}, ctx)
set_reason(reason, {}, ctx, security_mode)
save_ctx(ctx)
if security_mode == "block" then
logger:log(WARN,
"IP " .. ctx.bw.remote_addr .. " is banned with reason " .. reason .. " (" .. tostring(ttl) .. "s remaining)")
return exit(get_deny_status())
end
logger:log(WARN,
"IP " .. ctx.bw.remote_addr .. " is banned with reason " .. reason .. " (" .. tostring(ttl) .. "s remaining)")
return exit(get_deny_status())
"detected IP " .. ctx.bw.remote_addr .. " ban with reason " .. reason .. " (" .. tostring(ttl) .. "s remaining)")
return exit(OK)
else
logger:log(INFO, "IP " .. ctx.bw.remote_addr .. " is not banned")
end
@ -101,7 +111,10 @@ access_by_lua_block {
logger:log(INFO, plugin_id .. ":access() call successful : " .. ret.msg)
end
if ret.status and not ret.redirect then
if ret.status == get_deny_status() then
if security_mode == "detect" then
logger:log(WARN, "detected deny access from " .. plugin_id .. " : " .. ret.msg)
break
elseif ret.status == get_deny_status() then
set_reason(plugin_id, ret.data, ctx)
logger:log(WARN, "denied access from " .. plugin_id .. " : " .. ret.msg)
else

View file

@ -74,9 +74,13 @@ log_by_lua_block {
logger:log(INFO, "called log() methods of plugins")
-- Display reason at info level
local reason, reason_data = get_reason(ctx)
local reason, reason_data, security_mode = get_reason(ctx)
if reason then
logger:log(INFO, "client was denied with reason " .. reason .. " and data = " .. encode(reason_data))
if security_mode == "block" then
logger:log(INFO, "client was denied with reason " .. reason .. " and data = " .. encode(reason_data))
else
logger:log(INFO, "detected client deny with reason " .. reason .. " and data = " .. encode(reason_data))
end
end
logger:log(INFO, "log phase ended")

View file

@ -52,7 +52,7 @@ function metrics:log(bypass_checks)
return self:ret(true, "metrics are disabled")
end
-- Store blocked requests
local reason, data = get_reason(self.ctx)
local reason, data, security_mode = get_reason(self.ctx)
if reason then
local country = "local"
local err
@ -74,6 +74,7 @@ function metrics:log(bypass_checks)
reason = reason,
server_name = self.ctx.bw.server_name,
data = data,
security_mode = security_mode
}
-- Get current requests
local requests = lru:get("requests")

View file

@ -2,7 +2,11 @@
{% set json = import("json") %}
{% set service_id = SERVER_NAME.split(" ")[0] %}
# process rules with disruptive actions
{% if SECURITY_MODE == "block" %}
SecRuleEngine {{ MODSECURITY_SEC_RULE_ENGINE }}
{% else %}
SecRuleEngine DetectionOnly
{% endif %}
# allow body checks
SecRequestBodyAccess On

View file

@ -343,5 +343,14 @@
"label": "Use template",
"regex": "^.*$",
"type": "text"
},
"SECURITY_MODE": {
"context": "multisite",
"default": "block",
"help": "Defines the response to threats: \"detect\" to monitor and log, or \"block\" to prevent access and log incidents.",
"id": "security-mode",
"label": "Security mode",
"regex": "^(detect|block)$",
"type": "check"
}
}

View file

@ -40,6 +40,9 @@
<th data-bs-toggle="tooltip"
data-bs-placement="bottom"
data-bs-original-title="Additional data about the Report">Data</th>
<th data-bs-toggle="tooltip"
data-bs-placement="bottom"
data-bs-original-title="Security mode">Security mode</th>
</tr>
</thead>
<tbody>
@ -74,6 +77,7 @@
<td>{{ report["reason"] }}</td>
<td>{{ report["server_name"] }}</td>
<td>{{ report["data"] }}</td>
<td>{{ report["security_mode"] }}</td>
</tr>
{% endfor %}
</tbody>