Mercurial > prosody-modules
comparison mod_audit_auth/mod_audit_auth.lua @ 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 | f199bff16f1f |
| children |
comparison
equal
deleted
inserted
replaced
| 5905:02657e8693bc | 5906:cc30c4b5f006 |
|---|---|
| 1 local jid = require"util.jid"; | 1 local cache = require "util.cache"; |
| 2 local jid = require "util.jid"; | |
| 2 local st = require "util.stanza"; | 3 local st = require "util.stanza"; |
| 3 | 4 |
| 4 module:depends("audit"); | 5 module:depends("audit"); |
| 5 -- luacheck: read globals module.audit | 6 -- luacheck: read globals module.audit |
| 6 | 7 |
| 7 local only_passwords = module:get_option_boolean("audit_auth_passwords_only", true); | 8 local only_passwords = module:get_option_boolean("audit_auth_passwords_only", true); |
| 9 local cache_size = module:get_option_number("audit_auth_cache_size", 128); | |
| 10 local repeat_failure_timeout = module:get_option_number("audit_auth_repeat_failure_timeout"); | |
| 11 local repeat_success_timeout = module:get_option_number("audit_auth_repeat_success_timeout"); | |
| 8 | 12 |
| 13 local failure_cache = cache.new(cache_size); | |
| 9 module:hook("authentication-failure", function(event) | 14 module:hook("authentication-failure", function(event) |
| 10 local session = event.session; | 15 local session = event.session; |
| 11 module:audit(jid.join(session.sasl_handler.username, module.host), "authentication-failure", { | 16 |
| 12 session = session, | 17 local username = session.sasl_handler.username; |
| 18 if repeat_failure_timeout then | |
| 19 local cache_key = ("%s\0%s"):format(username, session.ip); | |
| 20 local last_failure = failure_cache:get(cache_key); | |
| 21 local now = os.time(); | |
| 22 if last_failure and (now - last_failure) > repeat_failure_timeout then | |
| 23 return; | |
| 24 end | |
| 25 failure_cache:set(cache_key, now); | |
| 26 end | |
| 27 | |
| 28 module:audit(jid.join(username, module.host), "authentication-failure", { | |
| 29 session = session; | |
| 13 }); | 30 }); |
| 14 end) | 31 end) |
| 15 | 32 |
| 33 local success_cache = cache.new(cache_size); | |
| 16 module:hook("authentication-success", function(event) | 34 module:hook("authentication-success", function(event) |
| 17 local session = event.session; | 35 local session = event.session; |
| 18 if only_passwords and session.sasl_handler.fast then | 36 if only_passwords and session.sasl_handler.fast then |
| 19 return; | 37 return; |
| 20 end | 38 end |
| 21 module:audit(jid.join(session.sasl_handler.username, module.host), "authentication-success", { | 39 |
| 22 session = session, | 40 local username = session.sasl_handler.username; |
| 41 if repeat_success_timeout then | |
| 42 local cache_key = ("%s\0%s"):format(username, session.ip); | |
| 43 local last_success = success_cache:get(cache_key); | |
| 44 local now = os.time(); | |
| 45 if last_success and (now - last_success) > repeat_success_timeout then | |
| 46 return; | |
| 47 end | |
| 48 success_cache:set(cache_key, now); | |
| 49 end | |
| 50 | |
| 51 module:audit(jid.join(username, module.host), "authentication-success", { | |
| 52 session = session; | |
| 23 }); | 53 }); |
| 24 end) | 54 end) |
| 25 | 55 |
| 26 module:hook("client_management/new-client", function (event) | 56 module:hook("client_management/new-client", function (event) |
| 27 local session, client = event.session, event.client; | 57 local session, client = event.session, event.client; |
