1
0
Fork 0
mirror of https://github.com/processone/ejabberd synced 2025-10-03 09:49:18 +02:00

Replace options rtbl_host and rtbl_domains_node with rtbl_services

This commit is contained in:
Badlop 2025-06-27 17:56:58 +02:00
parent d862e04186
commit 5e93725044
7 changed files with 76 additions and 22 deletions

View file

@ -24,3 +24,13 @@
-type filename() :: binary() | none | false. -type filename() :: binary() | none | false.
-type jid_set() :: sets:set(ljid()). -type jid_set() :: sets:set(ljid()).
-type url_set() :: sets:set(url()). -type url_set() :: sets:set(url()).
-define(DEFAULT_RTBL_DOMAINS_NODE, <<"spam_source_domains">>).
-record(rtbl_service,
{host = none :: binary() | none,
node = ?DEFAULT_RTBL_DOMAINS_NODE :: binary(),
subscribed = false :: boolean(),
retry_timer = undefined :: reference() | undefined}).
-type rtbl_service() :: #rtbl_service{}.

View file

@ -51,6 +51,8 @@
terminate/2, terminate/2,
code_change/3]). code_change/3]).
-export([get_rtbl_services_option/1]).
%% ejabberd_commands callbacks. %% ejabberd_commands callbacks.
-export([add_blocked_domain/2, -export([add_blocked_domain/2,
add_to_spam_filter_cache/2, add_to_spam_filter_cache/2,
@ -87,7 +89,6 @@
-type state() :: #state{}. -type state() :: #state{}.
-define(COMMAND_TIMEOUT, timer:seconds(30)). -define(COMMAND_TIMEOUT, timer:seconds(30)).
-define(DEFAULT_RTBL_DOMAINS_NODE, <<"spam_source_domains">>).
-define(DEFAULT_CACHE_SIZE, 10000). -define(DEFAULT_CACHE_SIZE, 10000).
%% @format-begin %% @format-begin
@ -137,12 +138,14 @@ mod_opt_type(access_spam) ->
econf:acl(); econf:acl();
mod_opt_type(cache_size) -> mod_opt_type(cache_size) ->
econf:pos_int(unlimited); econf:pos_int(unlimited);
mod_opt_type(rtbl_host) -> mod_opt_type(rtbl_services) ->
econf:either( econf:list(
econf:enum([none]), econf:host()); econf:either(
mod_opt_type(rtbl_domains_node) -> econf:binary(),
econf:non_empty( econf:map(
econf:binary()); econf:binary(),
econf:map(
econf:enum([spam_source_domains_node]), econf:binary()))));
mod_opt_type(spam_domains_file) -> mod_opt_type(spam_domains_file) ->
econf:either( econf:either(
econf:enum([none]), econf:file()); econf:enum([none]), econf:file());
@ -159,12 +162,11 @@ mod_opt_type(whitelist_domains_file) ->
econf:either( econf:either(
econf:enum([none]), econf:file()). econf:enum([none]), econf:file()).
-spec mod_options(binary()) -> [{atom(), any()}]. -spec mod_options(binary()) -> [{rtbl_services, [tuple()]} | {atom(), any()}].
mod_options(_Host) -> mod_options(_Host) ->
[{access_spam, none}, [{access_spam, none},
{cache_size, ?DEFAULT_CACHE_SIZE}, {cache_size, ?DEFAULT_CACHE_SIZE},
{rtbl_domains_node, ?DEFAULT_RTBL_DOMAINS_NODE}, {rtbl_services, []},
{rtbl_host, none},
{spam_domains_file, none}, {spam_domains_file, none},
{spam_dump_file, false}, {spam_dump_file, false},
{spam_jids_file, none}, {spam_jids_file, none},
@ -200,6 +202,21 @@ mod_doc() ->
"Note that separate caches are used for each virtual host, " "Note that separate caches are used for each virtual host, "
" and that the caches aren't distributed across cluster nodes. " " and that the caches aren't distributed across cluster nodes. "
"The default value is '10000'.")}}, "The default value is '10000'.")}},
{rtbl_services,
#{value => ?T("[Service]"),
example =>
["rtbl_services:",
" - pubsub.server1.localhost:",
" spam_source_domains_node: actual_custom_pubsub_node"],
desc =>
?T("Query a RTBL service to get domains to block, as provided by "
"https://xmppbl.org/[xmppbl.org]. "
"Please note right now this option only supports one service in that list. "
"For blocking spam and abuse on MUC channels, please use _`mod_muc_rtbl`_ for now. "
"If only the host is provided, the default node names will be assumed. "
"If the node name is different than 'spam_source_domains', "
"you can setup the custom node name with the option 'spam_source_domains_node'. "
"The default value is an empty list of services.")}},
{spam_domains_file, {spam_domains_file,
#{value => ?T("none | Path"), #{value => ?T("none | Path"),
desc => desc =>
@ -253,6 +270,8 @@ mod_doc() ->
example => example =>
["modules:", ["modules:",
" mod_antispam:", " mod_antispam:",
" rtbl_services:",
" - xmppbl.org",
" spam_jids_file: \"@CONFIG_PATH@/spam_jids.txt\"", " spam_jids_file: \"@CONFIG_PATH@/spam_jids.txt\"",
" spam_dump_file: \"@LOG_PATH@/spam/host-@HOST@.log\""]}. " spam_dump_file: \"@LOG_PATH@/spam/host-@HOST@.log\""]}.
@ -274,8 +293,7 @@ init([Host, Opts]) ->
mod_antispam_rtbl, mod_antispam_rtbl,
pubsub_event_handler, pubsub_event_handler,
50), 50),
RTBLHost = gen_mod:get_opt(rtbl_host, Opts), [#rtbl_service{host = RTBLHost, node = RTBLDomainsNode}] = get_rtbl_services_option(Opts),
RTBLDomainsNode = gen_mod:get_opt(rtbl_domains_node, Opts),
mod_antispam_filter:init_filtering(Host), mod_antispam_filter:init_filtering(Host),
InitState = InitState =
#state{host = Host, #state{host = Host,
@ -384,8 +402,8 @@ handle_cast({reload, NewOpts, OldOpts},
end, end,
ok = mod_antispam_rtbl:unsubscribe(OldRTBLHost, OldRTBLDomainsNode, Host), ok = mod_antispam_rtbl:unsubscribe(OldRTBLHost, OldRTBLDomainsNode, Host),
{_Result, State3} = reload_files(State2#state{blocked_domains = #{}}), {_Result, State3} = reload_files(State2#state{blocked_domains = #{}}),
RTBLHost = gen_mod:get_opt(rtbl_host, NewOpts), [#rtbl_service{host = RTBLHost, node = RTBLDomainsNode}] =
RTBLDomainsNode = gen_mod:get_opt(rtbl_domains_node, NewOpts), get_rtbl_services_option(NewOpts),
ok = mod_antispam_rtbl:request_blocked_domains(RTBLHost, RTBLDomainsNode, Host), ok = mod_antispam_rtbl:request_blocked_domains(RTBLHost, RTBLDomainsNode, Host),
{noreply, State3#state{rtbl_host = RTBLHost, rtbl_domains_node = RTBLDomainsNode}}; {noreply, State3#state{rtbl_host = RTBLHost, rtbl_domains_node = RTBLDomainsNode}};
handle_cast({update_blocked_domains, NewItems}, handle_cast({update_blocked_domains, NewItems},
@ -565,6 +583,27 @@ read_files(Host) ->
whitelist_domains => gen_mod:get_module_opt(Host, ?MODULE, whitelist_domains_file)}, whitelist_domains => gen_mod:get_module_opt(Host, ?MODULE, whitelist_domains_file)},
ejabberd_hooks:run_fold(antispam_get_lists, Host, AccInitial, [Files]). ejabberd_hooks:run_fold(antispam_get_lists, Host, AccInitial, [Files]).
get_rtbl_services_option(Host) when is_binary(Host) ->
get_rtbl_services_option(gen_mod:get_module_opts(Host, ?MODULE));
get_rtbl_services_option(Opts) when is_map(Opts) ->
Services = gen_mod:get_opt(rtbl_services, Opts),
case length(Services) =< 1 of
true ->
ok;
false ->
?WARNING_MSG("Option rtbl_services only supports one service, but several "
"were configured. Will use only first one",
[])
end,
case Services of
[] ->
[#rtbl_service{}];
[Host | _] when is_binary(Host) ->
[#rtbl_service{host = Host, node = ?DEFAULT_RTBL_DOMAINS_NODE}];
[[{Host, [{spam_source_domains_node, Node}]}] | _] ->
[#rtbl_service{host = Host, node = Node}]
end.
-spec get_proc_name(binary()) -> atom(). -spec get_proc_name(binary()) -> atom().
get_proc_name(Host) -> get_proc_name(Host) ->
gen_mod:get_module_proc(Host, ?MODULE). gen_mod:get_module_proc(Host, ?MODULE).

View file

@ -52,7 +52,6 @@
-define(COMMAND_TIMEOUT, timer:seconds(30)). -define(COMMAND_TIMEOUT, timer:seconds(30)).
-define(DEFAULT_CACHE_SIZE, 10000). -define(DEFAULT_CACHE_SIZE, 10000).
-define(DEFAULT_RTBL_DOMAINS_NODE, <<"spam_source_domains">>).
-define(HTTPC_TIMEOUT, timer:seconds(3)). -define(HTTPC_TIMEOUT, timer:seconds(3)).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------

View file

@ -78,7 +78,7 @@ request_blocked_domains(RTBLHost, RTBLDomainsNode, From) ->
-spec parse_blocked_domains(stanza()) -> #{binary() => any()} | undefined. -spec parse_blocked_domains(stanza()) -> #{binary() => any()} | undefined.
parse_blocked_domains(#iq{to = #jid{lserver = LServer}, type = result} = IQ) -> parse_blocked_domains(#iq{to = #jid{lserver = LServer}, type = result} = IQ) ->
?DEBUG("parsing iq-result items: ~p", [IQ]), ?DEBUG("parsing iq-result items: ~p", [IQ]),
RTBLDomainsNode = gen_mod:get_module_opt(LServer, ?SERVICE_MODULE, rtbl_domains_node), [#rtbl_service{node = RTBLDomainsNode}] = mod_antispam:get_rtbl_services_option(LServer),
case xmpp:get_subtag(IQ, #pubsub{}) of case xmpp:get_subtag(IQ, #pubsub{}) of
#pubsub{items = #ps_items{node = RTBLDomainsNode, items = Items}} -> #pubsub{items = #ps_items{node = RTBLDomainsNode, items = Items}} ->
?DEBUG("Got items:~n~p", [Items]), ?DEBUG("Got items:~n~p", [Items]),
@ -89,7 +89,7 @@ parse_blocked_domains(#iq{to = #jid{lserver = LServer}, type = result} = IQ) ->
-spec parse_pubsub_event(stanza()) -> #{binary() => any()}. -spec parse_pubsub_event(stanza()) -> #{binary() => any()}.
parse_pubsub_event(#message{to = #jid{lserver = LServer}} = Msg) -> parse_pubsub_event(#message{to = #jid{lserver = LServer}} = Msg) ->
RTBLDomainsNode = gen_mod:get_module_opt(LServer, ?SERVICE_MODULE, rtbl_domains_node), [#rtbl_service{node = RTBLDomainsNode}] = mod_antispam:get_rtbl_services_option(LServer),
case xmpp:get_subtag(Msg, #ps_event{}) of case xmpp:get_subtag(Msg, #ps_event{}) of
#ps_event{items = #ps_event{items =
#ps_items{node = RTBLDomainsNode, #ps_items{node = RTBLDomainsNode,
@ -130,7 +130,8 @@ pubsub_event_handler(#message{from = FromJid,
Msg) -> Msg) ->
?DEBUG("Got RTBL message:~n~p", [Msg]), ?DEBUG("Got RTBL message:~n~p", [Msg]),
From = jid:encode(FromJid), From = jid:encode(FromJid),
case gen_mod:get_module_opt(LServer, ?SERVICE_MODULE, rtbl_host) of [#rtbl_service{host = RTBLHost}] = mod_antispam:get_rtbl_services_option(LServer),
case RTBLHost of
From -> From ->
ParsedItems = parse_pubsub_event(Msg), ParsedItems = parse_pubsub_event(Msg),
Proc = gen_mod:get_module_proc(LServer, ?SERVICE_MODULE), Proc = gen_mod:get_module_proc(LServer, ?SERVICE_MODULE),

View file

@ -31,6 +31,7 @@
disconnect/1, put_event/2, get_event/1, peer_muc_jid/1, disconnect/1, put_event/2, get_event/1, peer_muc_jid/1,
my_muc_jid/1, get_features/2, set_opt/3]). my_muc_jid/1, get_features/2, set_opt/3]).
-include("suite.hrl"). -include("suite.hrl").
-include("mod_antispam.hrl").
%% @format-begin %% @format-begin
@ -166,7 +167,8 @@ rtbl_domains(Config) ->
RTBLDomainsNode = <<"spam_source_domains">>, RTBLDomainsNode = <<"spam_source_domains">>,
OldOpts = gen_mod:get_module_opts(Host, mod_antispam), OldOpts = gen_mod:get_module_opts(Host, mod_antispam),
NewOpts = NewOpts =
maps:merge(OldOpts, #{rtbl_host => RTBLHost, rtbl_domains_node => RTBLDomainsNode}), maps:merge(OldOpts,
#{rtbl_services => [#rtbl_service{host = RTBLHost, node = RTBLDomainsNode}]}),
Owner = jid:make(?config(user, Config), ?config(server, Config), <<>>), Owner = jid:make(?config(user, Config), ?config(server, Config), <<>>),
{result, _} = {result, _} =
mod_pubsub:create_node(RTBLHost, mod_pubsub:create_node(RTBLHost,
@ -210,7 +212,8 @@ rtbl_domains_whitelisted(Config) ->
RTBLDomainsNode = <<"spam_source_domains">>, RTBLDomainsNode = <<"spam_source_domains">>,
OldOpts = gen_mod:get_module_opts(Host, mod_antispam), OldOpts = gen_mod:get_module_opts(Host, mod_antispam),
NewOpts = NewOpts =
maps:merge(OldOpts, #{rtbl_host => RTBLHost, rtbl_domains_node => RTBLDomainsNode}), maps:merge(OldOpts,
#{rtbl_services => [#rtbl_service{host = RTBLHost, node = RTBLDomainsNode}]}),
Owner = jid:make(?config(user, Config), ?config(server, Config), <<>>), Owner = jid:make(?config(user, Config), ?config(server, Config), <<>>),
{result, _} = {result, _} =
mod_pubsub:create_node(RTBLHost, mod_pubsub:create_node(RTBLHost,

View file

@ -7,7 +7,8 @@ define_macro:
db_type: internal db_type: internal
access: local access: local
mod_antispam: mod_antispam:
rtbl_host: pubsub.mnesia.localhost rtbl_services:
- "pubsub.mnesia.localhost"
spam_jids_file: spam_jids.txt spam_jids_file: spam_jids.txt
spam_domains_file: spam_domains.txt spam_domains_file: spam_domains.txt
spam_urls_file: spam_urls.txt spam_urls_file: spam_urls.txt

View file

@ -8,7 +8,8 @@ define_macro:
db_type: internal db_type: internal
access: local access: local
mod_antispam: mod_antispam:
rtbl_host: pubsub.redis.localhost rtbl_services:
- "pubsub.redis.localhost"
spam_jids_file: spam_jids.txt spam_jids_file: spam_jids.txt
spam_domains_file: spam_domains.txt spam_domains_file: spam_domains.txt
spam_urls_file: spam_urls.txt spam_urls_file: spam_urls.txt