plugin/antibrute: exclude

Massimo Melina committed Feb 16, 2026 at 12:11 UTC 86ac04265f8d46f25af9ffdfc9f4262a8c475506
1 file changed +14 -3
plugins/antibrute/plugin.js
+14 -3
@@ -1,4 +1,4 @@
1 -exports.version = 3
1 +exports.version = 3.1
2 exports.description = "Introduce increasing delays between login attempts."
3 exports.apiRequired = 9.6 // addBlock
4
@@ -7,6 +7,7 @@ exports.config = {
7 max: { type: 'number', min: 1, defaultValue: 60, label: "Max delay", unit: "seconds", helperText: "Max seconds to delay before next login is allowed" },
8 blockAfter: { type: 'number', xs: 6, min: 1, max: 9999, defaultValue: 100, label: "Block IP after", unit: "attempts", helperText: "localhost excluded" },
9 blockForHours: { type: 'number', xs: 6, min: 0, defaultValue: 24, label: "Block for", unit: "hours" },
10 + exclude: { type: 'string', defaultValue: '', label: "Exclude IPs", helperText: "Net mask syntax" },
11 }
12 exports.configDialog = {
13 maxWidth: 'xs',
@@ -15,7 +16,7 @@ exports.configDialog = {
16 const byIp = {}
17
18 exports.init = api => {
18 - const { isLocalHost, HOUR } = api.misc
19 + const { isLocalHost, HOUR, netMatches } = api.misc
20 api.events.multi({
21 async attemptingLogin({ ctx }) {
22 const { ip } = ctx
@@ -25,7 +26,7 @@ exports.init = api => {
26 const delay = Math.min(max, 1000 * api.getConfig('increment') * ++rec.attempts)
27 const wait = rec.next - now
28 rec.next = new Date(+rec.next + delay)
28 - if (rec.attempts > api.getConfig('blockAfter') && !isLocalHost(ctx)) {
29 + if (rec.attempts > api.getConfig('blockAfter') && !isLocalHost(ctx) && !isExcluded(ip)) {
30 const hours = api.getConfig('blockForHours')
31 api.addBlock({ ip, comment: "From antibrute plugin", expire: hours ? new Date(now.getTime() + hours * HOUR) : undefined })
32 }
@@ -42,4 +43,14 @@ exports.init = api => {
43 delete byIp[ctx.ip] // reset if login was successful
44 }
45 })
46 +
47 + function isExcluded(ip) {
48 + const mask = api.getConfig('exclude')
49 + if (!mask) return false
50 + try { return netMatches(ip, mask) }
51 + catch (e) {
52 + api.log("bad exclude mask:", String(e))
53 + return false
54 + }
55 + }
56 }