From: Christophe Romain Date: Fri, 11 Jul 2008 06:59:45 +0000 (+0000) Subject: Backport C2S blacklist support from trunk X-Git-Tag: v2.0.2~53 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bc18e89d615b39a2dfd5d8347601f4bc1d680cf5;p=ejabberd Backport C2S blacklist support from trunk SVN Revision: 1431 --- diff --git a/ChangeLog b/ChangeLog index f9c68ed70..5ae951697 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-07-11 Christophe Romain + + * src/ejabberd_c2s.erl: Backport C2S blacklist support from trunk + was (EJAB-625). + * src/mod_ip_blacklist.erl: Likewise. + 2008-07-10 Badlop * src/configure.ac: Don't check for erlang header file (EJAB-232) diff --git a/src/ejabberd_c2s.erl b/src/ejabberd_c2s.erl index 3810edf40..2d8e315e1 100644 --- a/src/ejabberd_c2s.erl +++ b/src/ejabberd_c2s.erl @@ -176,26 +176,34 @@ init([{SockMod, Socket}, Opts]) -> (_) -> false end, Opts), IP = peerip(SockMod, Socket), - Socket1 = - if - TLSEnabled -> - SockMod:starttls(Socket, TLSOpts); - true -> - Socket - end, - SocketMonitor = SockMod:monitor(Socket1), - {ok, wait_for_stream, #state{socket = Socket1, - sockmod = SockMod, - socket_monitor = SocketMonitor, - zlib = Zlib, - tls = TLS, - tls_required = StartTLSRequired, - tls_enabled = TLSEnabled, - tls_options = TLSOpts, - streamid = new_id(), - access = Access, - shaper = Shaper, - ip = IP}, ?C2S_OPEN_TIMEOUT}. + %% Check if IP is blacklisted: + case is_ip_blacklisted(IP) of + true -> + ?INFO_MSG("Connection attempt from blacklisted IP: ~s", + [jlib:ip_to_list(IP)]), + {stop, normal}; + false -> + Socket1 = + if + TLSEnabled -> + SockMod:starttls(Socket, TLSOpts); + true -> + Socket + end, + SocketMonitor = SockMod:monitor(Socket1), + {ok, wait_for_stream, #state{socket = Socket1, + sockmod = SockMod, + socket_monitor = SocketMonitor, + zlib = Zlib, + tls = TLS, + tls_required = StartTLSRequired, + tls_enabled = TLSEnabled, + tls_options = TLSOpts, + streamid = new_id(), + access = Access, + shaper = Shaper, + ip = IP}, ?C2S_OPEN_TIMEOUT} + end. %% Return list of all available resources of contacts, %% in form [{JID, Caps}]. @@ -1955,3 +1963,7 @@ fsm_reply(Reply, session_established, StateData) -> {reply, Reply, session_established, StateData, ?C2S_HIBERNATE_TIMEOUT}; fsm_reply(Reply, StateName, StateData) -> {reply, Reply, StateName, StateData, ?C2S_OPEN_TIMEOUT}. + +%% Used by c2s blacklist plugins +is_ip_blacklisted({IP,_Port}) -> + ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]). diff --git a/src/mod_ip_blacklist.erl b/src/mod_ip_blacklist.erl new file mode 100644 index 000000000..6a0cc3947 --- /dev/null +++ b/src/mod_ip_blacklist.erl @@ -0,0 +1,119 @@ +%%%---------------------------------------------------------------------- +%%% File : mod_ip_blacklist.erl +%%% Author : Mickael Remond +%%% Purpose : Download blacklists from ProcessOne +%%% Created : 5 May 2008 by Mickael Remond +%%% Usage : Add the following line in modules section of ejabberd.cfg: +%%% {mod_ip_blacklist, []} +%%% +%%% +%%% ejabberd, Copyright (C) 2002-2008 Process-one +%%% +%%% This program is free software; you can redistribute it and/or +%%% modify it under the terms of the GNU General Public License as +%%% published by the Free Software Foundation; either version 2 of the +%%% License, or (at your option) any later version. +%%% +%%% This program is distributed in the hope that it will be useful, +%%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +%%% General Public License for more details. +%%% +%%% You should have received a copy of the GNU General Public License +%%% along with this program; if not, write to the Free Software +%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +%%% 02111-1307 USA +%%% +%%%---------------------------------------------------------------------- + +-module(mod_ip_blacklist). +-author('mremond@process-one.net'). + +-behaviour(gen_mod). + +%% API: +-export([start/2, + init/1, + stop/1]). +-export([update_bl_c2s/0]). +%% Hooks: +-export([is_ip_in_c2s_blacklist/2]). + +-include("ejabberd.hrl"). + +-define(PROCNAME, ?MODULE). +-define(BLC2S, "http://xaai.process-one.net/bl_c2s.txt"). +-define(UPDATE_INTERVAL, 6). %% in hours + +-record(state, {timer}). +-record(bl_c2s, {ip}). + +%% Start once for all vhost +start(Host, Opts) -> + case whereis(?PROCNAME) of + undefined -> + ?DEBUG("Starting mod_ip_blacklist ~p ~p~n", [Host, Opts]), + register(?PROCNAME, + spawn(?MODULE, init, [#state{}])); + _ -> + ok + end. + +%% TODO: +stop(_Host) -> + ok. + +init(State)-> + inets:start(), + ets:new(bl_c2s, [named_table, public, {keypos, #bl_c2s.ip}]), + update_bl_c2s(), + %% Register hooks for blacklist + ejabberd_hooks:add(check_bl_c2s, ?MODULE, is_ip_in_c2s_blacklist, 50), + %% Set timer: Download the blacklist file every 6 hours + timer:apply_interval(timer:hours(?UPDATE_INTERVAL), ?MODULE, update_bl_c2s, []), + loop(State). + +%% Remove timer when stop is received. +loop(_State) -> + receive + stop -> + ok + end. + +%% Download blacklist file from ProcessOne XAAI +%% and update the table internal table +%% TODO: Support comment lines starting by % +update_bl_c2s() -> + ?INFO_MSG("Updating C2S Blacklist", []), + case http:request(?BLC2S) of + {ok, {{_Version, 200, _Reason}, _Headers, Body}} -> + IPs = string:tokens(Body,"\n"), + ets:delete_all_objects(bl_c2s), + lists:foreach( + fun(IP) -> + ets:insert(bl_c2s, #bl_c2s{ip=list_to_binary(IP)}) + end, IPs); + {error, Reason} -> + ?ERROR_MSG("Cannot download C2S blacklist file. Reason: ~p", + [Reason]) + end. + +%% Hook is run with: +%% ejabberd_hooks:run_fold(check_bl_c2s, false, [IP]), +%% Return: false: IP not blacklisted +%% true: IP is blacklisted +%% IPV4 IP tuple: +is_ip_in_c2s_blacklist(_Val, IP) when is_tuple(IP) -> + BinaryIP = list_to_binary(jlib:ip_to_list(IP)), + case ets:lookup(bl_c2s, BinaryIP) of + [] -> %% Not in blacklist + false; + [_] -> %% Blacklisted! + {stop, true} + end; +is_ip_in_c2s_blacklist(_Val, _IP) -> + false. + +%% TODO: +%% - For now, we do not kick user already logged on a given IP after +%% we update the blacklist.