plugins/mod_register_limits.lua
author Kim Alvefur <zash@zash.se>
Sun, 24 Mar 2024 20:39:42 +0100
changeset 13466 720aed1f5cf2
parent 13217 50324f66ca2a
permissions -rw-r--r--
util.startup: Check root after detecting platform and reading config (thanks SigmaTel71) Ensures that startup.detect_platform() runs so know whether to use the POSIX method of checking the current user or something else. Also after reading the config so we know whether the root override setting is set.
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);