21 marzo 2012

Construyendo un sistema firewall/antispam telefónico

 
¿Cuántas veces os ha sonado el teléfono fijo interrumpiendo la comida, despertándoos de la siesta, o incluso hecho salir del baño porque un sistema de telemárketing "avanzado" llama aleatoriamente tu número para ofrecerte un mejor ADSL, cobertura de noseque seguro, una tarjeta de crédito nueva, o vaya usted a saber?

Bueno pues a mí unas cuantas. Además, desde que tengo la oficina en mi propia casa, es un coñazo soberano la cantidad de molestas llamadas "spam" personas o bots. Antes, tenía un pool de actitudes a tomar cuando recibía estas llamadas, pero ahora, todo esto ha cambiado.

En el móvil, ya instalé una aplicación como la que comentamos tiempo atrás para evitar el Spam via SMS, y para casa, desde que monté una centralita con Asterisk con el ATA Linksys con el que simulaba hacer llamadas como si estuviera en mi casa/oficina, quien contesta las llamadas es el propio Asterisk. He de decir, que lo de las centralitas VoIP es todo un mundo y me ha sorprendido, muy gratamente, la cantidad de cosas que se puede hacer con ellas.

En el briconsejo de hoy, vamos a ver cómo se puede hacer para que sea la propia centralita quien filtre las llamadas, blacklisteando números de teléfono origen de los que no queremos oir hablar.

Dentro del propio interfaz con FreePBX, hay una sección Blacklist, donde se pueden ir añadiendo aquellos números que consideremos molestos.




Incluso, podemos habilitar el check para que bloquee directamente aquellas llamadas con número oculto (ojo si recibís llamadas internacionales, que a veces entran con CallerID oculto).

Por otra parte, y con fines más dinámicos, puede que quiera añadir un número a la blacklist, simplemente usando la línea de comandos que tanto me gusta, o delegarlo como un comando más a mi bot GTalk.

Así que me hice un script, en Perl, que interactúa con el módulo de gestión de la centralita, de manera que pueda pasarle el número de teléfono origen que quiero bloquear.


#!/usr/bin/perl
use Asterisk::AMI;

#Vars Asterisk
my $IP_asterisk="192.168.52.47";
my $peerport_asterisk="5038";
my $username_asterisk="admin";
my $secret_asterisk="esperasentadoqueteladigoeh";
#/Vars Asterisk


        my $astman = Asterisk::AMI->new(PeerAddr => $IP_asterisk,
                                        PeerPort => $peerport_asterisk,
                                        Username => $username_asterisk,
                                        Secret => $secret_asterisk
                                );

        die "Unable to connect to asterisk" unless ($astman);

        my $quehacer=$ARGV[0];
        my $phone=$ARGV[1];

        my $lecommand=undef;

        if ($phone)
        {#Hay un telefono leido
                if ($quehacer eq "block")
                {
                        $lecommand="database put blacklist $phone 1";
                }
                elsif ($quehacer eq "unblock")
                {
                        $lecommand="database del blacklist $phone";
                }
                else
                {
                        die "Usage: $0 <block || unblock> <phone>";
                }

                my $action = $astman->send_action ({ Action => 'Command',
                                                 Command => $lecommand
                                                 });

                my $response1 = $astman->get_response($action);

                print "$response1->{'CMD'}[0]\n";
                #printamos la respuesta
        }
        else {die "Usage: $0 <block || unblock> <phone>";}   


En mi caso, llamando con oculto, el Linksys SPA3102 (recordad que es el dispositivo que me reenvía la señal de línea analógica convertida en VoIP a mi Asterisk) lo que mi centralita ve es SPA, que es el alias que le configuré, por lo que tampoco vale la opción "block" que introducía FreePBX. Si intentas añadir manualmente una entrada identificada con letras, FreePBX comprueba mediante Javascript que sea un número y lo bloquea. Sin embargo la API de Asterisk sí que lo permite.

Hasta ahora, cada vez que me llamaban (e importunaban) apuntaba el número, lo googleaba el número de teléfono y lo guardaba en un fichero de texto. Casi todos hasta ahora han sido de una empresa contratada por Jazztel (pesados!) y Citibank. Investigando por listas de spam telefónico, hay incluso una especie de ranking con teléfonos de mala reputación, al estilo de las listas de reputación IP como las ofrecidas por Alienvault.

