25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Add mod_fail2ban

This commit is contained in:
Evgeniy Khramtsov 2014-08-15 13:40:04 +04:00
parent bfd028beea
commit 2430e6691b
2 changed files with 107 additions and 25 deletions

View File

@ -623,9 +623,13 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
P, D, DGen)
of
{true, AuthModule} ->
?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p",
[StateData#state.socket,
jlib:jid_to_string(JID), AuthModule]),
?INFO_MSG("(~w) Accepted legacy authentication for ~s by ~p from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID), AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
Conn = get_conn_type(StateData),
Info = [{ip, StateData#state.ip}, {conn, Conn},
{auth_module, AuthModule}],
@ -660,12 +664,13 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
privacy_list = PrivList},
fsm_next_state(session_established, NewStateData);
_ ->
IP = peerip(StateData#state.sockmod,
StateData#state.socket),
?INFO_MSG("(~w) Failed legacy authentication for "
"~s from IP ~s",
[StateData#state.socket,
jlib:jid_to_string(JID), jlib:ip_to_list(IP)]),
?INFO_MSG("(~w) Failed legacy authentication for ~s from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID),
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, U, StateData#state.server,
StateData#state.ip]),
Err = jlib:make_error_reply(El, ?ERR_NOT_AUTHORIZED),
send_element(StateData, Err),
fsm_next_state(wait_for_auth, StateData)
@ -680,9 +685,13 @@ wait_for_auth({xmlstreamelement, El}, StateData) ->
fsm_next_state(wait_for_auth, StateData);
true ->
?INFO_MSG("(~w) Forbidden legacy authentication "
"for ~s",
"for ~s from ~s",
[StateData#state.socket,
jlib:jid_to_string(JID)]),
jlib:jid_to_string(JID),
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, U, StateData#state.server,
StateData#state.ip]),
Err = jlib:make_error_reply(El, ?ERR_NOT_ALLOWED),
send_element(StateData, Err),
fsm_next_state(wait_for_auth, StateData)
@ -732,8 +741,12 @@ wait_for_feature_request({xmlstreamelement, El},
%AuthModule = xml:get_attr_s(auth_module, Props),
AuthModule = proplists:get_value(auth_module, Props, undefined),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p",
[StateData#state.socket, U, AuthModule]),
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
send_element(StateData,
#xmlel{name = <<"success">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],
@ -754,10 +767,13 @@ wait_for_feature_request({xmlstreamelement, El},
fsm_next_state(wait_for_sasl_response,
StateData#state{sasl_state = NewSASLState});
{error, Error, Username} ->
IP = peerip(StateData#state.sockmod, StateData#state.socket),
?INFO_MSG("(~w) Failed authentication for ~s@~s from IP ~s",
[StateData#state.socket,
Username, StateData#state.server, jlib:ip_to_list(IP)]),
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
[StateData#state.socket,
Username, StateData#state.server,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, Username, StateData#state.server,
StateData#state.ip]),
send_element(StateData,
#xmlel{name = <<"failure">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],
@ -878,8 +894,12 @@ wait_for_sasl_response({xmlstreamelement, El},
% AuthModule = xml:get_attr_s(auth_module, Props),
AuthModule = proplists:get_value(auth_module, Props, <<>>),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p",
[StateData#state.socket, U, AuthModule]),
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
send_element(StateData,
#xmlel{name = <<"success">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],
@ -897,8 +917,12 @@ wait_for_sasl_response({xmlstreamelement, El},
% AuthModule = xml:get_attr_s(auth_module, Props),
AuthModule = proplists:get_value(auth_module, Props, undefined),
?INFO_MSG("(~w) Accepted authentication for ~s "
"by ~p",
[StateData#state.socket, U, AuthModule]),
"by ~p from ~s",
[StateData#state.socket, U, AuthModule,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[true, U, StateData#state.server,
StateData#state.ip]),
send_element(StateData,
#xmlel{name = <<"success">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],
@ -921,10 +945,13 @@ wait_for_sasl_response({xmlstreamelement, El},
fsm_next_state(wait_for_sasl_response,
StateData#state{sasl_state = NewSASLState});
{error, Error, Username} ->
IP = peerip(StateData#state.sockmod, StateData#state.socket),
?INFO_MSG("(~w) Failed authentication for ~s@~s from IP ~s",
[StateData#state.socket,
Username, StateData#state.server, jlib:ip_to_list(IP)]),
?INFO_MSG("(~w) Failed authentication for ~s@~s from ~s",
[StateData#state.socket,
Username, StateData#state.server,
jlib:ip_to_list(StateData#state.ip)]),
ejabberd_hooks:run(c2s_auth_result, StateData#state.server,
[false, Username, StateData#state.server,
StateData#state.ip]),
send_element(StateData,
#xmlel{name = <<"failure">>,
attrs = [{<<"xmlns">>, ?NS_SASL}],

55
src/mod_fail2ban.erl Normal file
View File

@ -0,0 +1,55 @@
%%%-------------------------------------------------------------------
%%% @author Evgeny Khramtsov <ekhramtsov@process-one.net>
%%% @copyright (C) 2014, Evgeny Khramtsov
%%% @doc
%%%
%%% @end
%%% Created : 15 Aug 2014 by Evgeny Khramtsov <ekhramtsov@process-one.net>
%%%-------------------------------------------------------------------
-module(mod_fail2ban).
-behaviour(gen_mod).
%% API
-export([start/2, stop/1, c2s_auth_result/4]).
-include("jlib.hrl").
%%%===================================================================
%%% API
%%%===================================================================
start(Host, _Opts) ->
ets:new(failed_auth, [bag, named_table, public]),
ejabberd_hooks:add(c2s_auth_result, Host, ?MODULE, c2s_auth_result, 100).
stop(Host) ->
ejabberd_hooks:delete(c2s_auth_result, Host, ?MODULE, c2s_auth_result, 100).
%%%===================================================================
%%% Internal functions
%%%===================================================================
c2s_auth_result(true, User, Server, {Addr, _Port}) ->
case jlib:make_jid(User, Server, <<"">>) of
#jid{luser = LUser, lserver = LServer} ->
US = {LUser, LServer},
Objs = ets:lookup(failed_auth, Addr),
case lists:filter(fun({_, US1, _}) -> US1 == US end, Objs) of
[_|_] ->
ets:match_delete(failed_auth, {'_', US, '_'});
[] ->
true
end;
_ ->
false
end;
c2s_auth_result(false, User, Server, {Addr, _Port}) ->
case jlib:make_jid(User, Server, <<"">>) of
#jid{luser = LUser, lserver = LServer} ->
US = {LUser, LServer},
ets:insert(failed_auth, {Addr, US, now()}),
Objs = ets:match_object(failed_auth, {'_', US, '_'}),
Timeout = round(math:exp(length(Objs))),
timer:sleep(timer:seconds(Timeout));
_ ->
ok
end.