diff options
author | Pablo Polvorin <pablo.polvorin@process-one.net> | 2011-12-02 15:30:20 -0300 |
---|---|---|
committer | Pablo Polvorin <pablo.polvorin@process-one.net> | 2011-12-02 15:30:20 -0300 |
commit | cf973f27bb62dbb1e5c89b062eae491a646860db (patch) | |
tree | b695adfc9f5cf9f887b0478f855a69107e060ccc /src/ejabberd_s2s.erl | |
parent | Fix bug on s2s shaper when TLS is used (diff) |
Prevent overload of incomming s2s connections
Three changes were introduced:
1) ejabberd_s2s_in now uses p1_fsm instead of gen_fsm. And uses
the {max_queue, N} option to kill the process if its input
queue grows too much.
2) If a ejabberd_s2s_in process is overload and killed, the server
that originated that connection is not allowed to connect back
to us for X seconds (set to 60seconds on the source)
3) The list of blocked (both statically and dynamically by the above
method) host is now also checked for hosts authenticating by
starttls+sasl. Previusly it was only used during dialback.
Diffstat (limited to 'src/ejabberd_s2s.erl')
-rw-r--r-- | src/ejabberd_s2s.erl | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/src/ejabberd_s2s.erl b/src/ejabberd_s2s.erl index 1ca4b37f9..476233d7d 100644 --- a/src/ejabberd_s2s.erl +++ b/src/ejabberd_s2s.erl @@ -41,7 +41,11 @@ dirty_get_connections/0, allow_host/2, incoming_s2s_number/0, - outgoing_s2s_number/0 + outgoing_s2s_number/0, + clean_temporarily_blocked_table/0, + list_temporarily_blocked_hosts/0, + external_host_overloaded/1, + is_temporarly_blocked/1 ]). %% gen_server callbacks @@ -57,9 +61,14 @@ -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER, 1). -define(DEFAULT_MAX_S2S_CONNECTIONS_NUMBER_PER_NODE, 1). +-define(S2S_OVERLOAD_BLOCK_PERIOD, 60). +%% once a server is temporarly blocked, it stay blocked for 60 seconds + -record(s2s, {fromto, pid, key}). -record(state, {}). +-record(temporarily_blocked, {host, timestamp}). + %%==================================================================== %% API %%==================================================================== @@ -79,6 +88,31 @@ route(From, To, Packet) -> ok end. +clean_temporarily_blocked_table() -> + mnesia:clear_table(temporarily_blocked). +list_temporarily_blocked_hosts() -> + ets:tab2list(temporarily_blocked). + +external_host_overloaded(Host) -> + ?INFO_MSG("Disabling connections from ~s for ~p seconds", [Host, ?S2S_OVERLOAD_BLOCK_PERIOD]), + mnesia:transaction( fun() -> + mnesia:write(#temporarily_blocked{host = Host, timestamp = now()}) + end). + +is_temporarly_blocked(Host) -> + case mnesia:dirty_read(temporarily_blocked, Host) of + [] -> false; + [#temporarily_blocked{timestamp = T}=Entry] -> + case timer:now_diff(now(), T) of + N when N > ?S2S_OVERLOAD_BLOCK_PERIOD * 1000 * 1000 -> + mnesia:dirty_delete_object(Entry), + false; + _ -> + true + end + end. + + remove_connection(FromTo, Pid, Key) -> case catch mnesia:dirty_match_object(s2s, #s2s{fromto = FromTo, pid = Pid, @@ -169,6 +203,7 @@ init([]) -> mnesia:add_table_copy(s2s, node(), ram_copies), mnesia:subscribe(system), ejabberd_commands:register_commands(commands()), + mnesia:create_table(temporarily_blocked, [{ram_copies, [node()]}, {attributes, record_info(fields, temporarily_blocked)}]), {ok, #state{}}. %%-------------------------------------------------------------------- @@ -486,6 +521,9 @@ update_tables() -> %% Check if host is in blacklist or white list allow_host(MyServer, S2SHost) -> + allow_host2(MyServer, S2SHost) andalso (not is_temporarly_blocked(S2SHost)). + +allow_host2(MyServer, S2SHost) -> Hosts = ?MYHOSTS, case lists:dropwhile( fun(ParentDomain) -> |