# HG changeset patch # User Matthew Wild # Date 1715621418 -3600 # Node ID cc30c4b5f006d5b781fe575518878373c1bd2f28 # Parent 02657e8693bc24651a977c3636378ae1b8aa6eb9 mod_audit_auth: Allow suppressing repeated failure/success log entries from the same IP for a time This can be triggered by e.g. a distributed brute force attack, or from Monal. diff -r 02657e8693bc -r cc30c4b5f006 mod_audit_auth/mod_audit_auth.lua --- a/mod_audit_auth/mod_audit_auth.lua Sun May 12 17:01:20 2024 +0200 +++ b/mod_audit_auth/mod_audit_auth.lua Mon May 13 18:30:18 2024 +0100 @@ -1,25 +1,55 @@ -local jid = require"util.jid"; +local cache = require "util.cache"; +local jid = require "util.jid"; local st = require "util.stanza"; module:depends("audit"); -- luacheck: read globals module.audit local only_passwords = module:get_option_boolean("audit_auth_passwords_only", true); +local cache_size = module:get_option_number("audit_auth_cache_size", 128); +local repeat_failure_timeout = module:get_option_number("audit_auth_repeat_failure_timeout"); +local repeat_success_timeout = module:get_option_number("audit_auth_repeat_success_timeout"); +local failure_cache = cache.new(cache_size); module:hook("authentication-failure", function(event) local session = event.session; - module:audit(jid.join(session.sasl_handler.username, module.host), "authentication-failure", { - session = session, + + local username = session.sasl_handler.username; + if repeat_failure_timeout then + local cache_key = ("%s\0%s"):format(username, session.ip); + local last_failure = failure_cache:get(cache_key); + local now = os.time(); + if last_failure and (now - last_failure) > repeat_failure_timeout then + return; + end + failure_cache:set(cache_key, now); + end + + module:audit(jid.join(username, module.host), "authentication-failure", { + session = session; }); end) +local success_cache = cache.new(cache_size); module:hook("authentication-success", function(event) local session = event.session; if only_passwords and session.sasl_handler.fast then return; end - module:audit(jid.join(session.sasl_handler.username, module.host), "authentication-success", { - session = session, + + local username = session.sasl_handler.username; + if repeat_success_timeout then + local cache_key = ("%s\0%s"):format(username, session.ip); + local last_success = success_cache:get(cache_key); + local now = os.time(); + if last_success and (now - last_success) > repeat_success_timeout then + return; + end + success_cache:set(cache_key, now); + end + + module:audit(jid.join(username, module.host), "authentication-success", { + session = session; }); end)