mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
[#1460] Add "service" field in bans and reports
This commit is contained in:
parent
609dfc3cdc
commit
0d6fdbdd18
11 changed files with 56 additions and 26 deletions
|
|
@ -225,6 +225,7 @@ api.global.POST["^/ban$"] = function(self)
|
|||
ip = "",
|
||||
exp = 86400,
|
||||
reason = "manual",
|
||||
service = "unknown",
|
||||
}
|
||||
ban.ip = ip["ip"]
|
||||
if ip["exp"] then
|
||||
|
|
@ -233,10 +234,14 @@ api.global.POST["^/ban$"] = function(self)
|
|||
if ip["reason"] then
|
||||
ban.reason = ip["reason"]
|
||||
end
|
||||
if ip["service"] then
|
||||
ban.service = ip["service"]
|
||||
end
|
||||
datastore:set(
|
||||
"bans_ip_" .. ban["ip"],
|
||||
encode({
|
||||
reason = ban["reason"],
|
||||
service = ban["service"],
|
||||
date = os.time(),
|
||||
}),
|
||||
ban["exp"]
|
||||
|
|
@ -267,12 +272,15 @@ api.global.GET["^/bans$"] = function(self)
|
|||
local ban_data
|
||||
ok, ban_data = pcall(decode, result)
|
||||
if not ok then
|
||||
ban_data = { reason = result, date = -1 }
|
||||
ban_data = { reason = result, service = "unknown", date = -1 }
|
||||
end
|
||||
table.insert(
|
||||
data,
|
||||
{ ip = k:sub(9, #k), reason = ban_data["reason"], date = ban_data["date"], exp = math.floor(ttl) }
|
||||
)
|
||||
table.insert(data, {
|
||||
ip = k:sub(9, #k),
|
||||
reason = ban_data["reason"],
|
||||
service = ban_data["service"],
|
||||
date = ban_data["date"],
|
||||
exp = math.floor(ttl),
|
||||
})
|
||||
end
|
||||
end
|
||||
return self:response(HTTP_OK, "success", data)
|
||||
|
|
|
|||
|
|
@ -714,10 +714,11 @@ utils.is_banned = function(ip)
|
|||
return false, "not banned"
|
||||
end
|
||||
|
||||
utils.add_ban = function(ip, reason, ttl)
|
||||
utils.add_ban = function(ip, reason, ttl, service)
|
||||
-- Set on local datastore
|
||||
local ban_data = encode({
|
||||
reason = reason,
|
||||
service = service or "unknown",
|
||||
date = os.time(),
|
||||
})
|
||||
local ok, err = datastore:set("bans_ip_" .. ip, ban_data, ttl)
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ class CLI(ApiCaller):
|
|||
def ban(self, ip: str, exp: float, reason: str) -> Tuple[bool, str]:
|
||||
if self.__redis:
|
||||
try:
|
||||
ok = self.__redis.set(f"bans_ip_{ip}", dumps({"reason": reason, "date": time()}))
|
||||
ok = self.__redis.set(f"bans_ip_{ip}", dumps({"reason": reason, "date": time(), "service": "bwcli"}))
|
||||
if not ok:
|
||||
self.__logger.error(f"Failed to ban {ip} in redis")
|
||||
self.__redis.expire(f"bans_ip_{ip}", int(exp))
|
||||
|
|
@ -260,7 +260,12 @@ class CLI(ApiCaller):
|
|||
banned_date = f"the {datetime.fromtimestamp(ban['date']).strftime('%Y-%m-%d at %H:%M:%S %Z')} "
|
||||
if ban["exp"] != -1:
|
||||
remaining = f"for {format_remaining_time(ban['exp'])} remaining"
|
||||
cli_str += f"- {ban['ip']} ; banned {banned_date}{remaining} with reason \"{ban.get('reason', 'no reason given')}\"\n"
|
||||
cli_str += f"- {ban['ip']} ; banned {banned_date}{remaining} with reason \"{ban.get('reason', 'no reason given')}\""
|
||||
|
||||
if ban.get("service", "unknown") != "unknown":
|
||||
cli_str += f" by {ban['service'] if ban['service'] != '_' else 'default server'}"
|
||||
|
||||
cli_str += "\n"
|
||||
cli_str += "\n"
|
||||
|
||||
return True, cli_str
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ function badbehavior:log()
|
|||
tonumber(self.variables["BAD_BEHAVIOR_COUNT_TIME"]),
|
||||
tonumber(self.variables["BAD_BEHAVIOR_BAN_TIME"]),
|
||||
tonumber(self.variables["BAD_BEHAVIOR_THRESHOLD"]),
|
||||
self.use_redis
|
||||
self.use_redis,
|
||||
self.ctx.bw.server_name
|
||||
)
|
||||
if not ok then
|
||||
return self:ret(false, "can't create increase timer : " .. err)
|
||||
|
|
@ -62,7 +63,7 @@ function badbehavior:log_stream()
|
|||
end
|
||||
|
||||
-- luacheck: ignore 212
|
||||
function badbehavior.increase(premature, ip, count_time, ban_time, threshold, use_redis)
|
||||
function badbehavior.increase(premature, ip, count_time, ban_time, threshold, use_redis, server_name)
|
||||
-- Instantiate objects
|
||||
local logger = require "bunkerweb.logger":new("badbehavior")
|
||||
local datastore = require "bunkerweb.datastore":new()
|
||||
|
|
@ -102,7 +103,7 @@ 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)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ function metrics:log(bypass_checks)
|
|||
status = ngx.status,
|
||||
user_agent = self.ctx.bw.http_user_agent or "",
|
||||
reason = reason,
|
||||
server_name = self.ctx.bw.server_name,
|
||||
data = data,
|
||||
}
|
||||
-- Get current requests
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ class Instance:
|
|||
return f"Instance {self.hostname} has been restarted."
|
||||
return f"Can't restart instance {self.hostname}"
|
||||
|
||||
def ban(self, ip: str, exp: float, reason: str) -> str:
|
||||
def ban(self, ip: str, exp: float, reason: str, service: str) -> str:
|
||||
try:
|
||||
result = self.apiCaller.send_to_apis("POST", "/ban", data={"ip": ip, "exp": exp, "reason": reason})[0]
|
||||
result = self.apiCaller.send_to_apis("POST", "/ban", data={"ip": ip, "exp": exp, "reason": reason, "service": service})[0]
|
||||
except BaseException as e:
|
||||
return f"Can't ban {ip} on instance {self.hostname}: {e}"
|
||||
|
||||
|
|
@ -193,8 +193,10 @@ class InstancesUtils:
|
|||
instance.name for instance in instances or self.get_instances() if instance.status == "down" or instance.reload().startswith("Can't reload")
|
||||
] or "Successfully reloaded instances"
|
||||
|
||||
def ban(self, ip: str, exp: float, reason: str, *, instances: Optional[List[Instance]] = None) -> Union[list[str], str]:
|
||||
return [instance.name for instance in instances or self.get_instances(status="up") if instance.ban(ip, exp, reason).startswith("Can't ban")] or ""
|
||||
def ban(self, ip: str, exp: float, reason: str, service: str, *, instances: Optional[List[Instance]] = None) -> Union[list[str], str]:
|
||||
return [
|
||||
instance.name for instance in instances or self.get_instances(status="up") if instance.ban(ip, exp, reason, service).startswith("Can't ban")
|
||||
] or ""
|
||||
|
||||
def unban(self, ip: str, *, instances: Optional[List[Instance]] = None) -> Union[list[str], str]:
|
||||
return [instance.name for instance in instances or self.get_instances(status="up") if instance.unban(ip).startswith("Can't unban")] or ""
|
||||
|
|
|
|||
|
|
@ -85,12 +85,12 @@ def bans_ban():
|
|||
ban_end = (ban_end - current_time).total_seconds()
|
||||
|
||||
if redis_client:
|
||||
ok = redis_client.set(f"bans_ip_{ban['ip']}", dumps({"reason": reason, "date": time()}))
|
||||
ok = redis_client.set(f"bans_ip_{ban['ip']}", dumps({"reason": reason, "date": time(), "service": "web UI"}))
|
||||
if not ok:
|
||||
flash(f"Couldn't ban {ban['ip']} on redis", "error")
|
||||
redis_client.expire(f"bans_ip_{ban['ip']}", int(ban_end))
|
||||
|
||||
resp = BW_INSTANCES_UTILS.ban(ban["ip"], ban_end, reason)
|
||||
resp = BW_INSTANCES_UTILS.ban(ban["ip"], ban_end, reason, "web UI")
|
||||
if resp:
|
||||
flash(f"Couldn't ban {ban['ip']} on the following instances: {', '.join(resp)}", "error")
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ $(document).ready(function () {
|
|||
viewTotal: true,
|
||||
cascadePanes: true,
|
||||
collapse: false,
|
||||
columns: [1, 4],
|
||||
columns: [1, 4, 5],
|
||||
},
|
||||
},
|
||||
topStart: {},
|
||||
|
|
@ -336,7 +336,7 @@ $(document).ready(function () {
|
|||
targets: -1,
|
||||
},
|
||||
{
|
||||
targets: [1, 4],
|
||||
targets: [1, 5],
|
||||
render: function (data, type, row) {
|
||||
if (type === "display" || type === "filter") {
|
||||
const date = new Date(data);
|
||||
|
|
@ -396,7 +396,7 @@ $(document).ready(function () {
|
|||
{
|
||||
label: "Next 24 hours",
|
||||
value: function (rowData, rowIdx) {
|
||||
const date = new Date(rowData[4]);
|
||||
const date = new Date(rowData[5]);
|
||||
const now = new Date();
|
||||
return date - now < 24 * 60 * 60 * 1000;
|
||||
},
|
||||
|
|
@ -404,7 +404,7 @@ $(document).ready(function () {
|
|||
{
|
||||
label: "Next 7 days",
|
||||
value: function (rowData, rowIdx) {
|
||||
const date = new Date(rowData[4]);
|
||||
const date = new Date(rowData[5]);
|
||||
const now = new Date();
|
||||
return date - now < 7 * 24 * 60 * 60 * 1000;
|
||||
},
|
||||
|
|
@ -412,7 +412,7 @@ $(document).ready(function () {
|
|||
{
|
||||
label: "Next 30 days",
|
||||
value: function (rowData, rowIdx) {
|
||||
const date = new Date(rowData[4]);
|
||||
const date = new Date(rowData[5]);
|
||||
const now = new Date();
|
||||
return date - now < 30 * 24 * 60 * 60 * 1000;
|
||||
},
|
||||
|
|
@ -420,7 +420,7 @@ $(document).ready(function () {
|
|||
{
|
||||
label: "More than 30 days",
|
||||
value: function (rowData, rowIdx) {
|
||||
const date = new Date(rowData[4]);
|
||||
const date = new Date(rowData[5]);
|
||||
const now = new Date();
|
||||
return date - now >= 30 * 24 * 60 * 60 * 1000;
|
||||
},
|
||||
|
|
@ -429,10 +429,14 @@ $(document).ready(function () {
|
|||
combiner: "or",
|
||||
orderable: false,
|
||||
},
|
||||
targets: 5,
|
||||
},
|
||||
{
|
||||
searchPanes: { show: true },
|
||||
targets: 4,
|
||||
},
|
||||
],
|
||||
order: [[4, "asc"]],
|
||||
order: [[5, "asc"]],
|
||||
autoFill: false,
|
||||
responsive: true,
|
||||
select: {
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ $(function () {
|
|||
viewTotal: true,
|
||||
cascadePanes: true,
|
||||
collapse: false,
|
||||
columns: [1, 2, 3, 4, 5, 7],
|
||||
columns: [1, 2, 3, 4, 5, 7, 8],
|
||||
},
|
||||
},
|
||||
topStart: {},
|
||||
|
|
@ -460,7 +460,7 @@ $(function () {
|
|||
},
|
||||
{
|
||||
searchPanes: { show: true },
|
||||
targets: [1, 2, 3, 4, 5, 7],
|
||||
targets: [1, 2, 3, 4, 5, 7, 8],
|
||||
},
|
||||
],
|
||||
order: [[0, "desc"]],
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The reason why the Report was created">Reason</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The service that created the ban">Service</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The end date of the Ban">End date</th>
|
||||
|
|
@ -46,6 +49,7 @@
|
|||
<td class="ban-start-date">{{ ban["start_date"] }}</td>
|
||||
<td>{{ ban["ip"] }}</td>
|
||||
<td>{{ ban["reason"] }}</td>
|
||||
<td>{{ ban["service"] if ban["service"] != "_" else "default server" }}</td>
|
||||
<td class="ban-end-date">{{ ban["end_date"] }}</td>
|
||||
<td>{{ ban["remain"] }}</td>
|
||||
<td>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@
|
|||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The reason why the Report was created">Reason</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="The Server name that created the report">Server name</th>
|
||||
<th data-bs-toggle="tooltip"
|
||||
data-bs-placement="bottom"
|
||||
data-bs-original-title="Additional data about the Report">Data</th>
|
||||
|
|
@ -69,6 +72,7 @@
|
|||
<td>{{ report["status"] }}</td>
|
||||
<td>{{ report["user_agent"] }}</td>
|
||||
<td>{{ report["reason"] }}</td>
|
||||
<td>{{ report["server_name"] }}</td>
|
||||
<td>{{ report["data"] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue