diff --git a/src/common/core/badbehavior/badbehavior.lua b/src/common/core/badbehavior/badbehavior.lua index 1461242eb..87a59cb64 100644 --- a/src/common/core/badbehavior/badbehavior.lua +++ b/src/common/core/badbehavior/badbehavior.lua @@ -12,6 +12,7 @@ local timer_at = ngx.timer.at local add_ban = utils.add_ban local is_whitelisted = utils.is_whitelisted local is_banned = utils.is_banned +local get_security_mode = utils.get_security_mode local tostring = tostring function badbehavior:initialize(ctx) @@ -36,6 +37,8 @@ function badbehavior:log() if is_banned(self.ctx.bw.remote_addr) then return self:ret(true, "already banned") end + -- Get security mode + local security_mode = get_security_mode(self.ctx) -- Call increase function later and with cosocket enabled local ok, err = timer_at( 0, @@ -45,7 +48,8 @@ function badbehavior:log() tonumber(self.variables["BAD_BEHAVIOR_BAN_TIME"]), tonumber(self.variables["BAD_BEHAVIOR_THRESHOLD"]), self.use_redis, - self.ctx.bw.server_name + self.ctx.bw.server_name, + security_mode ) if not ok then return self:ret(false, "can't create increase timer : " .. err) @@ -63,7 +67,7 @@ function badbehavior:log_stream() end -- luacheck: ignore 212 -function badbehavior.increase(premature, ip, count_time, ban_time, threshold, use_redis, server_name) +function badbehavior.increase(premature, ip, count_time, ban_time, threshold, use_redis, server_name, security_mode) -- Instantiate objects local logger = require "bunkerweb.logger":new("badbehavior") local datastore = require "bunkerweb.datastore":new() @@ -103,23 +107,38 @@ function badbehavior.increase(premature, ip, count_time, ban_time, threshold, us end -- Store local ban if counter > threshold then - ok, err = add_ban(ip, "bad behavior", ban_time, server_name) - if not ok then - logger:log(ERR, "(increase) can't save ban : " .. err) - return + if security_mode == "block" then + ok, err = add_ban(ip, "bad behavior", ban_time, server_name) + if not ok then + logger:log(ERR, "(increase) can't save ban : " .. err) + return + end + logger:log( + WARN, + "IP " + .. ip + .. " is banned for " + .. ban_time + .. "s (" + .. tostring(counter) + .. "/" + .. tostring(threshold) + .. ")" + ) + else + logger:log( + WARN, + "detected IP " + .. ip + .. " ban for " + .. ban_time + .. "s (" + .. tostring(counter) + .. "/" + .. tostring(threshold) + .. ")" + ) end - logger:log( - WARN, - "IP " - .. ip - .. " is banned for " - .. ban_time - .. "s (" - .. tostring(counter) - .. "/" - .. tostring(threshold) - .. ")" - ) end logger:log( NOTICE, diff --git a/src/common/core/limit/limit.lua b/src/common/core/limit/limit.lua index 59d2b49fb..78c639fe5 100644 --- a/src/common/core/limit/limit.lua +++ b/src/common/core/limit/limit.lua @@ -13,6 +13,7 @@ local has_variable = utils.has_variable local get_multiple_variables = utils.get_multiple_variables local is_whitelisted = utils.is_whitelisted local regex_match = utils.regex_match +local security_mode = utils.get_security_mode local time = os.time local date = os.date local encode = cjson.encode @@ -159,21 +160,40 @@ function limit:access() -- Limit reached if limited then self:set_metric("counters", "limited_uri_" .. self.ctx.bw.uri, 1) - return self:ret( - true, - "client IP " - .. self.ctx.bw.remote_addr - .. " is limited for URL " - .. self.ctx.bw.uri - .. " (current rate = " - .. current_rate - .. "r/" - .. rate_time - .. " and max rate = " - .. rate - .. ")", - HTTP_TOO_MANY_REQUESTS - ) + local security_mode = get_security_mode(self.ctx) + if security_mode == "block" then + return self:ret( + true, + "client IP " + .. self.ctx.bw.remote_addr + .. " is limited for URL " + .. self.ctx.bw.uri + .. " (current rate = " + .. current_rate + .. "r/" + .. rate_time + .. " and max rate = " + .. rate + .. ")", + HTTP_TOO_MANY_REQUESTS + ) + else + return self:ret( + true, + "detected client IP " + .. self.ctx.bw.remote_addr + .. " limit for URL " + .. self.ctx.bw.uri + .. " (current rate = " + .. current_rate + .. "r/" + .. rate_time + .. " and max rate = " + .. rate + .. ")", + HTTP_TOO_MANY_REQUESTS + ) + end end -- Limit not reached return self:ret( diff --git a/src/common/core/misc/misc.lua b/src/common/core/misc/misc.lua index e1ef0f417..f9b14149c 100644 --- a/src/common/core/misc/misc.lua +++ b/src/common/core/misc/misc.lua @@ -8,6 +8,7 @@ local ngx = ngx local HTTP_NOT_ALLOWED = ngx.HTTP_NOT_ALLOWED local HTTP_BAD_REQUEST = ngx.HTTP_BAD_REQUEST local HTTP_MOVED_PERMANENTLY = ngx.HTTP_MOVED_PERMANENTLY +local get_security_mode = utils.get_security_mode local regex_match = utils.regex_match function misc:initialize(ctx) @@ -43,7 +44,11 @@ function misc:access() end end self:set_metric("counters", "failed_method", 1) - return self:ret(true, "method " .. method .. " is not allowed", HTTP_NOT_ALLOWED) + local security_mode = get_security_mode(self.ctx) + if security_mode == "block" then + return self:ret(true, "method " .. method .. " is not allowed", HTTP_NOT_ALLOWED) + end + return self:ret(true, "detected method " .. method .. " not allowed") end function misc:header() diff --git a/src/common/settings.json b/src/common/settings.json index c576e7927..984ed277f 100644 --- a/src/common/settings.json +++ b/src/common/settings.json @@ -351,6 +351,10 @@ "id": "security-mode", "label": "Security mode", "regex": "^(detect|block)$", - "type": "check" + "type": "select", + "select": [ + "detect", + "block" + ] } } diff --git a/src/ui/app/static/js/pages/reports.js b/src/ui/app/static/js/pages/reports.js index 8c0b12215..153b354ae 100644 --- a/src/ui/app/static/js/pages/reports.js +++ b/src/ui/app/static/js/pages/reports.js @@ -436,7 +436,7 @@ $(function () { const reports_table = new DataTable("#reports", { columnDefs: [ { orderable: false, targets: -1 }, - { visible: false, targets: [6, -1] }, + { visible: false, targets: [6, 9] }, { type: "ip-address", targets: 1 }, { targets: 0,