refactor - disable asn checks for non global IPs, use resty.template with antibot and various fixes

This commit is contained in:
florian 2023-04-17 22:43:28 +02:00
parent 8d63e39740
commit 2fddbd8627
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
13 changed files with 167 additions and 135 deletions

3
TODO
View File

@ -1,5 +1,6 @@
- utils refactoring
- use resty.template for antibot
- load inline values for white/black/grey list core
- check if correct setting is set to yes in new() before loading stuff in self
- store object in ngx.ctx
- bwcli with redis
- move bans to cachestore

View File

@ -31,7 +31,7 @@ if not ok then
end
-- Process bans as soon as possible
local ok, reason = cachestore:get("bans_ip_" .. ngx.var.remote_addr)
local ok, reason = datastore:get("bans_ip_" .. ngx.var.remote_addr)
if not ok and reason then
logger:log(ngx.INFO, "error while checking if client is banned : " .. reason)
return false

View File

@ -8,40 +8,13 @@ local base64 = require "base64"
local sha256 = require "resty.sha256"
local str = require "resty.string"
local http = require "resty.http"
local template = require "resty.template"
local antibot = class("antibot", plugin)
function antibot:initialize()
-- Call parent initialize
plugin.initialize(self, "antibot")
-- Check if init is needed
if ngx.get_phase() == "init" then
local init_needed, err = utils.has_not_variable("USE_ANTIBOT", "no")
if init_needed == nil then
self.logger:log(ngx.ERR, err)
end
self.init_needed = init_needed
end
end
function antibot:init()
if self.init_needed then
-- Load templates
local templates = {}
for i, template in ipairs({ "javascript", "captcha", "recaptcha", "hcaptcha" }) do
local f, err = io.open("/usr/share/bunkerweb/core/antibot/files/" .. template .. ".html")
if not f then
return self:ret(false, "error while loading " .. template .. ".html : " .. err)
end
templates[template] = f:read("*all")
f:close()
end
local ok, err = self.datastore:set("plugin_antibot_templates", cjson.encode(templates))
if not ok then
return self:ret(false, "can't save templates to datastore : " .. err)
end
end
return self:ret(true, "success")
end
function antibot:access()
@ -195,38 +168,33 @@ function antibot:display_challenge(challenge_uri)
return false, "session type is different from antibot type"
end
-- Load HTML templates
local str_templates, err = self.datastore:get("plugin_antibot_templates")
if not str_templates then
return false, "can't get templates from datastore : " .. err
end
local templates = cjson.decode(str_templates)
local html = ""
-- Common variables for templates
local template_vars = {
antibot_uri = self.variables["ANTIBOT_URI"]
}
-- Javascript case
if self.variables["USE_ANTIBOT"] == "javascript" then
html = templates.javascript:format(self.variables["ANTIBOT_URI"], data.random)
template_vars.random = data.random
end
-- Captcha case
if self.variables["USE_ANTIBOT"] == "captcha" then
html = templates.captcha:format(self.variables["ANTIBOT_URI"], data.image)
template_vars.captcha = data.image
end
-- reCAPTCHA case
if self.variables["USE_ANTIBOT"] == "recaptcha" then
html = templates.recaptcha:format(self.variables["ANTIBOT_RECAPTCHA_SITEKEY"], self.variables["ANTIBOT_URI"], self.variables["ANTIBOT_RECAPTCHA_SITEKEY"])
template_vars.recaptcha_sitekey = self.variables["ANTIBOT_RECAPTCHA_SITEKEY"]
end
-- hCaptcha case
if self.variables["USE_ANTIBOT"] == "hcaptcha" then
html = templates.hcaptcha:format(self.variables["ANTIBOT_URI"], self.variables["ANTIBOT_HCAPTCHA_SITEKEY"])
template_vars.hcaptcha_sitekey = self.variables["ANTIBOT_HCAPTCHA_SITEKEY"]
end
-- Send content
ngx.header["Content-Type"] = "text/html"
ngx.say(html)
-- Render content
template.render(self.variables["USE_ANTIBOT"] .. ".html", template_vars)
return true, "displayed challenge"
end

View File

