135 lines
3.3 KiB
HTML
135 lines
3.3 KiB
HTML
{% extends "base.html" %} {% block title %}Blocklist — Intrusion Detection{%
|
|
endblock %} {% block content %}
|
|
<h1>Blocklist</h1>
|
|
<p class="muted">
|
|
Current consolidated blocklist (from the latest scan). Adding/removing touches
|
|
the MikroTik router.
|
|
</p>
|
|
|
|
<div class="panel">
|
|
<div class="panel-head"><h2>Add / remove entry</h2></div>
|
|
<div class="panel-actions" style="margin-top: 0">
|
|
<input
|
|
id="ip"
|
|
placeholder="IP or CIDR, e.g. 1.2.3.4 or 1.2.0.0/16"
|
|
style="min-width: 260px"
|
|
/>
|
|
<button class="btn primary" id="add-btn">Add to Blocked</button>
|
|
<button class="btn danger" id="remove-btn">Remove from Blocked</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<div class="panel-head">
|
|
<h2>IPv4 <span id="v4-count"></span></h2>
|
|
</div>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Address</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="v4"></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<div class="panel-head">
|
|
<h2>IPv6 <span id="v6-count"></span></h2>
|
|
</div>
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Address</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="v6"></tbody>
|
|
</table>
|
|
</div>
|
|
{% endblock %} {% block scripts %}
|
|
<script>
|
|
async function loadBlocklist() {
|
|
try {
|
|
const data = await api("/api/blocklist");
|
|
render("v4", data.ipv4 || [], "v4-count");
|
|
render("v6", data.ipv6 || [], "v6-count");
|
|
} catch (e) {
|
|
toast(e.message, "error");
|
|
}
|
|
}
|
|
|
|
function render(tbodyId, entries, countId) {
|
|
const body = document.getElementById(tbodyId);
|
|
body.innerHTML = "";
|
|
document.getElementById(countId).textContent = `(${entries.length})`;
|
|
if (!entries.length) {
|
|
body.innerHTML =
|
|
'<tr><td colspan="2" class="muted">No entries.</td></tr>';
|
|
return;
|
|
}
|
|
for (const ip of entries) {
|
|
body.append(
|
|
el(
|
|
"tr",
|
|
el("td", { class: "mono", text: ip }),
|
|
el(
|
|
"td",
|
|
{ style: "text-align:right" },
|
|
el("button", {
|
|
class: "btn danger",
|
|
text: "Remove",
|
|
onclick: () => remove(ip),
|
|
}),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
async function act(action) {
|
|
const ip = document.getElementById("ip").value.trim();
|
|
if (!ip) {
|
|
toast("Enter an IP or CIDR", "warn");
|
|
return;
|
|
}
|
|
try {
|
|
const data = await api(`/api/blocklist/${action}`, {
|
|
method: "POST",
|
|
body: { ip },
|
|
});
|
|
toast(
|
|
`Removed ${ip}`.replace(
|
|
"Removed",
|
|
action === "add" ? "Added" : "Removed",
|
|
),
|
|
"ok",
|
|
);
|
|
document.getElementById("ip").value = "";
|
|
loadBlocklist();
|
|
} catch (e) {
|
|
toast(e.message, "error");
|
|
}
|
|
}
|
|
|
|
async function remove(ip) {
|
|
try {
|
|
await api("/api/blocklist/remove", { method: "POST", body: { ip } });
|
|
toast(`Removed ${ip}`, "ok");
|
|
loadBlocklist();
|
|
} catch (e) {
|
|
toast(e.message, "error");
|
|
}
|
|
}
|
|
|
|
document
|
|
.getElementById("add-btn")
|
|
.addEventListener("click", () => act("add"));
|
|
document
|
|
.getElementById("remove-btn")
|
|
.addEventListener("click", () => act("remove"));
|
|
loadBlocklist();
|
|
</script>
|
|
{% endblock %}
|