plugins/mod_register_limits.lua
author Kim Alvefur <zash@zash.se>
Thu, 28 Mar 2024 15:26:57 +0100
changeset 13472 98806cac64c3
parent 13217 50324f66ca2a
permissions -rw-r--r--
MUC: Switch to official XEP-0317 namespace for Hats (including compat) (thanks nicoco)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1523
841d61be198f Remove version number from copyright headers
Matthew Wild <mwild1@gmail.com>
parents: 1189
diff changeset
     1
-- Prosody IM
2923
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2448
diff changeset
     2
-- Copyright (C) 2008-2010 Matthew Wild
b7049746bd29 Update copyright headers for 2010
Matthew Wild <mwild1@gmail.com>
parents: 2448
diff changeset
     3
-- Copyright (C) 2008-2010 Waqas Hussain
5776
bd0ff8ae98a8 Remove all trailing whitespace
Florian Zeitz <florob@babelmonkeys.de>
parents: 5763
diff changeset
     4
--
758
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 691
diff changeset
     5
-- This project is MIT/X11 licensed. Please see the
b1885732e979 GPL->MIT!
Matthew Wild <mwild1@gmail.com>
parents: 691
diff changeset
     6
-- COPYING file in the source package for more information.
519
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 438
diff changeset
     7
--
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 438
diff changeset
     8
cccd610a0ef9 Insert copyright/license headers
Matthew Wild <mwild1@gmail.com>
parents: 438
diff changeset
     9
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11811
diff changeset
    10
local create_throttle = require "prosody.util.throttle".create;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11811
diff changeset
    11
local new_cache = require "prosody.util.cache".new;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11811
diff changeset
    12
local ip_util = require "prosody.util.ip";
8455
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    13
local new_ip = ip_util.new_ip;
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    14
local match_ip = ip_util.match;
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    15
local parse_cidr = ip_util.parse_cidr;
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 11811
diff changeset
    16
local errors = require "prosody.util.error";
3995
e504b06492c6 mod_register: Add registration_compat config option to allow account remove requests addressed to='host' (defaults to true)
Matthew Wild <mwild1@gmail.com>
parents: 3540
diff changeset
    17
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    18
-- COMPAT drop old option names
13213
c8d949cf6b09 plugins: Switch to :get_option_period() for time range options
Kim Alvefur <zash@zash.se>
parents: 12981
diff changeset
    19
local min_seconds_between_registrations = module:get_option_period("min_seconds_between_registrations");
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    20
local allowlist_only = module:get_option_boolean("allowlist_registration_only", module:get_option_boolean("whitelist_registration_only"));
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    21
local allowlisted_ips = module:get_option_set("registration_allowlist", module:get_option("registration_whitelist", { "127.0.0.1", "::1" }))._items;
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    22
local blocklisted_ips = module:get_option_set("registration_blocklist", module:get_option_set("registration_blacklist", {}))._items;
690
e901a0709005 Added rate limiting to in-band registration, and added IP [black/white]lists
Matthew Wild <mwild1@gmail.com>
parents: 665
diff changeset
    23
13217
50324f66ca2a plugins: Use integer config API with interval specification where sensible
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
    24
local throttle_max = module:get_option_number("registration_throttle_max", min_seconds_between_registrations and 1, 0);
13213
c8d949cf6b09 plugins: Switch to :get_option_period() for time range options
Kim Alvefur <zash@zash.se>
parents: 12981
diff changeset
    25
local throttle_period = module:get_option_period("registration_throttle_period", min_seconds_between_registrations);
13217
50324f66ca2a plugins: Use integer config API with interval specification where sensible
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
    26
local throttle_cache_size = module:get_option_integer("registration_throttle_cache_size", 100, 1);
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    27
local blocklist_overflow = module:get_option_boolean("blocklist_on_registration_throttle_overload",
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    28
	module:get_option_boolean("blacklist_on_registration_throttle_overload", false));
690
e901a0709005 Added rate limiting to in-band registration, and added IP [black/white]lists
Matthew Wild <mwild1@gmail.com>
parents: 665
diff changeset
    29
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    30
local throttle_cache = new_cache(throttle_cache_size, blocklist_overflow and function (ip, throttle)
7030
77d838ba91c6 mod_register: Support for blacklisting ips that are still over limit when they get pushed out of the cache
Kim Alvefur <zash@zash.se>
parents: 7029
diff changeset
    31
	if not throttle:peek() then
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    32
		module:log("info", "Adding ip %s to registration blocklist", ip);
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    33
		blocklisted_ips[ip] = true;
7030
77d838ba91c6 mod_register: Support for blacklisting ips that are still over limit when they get pushed out of the cache
Kim Alvefur <zash@zash.se>
parents: 7029
diff changeset
    34
	end
7296
c4af754d1e1b mod_register: Make sure only an on_evict function or nil is passed to util.cache
Kim Alvefur <zash@zash.se>
parents: 7040
diff changeset
    35
end or nil);
7028
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    36
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    37
local function check_throttle(ip)
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    38
	if not throttle_max then return true end
