Mercurial > prosody-modules
changeset 5906:cc30c4b5f006
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.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Mon, 13 May 2024 18:30:18 +0100 |
parents | 02657e8693bc |
children | d194d1012fd3 |
files | mod_audit_auth/mod_audit_auth.lua |
diffstat | 1 files changed, 35 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- 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)