aboutsummaryrefslogtreecommitdiff
path: root/src/ejabberd_s2s.erl
diff options
context:
space:
mode:
authorPablo Polvorin <pablo.polvorin@process-one.net>2011-12-02 15:30:20 -0300
committerPablo Polvorin <pablo.polvorin@process-one.net>2011-12-02 15:30:20 -0300
commitcf973f27bb62dbb1e5c89b062eae491a646860db (patch)
treeb695adfc9f5cf9f887b0478f855a69107e060ccc /src/ejabberd_s2s.erl
parentFix 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.erl40
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) ->