@ -1,10 +1,11 @@
{% if USE_ANTIBOT == "yes" +%}
location /{{ ANTIBOT_URI }} {
root /usr/share/bunkerweb/core/antibot/files;
content_by_lua_block {
local antibot = require "antibot.antibot"
local logger = require "bunkerweb.logger"
antibot:new()
logger:new("ANTIBOT")
local cantibot = require "antibot.antibot"
local clogger = require "bunkerweb.logger"
local antibot = cantibot:new()
local logger = clogger:new("ANTIBOT")
local ok, err = antibot:content()
if not ok then
logger:log(ngx.ERR, "antibot:content() failed : " .. err)

View File

@ -6,26 +6,26 @@
<title>Bot Detection</title>
<link
rel="icon"
href="data:image/svg+xml, %%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%%3E%%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%%0Afill='%%23085577' stroke='none'%%3E%%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%%0A45 136 19z'/%%3E%%3C/g%%3E%%3C/svg%%3E"
href="data:image/svg+xml, %3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%3E%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%0Afill='%23085577' stroke='none'%3E%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%0A45 136 19z'/%3E%3C/g%3E%3C/svg%3E"
type="image/svg+xml"
/>
<style type="text/css">
body,
html {
width: 100%%;
height: 100%%;
width: 100%;
height: 100%;
background-color: #125678;
}
body {
color: #fff;
text-align: center;
padding: 0;
min-height: 100%%;
min-height: 100%;
display: table;
font-family: "Open Sans", Arial, sans-serif;
margin: 0;
-ms-text-size-adjust: 100%%;
-webkit-text-size-adjust: 100%%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
h1 {
display: flex;
@ -54,7 +54,7 @@
}
footer {
position: fixed;
width: 100%%;
width: 100%;
letter-spacing: 1px;
left: 0;
bottom: 0;
@ -141,7 +141,7 @@
position: absolute;
width: 7px;
height: 7px;
border-radius: 50%%;
border-radius: 50%;
background: #fff;
margin: -4px 0 0 -4px;
}
@ -202,10 +202,10 @@
left: 12px;
}
@keyframes lds-roller {
0%% {
0% {
transform: rotate(0deg);
}
100%% {
100% {
transform: rotate(360deg);
}
}
@ -220,13 +220,13 @@
JavaScript needs to be enabled in order to visit this website.
</p>
</noscript>
<form method="POST" action="%s" id="form">
<form method="POST" action="{{antibot_uri}}" id="form">
<input type="hidden" name="token" id="token" />
</form>
<div>
<div
class="h-captcha"
data-sitekey="%s"
data-sitekey="{{hcaptcha_sitekey}}"
data-callback="send_challenge"
></div>
<br />

View File

@ -4,24 +4,24 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Bot Detection</title>
<link rel="icon" href="data:image/svg+xml, %%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%%3E%%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%%0Afill='%%23085577' stroke='none'%%3E%%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%%0A45 136 19z'/%%3E%%3C/g%%3E%%3C/svg%%3E" type="image/svg+xml"/>
<link rel="icon" href="data:image/svg+xml, %3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%3E%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%0Afill='%23085577' stroke='none'%3E%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%0A45 136 19z'/%3E%3C/g%3E%3C/svg%3E" type="image/svg+xml"/>
<style type="text/css">
body,
html {
width: 100%%;
height: 100%%;
width: 100%;
height: 100%;
background-color: #125678;
}
body {
color: #fff;
text-align: center;
padding: 0;
min-height: 100%%;
min-height: 100%;
display: table;
font-family: "Open Sans", Arial, sans-serif;
margin: 0;
-ms-text-size-adjust: 100%%;
-webkit-text-size-adjust: 100%%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
h1 {
display: flex;
@ -49,7 +49,7 @@
}
footer {
position: fixed;
width: 100%%;
width: 100%;
letter-spacing: 1px;
left: 0;
bottom: 0;
@ -123,7 +123,7 @@
font-size: 16px;
}
}
.lds-roller{display: inline-block;position: relative;width: 80px;height: 80px}.lds-roller div{animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;transform-origin: 40px 40px}.lds-roller div:after{content: " ";display: block;position: absolute;width: 7px;height: 7px;border-radius: 50%%;background: #fff;margin: -4px 0 0 -4px}.lds-roller div:nth-child(1){animation-delay: -0.036s}.lds-roller div:nth-child(1):after{top: 63px;left: 63px}.lds-roller div:nth-child(2){animation-delay: -0.072s}.lds-roller div:nth-child(2):after{top: 68px;left: 56px}.lds-roller div:nth-child(3){animation-delay: -0.108s}.lds-roller div:nth-child(3):after{top: 71px;left: 48px}.lds-roller div:nth-child(4){animation-delay: -0.144s}.lds-roller div:nth-child(4):after{top: 72px;left: 40px}.lds-roller div:nth-child(5){animation-delay: -0.18s}.lds-roller div:nth-child(5):after{top: 71px;left: 32px}.lds-roller div:nth-child(6){animation-delay: -0.216s}.lds-roller div:nth-child(6):after{top: 68px;left: 24px}.lds-roller div:nth-child(7){animation-delay: -0.252s}.lds-roller div:nth-child(7):after{top: 63px;left: 17px}.lds-roller div:nth-child(8){animation-delay: -0.288s}.lds-roller div:nth-child(8):after{top: 56px;left: 12px}@keyframes lds-roller{0%%{transform: rotate(0deg)}100%%{transform: rotate(360deg)}}#showjs{display:none}#nojs{display:table-cell}
.lds-roller{display: inline-block;position: relative;width: 80px;height: 80px}.lds-roller div{animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;transform-origin: 40px 40px}.lds-roller div:after{content: " ";display: block;position: absolute;width: 7px;height: 7px;border-radius: 50%;background: #fff;margin: -4px 0 0 -4px}.lds-roller div:nth-child(1){animation-delay: -0.036s}.lds-roller div:nth-child(1):after{top: 63px;left: 63px}.lds-roller div:nth-child(2){animation-delay: -0.072s}.lds-roller div:nth-child(2):after{top: 68px;left: 56px}.lds-roller div:nth-child(3){animation-delay: -0.108s}.lds-roller div:nth-child(3):after{top: 71px;left: 48px}.lds-roller div:nth-child(4){animation-delay: -0.144s}.lds-roller div:nth-child(4):after{top: 72px;left: 40px}.lds-roller div:nth-child(5){animation-delay: -0.18s}.lds-roller div:nth-child(5):after{top: 71px;left: 32px}.lds-roller div:nth-child(6){animation-delay: -0.216s}.lds-roller div:nth-child(6):after{top: 68px;left: 24px}.lds-roller div:nth-child(7){animation-delay: -0.252s}.lds-roller div:nth-child(7):after{top: 63px;left: 17px}.lds-roller div:nth-child(8){animation-delay: -0.288s}.lds-roller div:nth-child(8):after{top: 56px;left: 12px}@keyframes lds-roller{0%{transform: rotate(0deg)}100%{transform: rotate(360deg)}}#showjs{display:none}#nojs{display:table-cell}
</style>
</head>
<body>
@ -136,7 +136,7 @@
<div class="lds-roller"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>
</p>
</div>
<form method="POST" action="%s" id="form">
<form method="POST" action="{{antibot_uri}}" id="form">
<input type="hidden" name="challenge" id="challenge">
</form>
<footer>
@ -233,7 +233,7 @@
var i, l = input.length * 32,
output = '';
for (i = 0; i < l; i += 8) {
output += String.fromCharCode((input[i >> 5] >>> (24 - i %% 32)) & 0xFF);
output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
}
return output;
}
@ -250,7 +250,7 @@
output[i] = 0;
}
for (i = 0; i < l; i += 8) {
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i %% 32);
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
}
return output;
}
@ -299,7 +299,7 @@
var W = [64];
var a, b, c, d, e, f, g, h;
var i, j, T1, T2;
m[l >> 5] |= 0x80 << (24 - (l %% 32));
m[l >> 5] |= 0x80 << (24 - (l % 32));
m[(((l + 64) >> 9) << 4) + 15] = l;
for (i = 0; i < m.length; i += 16) {
a = HASH[0];
@ -362,7 +362,7 @@
return hashBuffer;
}
(async () => {
const nonce = '%s';
const nonce = '{{random}}';
var i = 0;
while (true) {
var digestHex = await digestMessage(nonce + i.toString());

View File

@ -6,26 +6,26 @@
<title>Bot Detection</title>
<link
rel="icon"
href="data:image/svg+xml, %%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%%3E%%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%%0Afill='%%23085577' stroke='none'%%3E%%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%%0A45 136 19z'/%%3E%%3C/g%%3E%%3C/svg%%3E"
href="data:image/svg+xml, %3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%3E%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%0Afill='%23085577' stroke='none'%3E%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%0A45 136 19z'/%3E%3C/g%3E%3C/svg%3E"
type="image/svg+xml"
/>
<style type="text/css">
body,
html {
width: 100%%;
height: 100%%;
width: 100%;
height: 100%;
background-color: #125678;
}
body {
color: #fff;
text-align: center;
padding: 0;
min-height: 100%%;
min-height: 100%;
display: table;
font-family: "Open Sans", Arial, sans-serif;
margin: 0;
-ms-text-size-adjust: 100%%;
-webkit-text-size-adjust: 100%%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
h1 {
display: flex;
@ -53,7 +53,7 @@
}
footer {
position: fixed;
width: 100%%;
width: 100%;
letter-spacing: 1px;
left: 0;
bottom: 0;
@ -120,7 +120,7 @@
visibility: hidden;
}
</style>
<script src="https://www.google.com/recaptcha/api.js?render=%s"></script>
<script src="https://www.google.com/recaptcha/api.js?render={{recaptcha_sitekey}}"></script>
</head>
<body>
<div class="cover">
@ -138,7 +138,7 @@
<a href="https://policies.google.com/terms">Terms of Service</a> apply.
</p>
</div>
<form method="POST" action="%s" id="form">
<form method="POST" action="{{antibot_uri}}" id="form">
<input type="hidden" name="token" id="token" />
</form>
<footer>
@ -156,7 +156,7 @@
function check_robot() {
grecaptcha.ready(function () {
grecaptcha
.execute("%s", { action: "recaptcha" })
.execute("{{recaptcha_sitekey}}", { action: "recaptcha" })
.then(function (token) {
document.getElementById("token").value = token;
document.getElementById("form").submit();

View File

@ -6,26 +6,26 @@
<title>%s</title>
<link
rel="icon"
href="data:image/svg+xml, %%3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%%3E%%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%%0Afill='%%23085577' stroke='none'%%3E%%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%%0A45 136 19z'/%%3E%%3C/g%%3E%%3C/svg%%3E"
href="data:image/svg+xml, %3Csvg version='1.0' xmlns='http://www.w3.org/2000/svg' width='96.000000pt' height='96.000000pt' viewBox='0 0 96.000000 96.000000' preserveAspectRatio='xMidYMid meet'%3E%3Cg transform='translate(0.000000,96.000000) scale(0.100000,-0.100000)'%0Afill='%23085577' stroke='none'%3E%3Cpath d='M535 863 c-22 -2 -139 -17 -260 -34 -228 -31 -267 -43 -272 -85 -2%0A-10 23 -181 55 -379 l57 -360 400 0 400 0 20 40 c16 31 20 59 19 125 -1 100%0A-24 165 -73 199 -41 29 -46 57 -22 111 30 67 29 188 -3 256 -13 28 -37 60 -53%0A72 -55 39 -169 62 -268 55z m-15 -348 c30 -16 60 -61 60 -90 0 -10 -8 -33 -17%0A-52 -16 -34 -16 -41 0 -116 9 -44 15 -82 12 -85 -6 -7 -92 -21 -131 -21 l-31%0A-1 -6 85 c-4 75 -8 89 -31 112 -20 20 -26 36 -26 70 0 38 5 50 34 79 39 39 86%0A45 136 19z'/%3E%3C/g%3E%3C/svg%3E"
type="image/svg+xml"
/>
<style type="text/css">
body,
html {
width: 100%%;
height: 100%%;
width: 100%;
height: 100%;
background-color: #125678;
}
body {
color: #fff;
text-align: center;
padding: 0;
min-height: 100%%;
min-height: 100%;
display: table;
font-family: "Open Sans", Arial, sans-serif;
margin: 0;
-ms-text-size-adjust: 100%%;
-webkit-text-size-adjust: 100%%;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
h1 {
display: flex;
@ -63,7 +63,7 @@
}
footer {
position: fixed;
width: 100%%;
width: 100%;
letter-spacing: 1px;
left: 0;
bottom: 0;

View File

@ -31,12 +31,12 @@ function badbehavior:log()
return self:ret(true, "not increasing counter")
end
-- Check if we are already banned
local banned, err = datastore:get("bans_ip_" .. ngx.var.remote_addr)
local banned, err = self.datastore:get("bans_ip_" .. ngx.var.remote_addr)
if banned then
return self:ret(true, "already banned")
end
-- Call increase function later and with cosocket enabled
local ok, err = ngx.timer.at(0, badbehavior.increase, self.use_redis, ngx.var.remote_addr, tonumber(self.variables["BAD_BEHAVIOR_COUNT_TIME"]), tonumber(self.variables["BAD_BEHAVIOR_BAN_TIME"]), tonumber(self.variables["BAD_BEHAVIOR_THRESHOLD"]))
local ok, err = ngx.timer.at(0, badbehavior.increase, self, ngx.var.remote_addr)
if not ok then
return self:ret(false, "can't create increase timer : " .. err)
end
@ -47,23 +47,27 @@ function badbehavior:log_default()
return self:log()
end
function badbehavior.increase(premature, use_redis, ip, count_time, ban_time, threshold)
function badbehavior.increase(premature, obj, ip)
-- Our vars
local count_time = tonumber(obj.variables["BAD_BEHAVIOR_COUNT_TIME"])
local ban_time = tonumber(obj.variables["BAD_BEHAVIOR_BAN_TIME"])
local threshold = tonumber(obj.variables["BAD_BEHAVIOR_THRESHOLD"])
-- Declare counter
local counter = false
-- Redis case
if use_redis then
local redis_counter, err = badbehavior.redis_increase(ip, count_time, ban_time, threshold)
if obj.use_redis then
local redis_counter, err = obj:redis_increase(ip)
if not redis_counter then
badbehavior.logger:log(ngx.ERR, "(increase) redis_increase failed, falling back to local : " .. err)
obj.logger:log(ngx.ERR, "(increase) redis_increase failed, falling back to local : " .. err)
else
counter = redis_counter
end
end
-- Local case
if not counter then
local local_counter, err = datastore:get("plugin_badbehavior_count_" .. ip)
local local_counter, err = obj.datastore:get("plugin_badbehavior_count_" .. ip)
if not local_counter and err ~= "not found" then
badbehavior.logger:log(ngx.ERR, "(increase) can't get counts from the datastore : " .. err)
obj.logger:log(ngx.ERR, "(increase) can't get counts from the datastore : " .. err)
end
if local_counter == nil then
local_counter = 0
@ -71,28 +75,71 @@ function badbehavior.increase(premature, use_redis, ip, count_time, ban_time, th
counter = local_counter + 1
end
-- Call decrease later
local ok, err = ngx.timer.at(count_time, badbehavior.decrease, use_redis, ip)
local ok, err = ngx.timer.at(count_time, badbehavior.decrease, obj, ip)
if not ok then
badbehavior.logger:log(ngx.ERR, "(increase) can't create decrease timer : " .. err)
obj.logger:log(ngx.ERR, "(increase) can't create decrease timer : " .. err)
end
-- Store local counter
local ok, err = datastore:set("plugin_badbehavior_count_" .. ip, counter)
local ok, err = obj.datastore:set("plugin_badbehavior_count_" .. ip, counter)
if not ok then
badbehavior.logger:log(ngx.ERR, "(increase) can't save counts to the datastore : " .. err)
obj.logger:log(ngx.ERR, "(increase) can't save counts to the datastore : " .. err)
return
end
-- Store local ban
if counter > threshold then
local ok, err = datastore:set("bans_ip_" .. ip, "bad behavior", ban_time)
local ok, err = obj.datastore:set("bans_ip_" .. ip, "bad behavior", ban_time)
if not ok then
badbehavior.logger:log(ngx.ERR, "(increase) can't save ban to the datastore : " .. err)
obj.logger:log(ngx.ERR, "(increase) can't save ban to the datastore : " .. err)
return
end
badbehavior.logger:log(ngx.WARN, "IP " .. ip .. " is banned for " .. ban_time .. "s (" .. tostring(counter) .. "/" .. tostring(threshold) .. ")")
obj.logger:log(ngx.WARN, "IP " .. ip .. " is banned for " .. ban_time .. "s (" .. tostring(counter) .. "/" .. tostring(threshold) .. ")")
end
end
function badbehavior.redis_increase(ip, count_time, ban_time, threshold)
function badbehavior.decrease(premature, obj, ip)
-- Our vars
local count_time = tonumber(obj.variables["BAD_BEHAVIOR_COUNT_TIME"])
local ban_time = tonumber(obj.variables["BAD_BEHAVIOR_BAN_TIME"])
local threshold = tonumber(obj.variables["BAD_BEHAVIOR_THRESHOLD"])
-- Declare counter
local counter = false
-- Redis case
if obj.use_redis then
local redis_counter, err = obj:redis_decrease(ip)
if not redis_counter then
obj.logger:log(ngx.ERR, "(increase) redis_increase failed, falling back to local : " .. err)
else
counter = redis_counter
end
end
-- Local case
if not counter then
local local_counter, err = obj.datastore:get("plugin_badbehavior_count_" .. ip)
if not local_counter and err ~= "not found" then
obj.logger:log(ngx.ERR, "(increase) can't get counts from the datastore : " .. err)
end
if local_counter == nil or local_counter <= 1 then
counter = 0
else
counter = local_counter - 1
end
end
-- Store local counter
if counter <= 0 then
local ok, err = obj.datastore:delete("plugin_badbehavior_count_" .. ip)
else
local ok, err = obj.datastore:delete("plugin_badbehavior_count_" .. ip, counter)
if not ok then
obj.logger:log(ngx.ERR, "(increase) can't save counts to the datastore : " .. err)
return
end
end
end
function badbehavior:redis_increase(ip)
-- Our vars
local count_time = tonumber(self.variables["BAD_BEHAVIOR_COUNT_TIME"])
local ban_time = tonumber(self.variables["BAD_BEHAVIOR_BAN_TIME"])
-- Connect to server
local cstore, err = clusterstore:new()
if not cstore then
@ -137,7 +184,7 @@ function badbehavior.redis_increase(ip, count_time, ban_time, threshold)
return counter
end
function badbehavior.redis_decrease(ip)
function badbehavior:redis_decrease(ip)
-- Connect to server
local cstore, err = clusterstore:new()
if not cstore then
@ -160,12 +207,12 @@ function badbehavior.redis_decrease(ip)
if counter == 0 then
local ok, err = clusterstore:call("del", "bad_behavior_" .. ip)
if err then
clusterstore:close(redis_client)
clusterstore:close()
return false, err
end
end
-- End connection
clusterstore:close(redis_client)
clusterstore:close()
return counter
end

View File

@ -200,8 +200,8 @@ function blacklist:is_blacklisted_ip()
-- Check if rDNS is needed
local check_rdns = true
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if self.variables["BLACKLIST_RDNS_GLOBAL"] == "yes" then
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if is_global == nil then
return nil, err
end
@ -241,22 +241,25 @@ function blacklist:is_blacklisted_ip()
end
-- Check if ASN is in ignore list
local asn, err = utils.get_asn(ngx.var.remote_addr)
if not asn then
return nil, err
end
local ignore = false
for i, ignore_asn in ipairs(self.lists["IGNORE_ASN"]) do
if ignore_asn == tostring(asn) then
ignore = true
break
if is_global then
local asn, err = utils.get_asn(ngx.var.remote_addr)
if not asn then
self.logger:log(ngx.ERR, "7")
return nil, err
end
end
-- Check if ASN is in blacklist
if not ignore then
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
local ignore = false
for i, ignore_asn in ipairs(self.lists["IGNORE_ASN"]) do
if ignore_asn == tostring(asn) then
ignore = true
break
end
end
-- Check if ASN is in blacklist
if not ignore then
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
end
end
end
end

View File

@ -25,7 +25,7 @@ location = {{ page }} {
internal;
modsecurity off;
default_type 'text/html';
root /usr/share/bunkerweb/core/files;
root /usr/share/bunkerweb/core/errors/files;
content_by_lua_block {
local logger = require "bunkerweb.logger"
local cerrors = require "errors.errors"

View File

@ -166,8 +166,8 @@ function greylist:is_greylisted_ip()
-- Check if rDNS is needed
local check_rdns = true
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if self.variables["BLACKLIST_RDNS_GLOBAL"] == "yes" then
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if is_global == nil then
return nil, err
end
@ -192,9 +192,15 @@ function greylist:is_greylisted_ip()
end
-- Check if ASN is in greylist
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
if is_global then
local asn, err = utils.get_asn(ngx.var.remote_addr)
if not asn then
return nil, err
end
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
end
end
end

View File

@ -219,8 +219,8 @@ function whitelist:is_whitelisted_ip()
-- Check if rDNS is needed
local check_rdns = true
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if self.variables["WHITELIST_RDNS_GLOBAL"] == "yes" then
local is_global, err = utils.ip_is_global(ngx.var.remote_addr)
if is_global == nil then
return nil, err
end
@ -245,9 +245,15 @@ function whitelist:is_whitelisted_ip()
end
-- Check if ASN is in whitelist
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
if is_global then
local asn, err = utils.get_asn(ngx.var.remote_addr)
if not asn then
return nil, err
end
for i, bl_asn in ipairs(self.lists["ASN"]) do
if bl_asn == tostring(asn) then
return true, "ASN " .. bl_asn
end
end
end