7029
f0dc5cc11d0e mod_register: Use util.cache to limit the number of per-ip throttles kept
Kim Alvefur <zash@zash.se>
parents: 7028
diff changeset
    39
	local throttle = throttle_cache:get(ip);
7028
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    40
	if not throttle then
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    41
		throttle = create_throttle(throttle_max, throttle_period);
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    42
	end
7029
f0dc5cc11d0e mod_register: Use util.cache to limit the number of per-ip throttles kept
Kim Alvefur <zash@zash.se>
parents: 7028
diff changeset
    43
	throttle_cache:set(ip, throttle);
7028
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    44
	return throttle:poll(1);
236e8d1ee96c mod_register: Switch to using util.throttle for limiting registrations per ip per time
Kim Alvefur <zash@zash.se>
parents: 7021
diff changeset
    45
end
690
e901a0709005 Added rate limiting to in-band registration, and added IP [black/white]lists
Matthew Wild <mwild1@gmail.com>
parents: 665
diff changeset
    46
8455
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    47
local function ip_in_set(set, ip)
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    48
	if set[ip] then
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    49
		return true;
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    50
	end
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    51
	ip = new_ip(ip);
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    52
	for in_set in pairs(set) do
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    53
		if match_ip(ip, parse_cidr(in_set)) then
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    54
			return true;
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    55
		end
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    56
	end
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    57
	return false;
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    58
end
4796fdcb7146 mod_register: Support CIDR notation in white-/blacklists (closes #941)
Kim Alvefur <zash@zash.se>
parents: 8197
diff changeset
    59
10368
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    60
local err_registry = {
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    61
	blocklisted = {
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    62
		text = "Your IP address is blocklisted";
10368
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    63
		type = "auth";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    64
		condition = "forbidden";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    65
	};
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    66
	not_allowlisted = {
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    67
		text = "Your IP address is not allowlisted";
10368
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    68
		type = "auth";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    69
		condition = "forbidden";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    70
	};
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    71
	throttled = {
10772
55a9e9bf6abb mod_register_limits: Fix text reason field name for 'throttled'
Kim Alvefur <zash@zash.se>
parents: 10770
diff changeset
    72
		text = "Too many registrations from this IP address recently";
10368
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    73
		type = "wait";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    74
		condition = "policy-violation";
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    75
	};
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    76
}
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    77
8488
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    78
module:hook("user-registering", function (event)
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    79
	local session = event.session;
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    80
	local ip = event.ip or session and session.ip;
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    81
	local log = session and session.log or module._log;
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    82
	if not ip then
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    83
		log("warn", "IP not known; can't apply blocklist/allowlist");
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    84
	elseif ip_in_set(blocklisted_ips, ip) then
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    85
		log("debug", "Registration disallowed by blocklist");
8588
046041a37c1e mod_register_limits: Log message for white- and blacklist hits separate
Kim Alvefur <zash@zash.se>
parents: 8587
diff changeset
    86
		event.allowed = false;
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    87
		event.error = errors.new("blocklisted", event, err_registry);
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    88
	elseif (allowlist_only and not ip_in_set(allowlisted_ips, ip)) then
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    89
		log("debug", "Registration disallowed by allowlist");
8488
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    90
		event.allowed = false;
11811
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    91
		event.error = errors.new("not_allowlisted", event, err_registry);
f5295e59ca78 mod_register_limits: Reword some options
Kim Alvefur <zash@zash.se>
parents: 10772
diff changeset
    92
	elseif throttle_max and not ip_in_set(allowlisted_ips, ip) then
8741
9f0dc1bbc83b mod_register_limits: Use existing local variable
Kim Alvefur <zash@zash.se>
parents: 8589
diff changeset
    93
		if not check_throttle(ip) then
8488
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    94
			log("debug", "Registrations over limit for ip %s", ip or "?");
0e02c6de5c02 mod_register_ibr: Split out throttling and IP limitations into mod_register_limits (#723)
Kim Alvefur <zash@zash.se>
parents: 8487
diff changeset
    95
			event.allowed = false;
10770
00d2a577204c mod_register_limits: Fix typo error name (fix #1539 p2) (thanks Ge0rG)
Kim Alvefur <zash@zash.se>
parents: 10769
diff changeset
    96
			event.error = errors.new("throttled", event, err_registry);
60
44800be871f5 User registration, etc (jabber:iq:register)
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
    97
		end
3529
3f9cc12308aa mod_register: Updated to use the new events API.
Waqas Hussain <waqas20@gmail.com>
parents: 3394
diff changeset
    98
	end
10368
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
    99
	if event.error then
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
   100
		-- COMPAT pre-util.error
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
   101
		event.reason = event.error.text;
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
   102
		event.error_type = event.error.type;
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
   103
		event.error_condition = event.error.condition;
66943afdd7f3 mod_register_limits: Use util.error for managing rejection reasons
Kim Alvefur <zash@zash.se>
parents: 10290
diff changeset
   104
	end
60
44800be871f5 User registration, etc (jabber:iq:register)
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
   105
end);