Software /
code /
prosody-modules
Changeset
6134:00b55c7ef393
Backed out changeset ffec70ddbffc
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sat, 04 Jan 2025 22:48:54 +0000 |
parents | 6133:a0429c322454 |
children | 6135:c42419d73737 |
files | mod_anti_spam/mod_anti_spam.lua mod_flags/mod_flags.lua |
diffstat | 2 files changed, 6 insertions(+), 291 deletions(-) [+] |
line wrap: on
line diff
--- a/mod_anti_spam/mod_anti_spam.lua Sat Jan 04 19:04:26 2025 +0100 +++ b/mod_anti_spam/mod_anti_spam.lua Sat Jan 04 22:48:54 2025 +0000 @@ -1,7 +1,5 @@ -local cache = require "util.cache"; local ip = require "util.ip"; local jid_bare = require "util.jid".bare; -local jid_host = require "util.jid".host; local jid_split = require "util.jid".split; local set = require "util.set"; local sha256 = require "util.hashes".sha256; @@ -13,26 +11,10 @@ local new_rtbl_subscription = module:require("rtbl").new_rtbl_subscription; local trie = module:require("trie"); -local pset = module:require("pset"); --- { [service_jid] = set, ... } -local spam_source_domains_by_service = {}; -local spam_source_ips_by_service = {}; -local spam_source_jids_by_service = {}; - -local service_probabilities = { - -- if_present = probability the address is a spammer if they are on the list - -- if_absent (optional): probability the address is a spammer if they are not on the list - -- [service_jid] = { if_present = 0.9, if_absent = 0.5 }; -}; - - --- These "probabilistic sets" combine the multiple lists according to their weights -local p_spam_source_domains = pset.new(spam_source_domains_by_service, service_probabilities); -local p_spam_source_ips = pset.new(spam_source_ips_by_service, service_probabilities); -local p_spam_source_jids = pset.new(spam_source_jids_by_service, service_probabilities); - -local domain_local_report_threshold = module:get_option_number("anti_spam_local_report_threshold", 2); +local spam_source_domains = set.new(); +local spam_source_ips = trie.new(); +local spam_source_jids = set.new(); local count_spam_blocked = module:metric("counter", "anti_spam_blocked", "stanzas", "Stanzas blocked as spam", {"reason"}); @@ -85,20 +67,20 @@ end function is_spammy_server(session) - if p_spam_source_domains:contains(session.from_host) then + if spam_source_domains:contains(session.from_host) then return true; end local raw_ip = session.ip; local parsed_ip = raw_ip and ip.new_ip(session.ip); -- Not every session has an ip - for example, stanzas sent from a -- local host session - if parsed_ip and p_spam_source_ips:contains_ip(parsed_ip) then + if parsed_ip and spam_source_ips:contains_ip(parsed_ip) then return true; end end function is_spammy_sender(sender_jid) - return p_spam_source_jids:contains(sha256(sender_jid, true)); + return spam_source_jids:contains(sha256(sender_jid, true)); end local spammy_strings = module:get_option_array("anti_spam_block_strings"); @@ -133,16 +115,6 @@ local anti_spam_services = module:get_option_array("anti_spam_services", {}); for _, rtbl_service_jid in ipairs(anti_spam_services) do - service_probabilities[rtbl_service_jid] = { if_present = 0.95 }; - - local spam_source_domains = set.new(); - local spam_source_ips = trie.new(); - local spam_source_jids = set.new(); - - spam_source_domains_by_service[rtbl_service_jid] = spam_source_domains; - spam_source_ips_by_service[rtbl_service_jid] = spam_source_ips; - spam_source_jids_by_service[rtbl_service_jid] = spam_source_jids; - new_rtbl_subscription(rtbl_service_jid, "spam_source_domains", { added = function (item) spam_source_domains:add(item); @@ -177,68 +149,6 @@ }); end --- And local reports... - -do - local spam_source_domains = set.new(); - local spam_source_ips = set.new(); - - local domain_counts = cache.new(100); - - service_probabilities[module.host] = { if_present = 0.6, if_absent = 0.4 }; - - module:hook("mod_spam_reporting/spam-report", function (event) - -- TODO: check for >= prosody:member - local reported_jid = event.jid; - local reported_domain = jid_host(reported_jid); - local report_count = (domain_counts:get(reported_domain) or 0) + 1; - domain_counts:set(reported_domain, report_count); - - if report_count >= domain_local_report_threshold then - spam_source_domains:add(reported_domain); - end - end); - - module:add_item("shell-command", { - section = "antispam"; - section_desc = "Anti-spam management commands"; - name = "filter_domain"; - desc = "Restrict interactions from a remote domain to a virtual host"; - args = { - { name = "host", type = "string" }; - { name = "remote_domain", type = "string" }; - }; - host_selector = "host"; - handler = function(self, host, remote_domain) --luacheck: ignore 212/self 212/host - spam_source_domains:add(remote_domain); - return true, "Remote domain now restricted: "..remote_domain; - end; - }); - - module:add_item("shell-command", { - section = "antispam"; - section_desc = "Anti-spam management commands"; - name = "filter_ip"; - desc = "Restrict interactions from a remote IP/CIDR to a virtual host"; - args = { - { name = "host", type = "string" }; - { name = "remote_ip", type = "string" }; - }; - host_selector = "host"; - handler = function(self, host, remote_ip) --luacheck: ignore 212/self 212/host - local subnet_ip, subnet_bits = ip.parse_cidr(remote_ip); - if not subnet_ip then - return false, subnet_bits; -- false, err - end - - spam_source_ips:add_subnet(subnet_ip, subnet_bits); - - return true, "Remote IP now restricted: "..remote_ip; - end; - }); - -end - module:hook("message/bare", function (event) local to_user, to_host = jid_split(event.stanza.attr.to); @@ -290,4 +200,3 @@ module:log("debug", "Allowing subscription request through"); end, 500); -
--- a/mod_flags/mod_flags.lua Sat Jan 04 19:04:26 2025 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ --- This module is only for 0.12, later versions have mod_flags bundled ---% conflicts: mod_flags - -local flags_map; -if prosody.process_type ~= "prosodyctl" then - flags_map = module:open_store("account_flags", "map"); -end - --- API - -function add_flag(username, flag, comment) -- luacheck: ignore 131/add_flag - local flag_data = { - when = os.time(); - comment = comment; - }; - - local ok, err = flags_map:set(username, flag, flag_data); - if not ok then - return nil, err; - end - - module:fire_event("user-flag-added/"..flag, { - user = username; - flag = flag; - data = flag_data; - }); - - return true; -end - -function remove_flag(username, flag) -- luacheck: ignore 131/remove_flag - local ok, err = flags_map:set(username, flag, nil); - if not ok then - return nil, err; - end - - module:fire_event("user-flag-removed/"..flag, { - user = username; - flag = flag; - }); - - return true; -end - -function has_flag(username, flag) -- luacheck: ignore 131/has_flag - local ok, err = flags_map:get(username, flag); - if not ok and err then - error("Failed to check flags for user: "..err); - end - return not not ok; -end - -function get_flag_info(username, flag) -- luacheck: ignore 131/get_flag_info - return flags_map:get(username, flag); -end - - --- Migration from mod_firewall marks - -local function migrate_marks(host) - local usermanager = require "core.usermanager"; - - local flag_storage = module:open_store("account_flags"); - local mark_storage = module:open_store("firewall_marks"); - - local migration_comment = "Migrated from mod_firewall marks at "..os.date("%Y-%m-%d %R"); - - local migrated, empty, errors = 0, 0, 0; - for username in usermanager.users(host) do - local marks, err = mark_storage:get(username); - if marks then - local flags = {}; - for mark_name, mark_timestamp in pairs(marks) do - flags[mark_name] = { - when = mark_timestamp; - comment = migration_comment; - }; - end - local saved_ok, saved_err = flag_storage:set(username, flags); - if saved_ok then - prosody.log("error", "Failed to save flags for %s: %s", username, saved_err); - migrated = migrated + 1; - else - errors = errors + 1; - end - elseif err then - prosody.log("error", "Failed to load marks for %s: %s", username, err); - errors = errors + 1; - else - empty = empty + 1; - end - end - - print(("Finished - %d migrated, %d users with no marks, %d errors"):format(migrated, empty, errors)); -end - -function module.command(arg) - local storagemanager = require "core.storagemanager"; - local usermanager = require "core.usermanager"; - local jid = require "util.jid"; - local warn = require"util.prosodyctl".show_warning; - - local command = arg[1]; - if not command then - warn("Valid subcommands: migrate_marks"); - return 0; - end - table.remove(arg, 1); - - local node, host = jid.prepped_split(arg[1]); - if not host then - warn("Please specify a host or JID after the command"); - return 1; - elseif not prosody.hosts[host] then - warn("Unknown host: "..host); - return 1; - end - - table.remove(arg, 1); - - module.host = host; -- luacheck: ignore 122 - storagemanager.initialize_host(host); - usermanager.initialize_host(host); - - flags_map = module:open_store("account_flags", "map"); - - if command == "migrate_marks" then - migrate_marks(host); - return 0; - elseif command == "find" then - local flag = assert(arg[1], "expected argument: flag"); - local flags = module:open_store("account_flags", "map"); - local users_with_flag = flags:get_all(flag); - - local c = 0; - for user, flag_data in pairs(users_with_flag) do - print(user, os.date("%Y-%m-%d %R", flag_data.when), flag_data.comment or ""); - c = c + 1; - end - - print(("%d accounts listed"):format(c)); - return 1; - elseif command == "add" then - local username = assert(node, "expected a user JID, got "..host); - local flag = assert(arg[1], "expected argument: flag"); - local comment = arg[2]; - - local ok, err = add_flag(username, flag, comment); - if not ok then - print("Failed to add flag: "..err); - return 1; - end - - print("Flag added"); - return 1; - elseif command == "remove" then - local username = assert(node, "expected a user JID, got "..host); - local flag = assert(arg[1], "expected argument: flag"); - - local ok, err = remove_flag(username, flag); - if not ok then - print("Failed to remove flag: "..err); - return 1; - end - - print("Flag removed"); - return 1; - elseif command == "list" then - local username = assert(node, "expected a user JID, got "..host); - - local c = 0; - - local flags = module:open_store("account_flags"); - local user_flags, err = flags:get(username); - - if not user_flags and err then - print("Unable to list flags: "..err); - return 1; - end - - if user_flags then - for flag_name, flag_data in pairs(user_flags) do - print(flag_name, os.date("%Y-%m-%d %R", flag_data.when), flag_data.comment or ""); - c = c + 1; - end - end - - print(("%d flags listed"):format(c)); - return 0; - else - warn("Unknown command: %s", command); - return 1; - end -end