Me he hecho otra herramienta que parsea diariamente el listado de "Top spam" ofrecido por la web  http://www.listaspam.com que, diariamente parsea el Top 10 y, si son números de teléfono de España, los blacklistea directamente en mi Asterisk:


#!/usr/bin/perl
use strict;
use LWP::UserAgent;
use Asterisk::AMI;

#Vars Asterisk
my $IP_asterisk="192.168.52.47";
my $peerport_asterisk="5038";
my $username_asterisk="admin";
my $secret_asterisk="esperasentadoqueteladigoeh";
#/Vars Asterisk


my $astman = Asterisk::AMI->new(PeerAddr => $IP_asterisk,
                                PeerPort => $peerport_asterisk,
                                Username => $username_asterisk,
                                Secret => $secret_asterisk
                         );
        die "Unable to connect to asterisk" unless ($astman);



sub blacklistea
{
        my $lecommand="database put blacklist $_[0] 1";
        my $action = $astman->send_action ({ Action => 'Command',
                                         Command => $lecommand
                                                 });

        my $response1 = $astman->get_response($action);

        print "$response1->{'CMD'}[0]\n";
}

#MAIN

my $url="http://www.listaspam.com";

my $browser= LWP::UserAgent->new;
my $response = $browser->get($url);

if ($response->is_success)
{
        my $web=$response->content;

        my @cachos=split (/Top spam<\/p>/,$web);
        my @trozos=split (/\<\/a\>\\<\/ul\><\'item_top\'\>/,@cachos[1]); 
        my @mascachos= split (/Telefono=/,@trozos[0]); 
        @mascachos[0]=undef;
        foreach (@mascachos) 
        { 
              my @trocitos=split(/>/,$_); 
              if ($trocitos[0] =~ /^[6-9]\d{8}/)                 
              {
                  print "$trocitos[0]\n";               
                  blacklistea ($trocitos[0]);                 
              }
        }
 }

Si además queremos poner una grabación personalizada de bienvenida a este tipo de llamadas, podemos hacerlo modificando en el fichero /etc/asterisk/extensions_additional.conf en la sección siguiente

[app-blacklist-check]
include => app-blacklist-check-custom
exten => s,1,GotoIf($["${CALLERID(number)}" = "Unknown"]?check-blocked)
exten => s,n,GotoIf($["${CALLERID(number)}" = "Unavailable"]?check-blocked)
exten => s,n,GotoIf($["foo${CALLERID(number)}" = "foo"]?check-blocked:check)
exten => s,n(check-blocked),GotoIf($["${DB(blacklist/blocked)}" = "1"]?blacklisted)
exten => s,n(check),GotoIf($["${BLACKLIST()}"="1"]?blacklisted)
exten => s,n,Set(CALLED_BLACKLIST=1)
exten => s,n,Return()
exten => s,n(blacklisted),Answer
exten => s,n,Wait(1)
exten => s,n,Zapateller()
exten => s,n,Playback(ss-noservice)
exten => s,n,Hangup

; end of [app-blacklist-check]

En este bloque cambiar la línea  "exten => s,n,Playback(ss-noservice)" por "exten => s,n,Playback(ss-spam)"

Además deberemos tener en formato .sln en el directorio /var/lib/asterisk/sounds/ el fichero "ss-spam.sln".
Para ello, convertir el .wav mediante "sox" así:

sox ss-spam.wav -t raw -r 8000 -s -2 -c 1 ss-spam.sln

Os dejo el que he creado yo para cuando me llama algún pesado desde un número que está en la blacklist:


22 comments :

Sdfg dijo...

que grande XD

Gonza dijo...

excelente!!

Victor J Chamorro dijo...

jajaja, la grabación es genial!

Masticover dijo...

¡¡¡IM-PRE-ZIO-NAN-TE!!! XD

Joseluis dijo...

Hay un plugin que permite gestionar blacklists por paises, horarios, comunidades,.. http://www.humbuglabs.org/blog/2012/03/20/how-to-configure-the-new-call-blocking-asterisk-collector/

Ivan Ricondo Bonachea dijo...

Que bueno, igual lo repito, por que tengo el hard y lo tendría fácil :-D
otra idea, si alguien te llama y no está ni en la blacklist, ni en la whitelist, que salga locución diciendo que teclee un número aleatorio en su teléfono (ya sabes una especie de catchup). El tema sería decir pronto el número para que no le de tiempo a una de esas operadoras a oír la locución...

Lorenzo_Martinez dijo...

 No lo conocía! No he tenido tiempo para mirarlo en profundidad, pero, aprovecho para preguntarte: ¿la subscripción con las listas negras es de pago o es gratuita?

Lorenzo_Martinez dijo...

 Hombre... está bien la idea, pero si uno no se lo espera, o te llama alguien desde un manos libres mientras conduce, puede ser un pelín violento/peligroso lo de ponerse a teclear el número no?

Quizá algo más útil sería que le diese una descarga eléctrica en el teléfono al que te llama y se ha equivocado de número :DDD

Invitado dijo...

Dios que me meo eres un crack :D

Joseluis dijo...

 Por lo poco que he visto (salio practicamente ayer), no dice nada al respecto (esta en la lista de cosas pendientes), pero por la plataforma que hay detras (sms, alertas, informes personalizados,..) supongo que sera de pago; en su web aparecen los precios del servicio antifraude (estadisticas free), pero no he visto referencia directa a la aplicacion, unicamente que se integra con su sistema.

Gonzalo Asensio dijo...

XD.. no hay nada más que les joda que les hagas esperar (porque pierden tiempo de molestar a otro)

.. ahora lo mejor la música "...palomitas de maiz..." me ha recordado a las maquinillas que había en mi pueblo :P que grande!

Silverhack dijo...

Lorenzo titi.... Vaya coco e imaginación que tienes.... Me ha encantado esta entrada!! Y sí!! Admirando ese código tan limpio te confirmo desde YA, que repasando todos tus artículos me he autoconvencido y ya tengo "en cola" aprender algo de perl! Ya hablaremos para pedirte consejo oh gurú!!
Repito... Impresionante entrada...
Un abrazo titi!!

cannabislegalize dijo...

JAJAJAJAJAJAJA K BUENA LA GRABACION!! XD

cannabislegalize dijo...

 XDD sumamente importante...
no se pueden grabar las llamadas cuando hablan con el bot? seria gracioso xd

Lorenzo_Martinez dijo...

No sería la primera vez que me pongo a cantar la cancioncilla de Palomitas de Maíz cuando les digo "Un momento por favor" :DDDD Ahí ya empieza el cachondeo y, en general termina habiendo unas risas con quien llama, pero venderme, no me venden nada nuevo xD

Lorenzo_Martinez dijo...

Se pueden grabar todas las conversaciones si quieres con Asterisk, o sólo las que estén consideradas desde números blacklist :) Lo tendré en cuenta jejeje Gracias por la idea!

Lorenzo_Martinez dijo...

Me halaga esto viniendo de tí! :D La verdad es que los scripts son de lo más sencillitos.
Si te muestro yo la lista de cosas que tengo en "To Do",... se hacen pocos los 365 días del año :(
Un abrazo Juanillo!

Jesús Cea dijo...

Yo me pregunto cuándo pasa la mopa el Roomba, si curras en casa. Pobres vecinos :-)

tisasia dijo...

¡¡¡ fantastico como siempre !!!

Rotevi28 dijo...

Hola Lorenzo; Me gustaría montar un sistema de llamadas igual al que manejas en tu oficina con el asterisk y router pero no tengo ni idea por donde comenzar; Podrías suministrame información. Te estaré agradecido. 

Lorenzo_Martinez dijo...

Pues claro que sí! Envíame un correo contándome qué necesitas y te intento guiar :)

Agustin Campos dijo...

¡Llevaba tiempo esperando esta entrada!! Por cierto... ¿no sería mejor ponerle la cancioncilla del interné? http://www.youtube.com/watch?v=LybAHotsvOg
 
Sobretodo si llaman de Jazztel sería la bombá. xDxDxD La estoy poniendo mientras que escribo esto!!!