Table des matières

Introduction

Plan d'action

  1. Je ne veux pas dependre d'Internet ie si les sites ne repondent plus ⇒ l'appel doit pouvoir etre traité
  2. Je ne desire ne pas solliciter en permance l'Internet ⇒ Generation de caches

Appels masqués

Appels Spam / blacklist

Carnets d'addresse

Pendant un appel accepté

Repondeurs

Techniquement...

FIXME Absolument rien de la partie Repondeur n'est traité

FIXME Lorsqu'un numero est dans l'annuaire interne, on lance quand meme les procedure AntiSpam, et c'est mal (mais bien pour mes tests)

FIXME Actuellement rien n'est fait sur la partie reverse annuaire sur l'internet

FIXME Actuellement rien n'est fait sur la qualification de l'appel en cours

Dialplan

appel entrant

exten => _X.,1,NoOp(Entrant ${EXTEN} CallerId ${CALLERID(all)})
exten => _X.,n,AGI(jabber_notif,"Debut ${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}" "${EXTEN}" "${CALLERID(all)}")
exten => _X.,n,macro(loadvcard,${CALLERID(num)})
exten => _X.,n,macro(spamcheck, ${CALLERID(num)}, 1)
...Traitement de l'appel Normalement (repondeur, ou pas...)
FIXME documenter l'AGI jabber_notif, et meme la faire evoluer pour son parametrage

Macro: loadvcard

Il y-aura ici autant d'appel a des chargement d'annuaire que necessaire, c'est pourquoi il n'y a qu'une ligne, aujourd'hui

[macro-loadvcard]
exten => s,1,Noop(Debut de la macro-loadvcard, tel a identifier ${ARG1})
exten => s,n,AGI(VCardReader4Asterisk,"CALLERID(name)",${ARG1},"VCRRET","/usr/local/etc/VCardReader4Asterisk.conf")

exten =>s,n,MacroExit

Macro: spamcheck

[macro-spamcheck]
exten => s,1,Noop(Determinig to be a spam or not)
exten => s,n,GotoIf($["${CALLERID(num)}" = ""]?NOCID,1:)
exten => s,n,AGI(localbwlist,${CALLERID(num)},"LOCALWHITELISTRC","/usr/local/etc/asterisk_whitelist.txt")
exten => s,n,GotoIf($["${LOCALWHITELISTRC}" = "0"]?NOSPAM,1:)
exten => s,n,AGI(localbwlist,${CALLERID(num)},"LOCALBLACKLISTRC","/usr/local/etc/asterisk_blacklist.txt","LOCALBLACKLISTEX")
exten => s,n,Set(SPAMDISCOVER="localblacklist")
exten => s,n,Set(SPAMSCODE=${LOCALBLACKLISTEX})
exten => s,n,GotoIf($["${LOCALBLACKLISTRC}" = "0"]?SPAM,1:)
exten => s,n,AGI(phonespamfilter.php)
exten => s,n,Set(SPAMDISCOVER="phonespamfilter.php")
exten => s,n,Set(SPAMSCODE=${PHONESPAMFILTER})
exten => s,n,GotoIf($["${PHONESPAMFILTER}" = "2"]?SPAM,1:)
exten => s,n,AGI(fr.spampages.info,${CALLERID(num)},"SPAMPAGEINFORC","SPALPAGEINFOEX")
exten => s,n,Set(SPAMDISCOVER="fr.spampages.info")
exten => s,n,Set(SPAMSCODE=${SPAMPAGEINFORC})
exten => s,n,GotoIf($["${SPAMPAGEINFORC}" = "0"]?SPAM,1:)
exten => s,n,MacroExit
exten => NOSPAM,1,MacroExit

; For SPAM calls
exten => SPAM,1,Noop(You are a spammer)
exten => SPAM,n,AGI(add2localbwlist,${CALLERID(num)},${SPAMDISCOVER},${SPAMSCODE},"localblacklist","/usr/local/etc/asterisk_blacklist.txt")
exten => SPAM,n,AGI(jabber_notif,"${CALLERID(num)} is a spammer because : ${SPAMDISCOVER} (${SPAMSCODE})")                                                              exten => SPAM,n,Answer()
exten => SPAM,n,Wait(1)
exten => SPAM,n,Hangup()
exten => SPAM,n,MacroExit

; For NOCID calls
exten => NOCID,1,Noop(No callerid)
exten => NOCID,n,Answer(1)
exten => NOCID,n,Wait(1)
exten => NOCID,n,Hangup()
exten => NOCID,n,MacroExit

AGI

VCardReader4Asterisk

exten => s,n,AGI(VCardReader4Asterisk,"CALLERID(name)",${ARG1},"VCRRET","/usr/local/etc/VCardReader4Asterisk.conf")

Information complementaire:

Parametres:

  1. Variable ou sera stoke le nom s'il est trouve
    • Defaut : CALLERID(name)
  2. Le numero de l'appelant
  3. Variable ou est stocke le code retour pour post traitement
    • Depend du fichier de configuration
  4. Fichier de configuration
    • Defaut : /usr/local/etc/VCardReader4Asterisk.conf

Fichier de configuration:

[returns]
code_anonymous=0
code_unknown=1
code_wellknown=2
str_anonymous="Appel Masque"
#str_unknown="Inconnu"
#str_wellknown="Connu"

[vcardaccess]
cachettl=0.5
#0.028 == 10min
cachefile=/var/lib/asterisk/VCardReader4Asterisk.cache
vcardreq="/usr/bin/wget --quiet --timeout=2 --auth-no-challenge --no-clobber --http-user=LOGIN --http-password=PASSWORD --no-check-certificate -O - https://example.lan/owncloud/index.php/apps/contacts/addressbook/local/4/export"

#!/usr/bin/perl
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
 
use strict;
use warnings;
use Asterisk::AGI;
use Text::vCard::Addressbook;
use Text::vCard::Node;
use Text::vCard;
use Storable;
use Data::Dumper;
use Config::Simple;
 
my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
 
my $wh2answh=$ARGV[0] || "CALLERID(name)";
my $callerid=$ARGV[1] || "";
my $returnco=$ARGV[2];
my $conffile=$ARGV[3] || "/usr/local/etc/VCardReader4Asterisk.conf";
my %cfg;
 
my $config = new Config::Simple();
if(-s $conffile) {
    $config->read($conffile);
    %cfg = $config->vars();
    }
 
my $callername;
my $returncode;
 
if(defined($cfg{'vcardaccess.vcardreq'}) or defined($cfg{'vcardaccess.cachefile'})) {
    #Ya un peu de conf, on accepte d'aller plus loin :)
    if(!defined($cfg{'vcardaccess.cachettl'}))      { $cfg{'vcardaccess.cachettl'}=0.028; }
 
    if(!defined($cfg{'returns.code_anonymous'}))    { $cfg{'returns.code_anonymous'}=10; }
    if(!defined($cfg{'returns.code_unknown'}))      { $cfg{'returns.code_unknown'}=20; }
    if(!defined($cfg{'returns.code_wellknown'}))    { $cfg{'returns.code_wellknown'}=30; }
    if(!defined($cfg{'returns.str_anonymous'}))     { $cfg{'returns.str_anonymous'}="Anonymous"; }
 
    if   ($callerid eq "")      {
        $callername=$cfg{'returns.str_anonymous'};
        $returncode=$cfg{'returns.code_anonymous'};
        }
    elsif(!defined($callername=FromVcard($callerid))) {
        if(defined($cfg{'returns.str_unknown'})) { $callername=$cfg{'returns.str_unknown'}; }
        $returncode=$cfg{'returns.code_unknown'};
        }
    else {
        $returncode=$cfg{'returns.code_wellknown'};
        }
    }
else { $returncode=10; }
 
$AGI->set_variable("$wh2answh", "$callername");
if(defined($returnco)) { $AGI->set_variable("$returnco", $returncode); }
 
exit($returncode);
 
sub FromVcard {
    my ($callerid)=@_;
 
    if(CacheIsOld($cfg{'vcardaccess.cachefile'},$cfg{'vcardaccess.cachettl'}))  {
        LoadNewCache($cfg{'vcardaccess.cachefile'},$cfg{'vcardaccess.vcardreq'})
        }
 
    $callername=FindNumInCache($cfg{'vcardaccess.cachefile'},$callerid);
 
    return($callername);
    }
 
sub FindNumInCache {
    my ($CacheFile,$callerid)=@_;
 
    my %CacheData = %{retrieve($cfg{'vcardaccess.cachefile'})};
 
    return($CacheData{$callerid});
    }
 
sub CacheIsOld {
    my ($CacheFile,$CacheTTL)=@_;
    my $ret=0;
    if((! -s $CacheFile) or (-M $CacheFile > $CacheTTL )) {
        $ret=1;
        }
    return($ret);
    }
 
sub LoadNewCache {
    my ($CacheFile,$VCardReq)=@_;
 
    my $card_text="";
    my %CacheData;
 
    open(WWW,"$VCardReq |");
    while(<WWW>) { $card_text.=$_; }
    close(WWW);
 
    # Create Addressbook
    my $address_book = Text::vCard::Addressbook->new({ 'source_text' => $card_text, });
    my $count=0;
 
    #Loop through Addressbook
    foreach my $vcard ($address_book->vcards()) {
        my $tels = $vcard->get({ 'node_type' => 'tel' });
        if(defined($tels)) {
            my %tabgr;
            my $xabs = $vcard->get({ 'node_type' => 'X-ABLABEL' });
            if(defined($xabs)) { # Load all the X-ABLABEL in a table to get them faster
                my $xab;
                foreach $xab (@{$xabs}) { $tabgr{$xab->group}=$xab->value; }
                }
 
            my $tel;
            foreach $tel (@{$tels}) { # Boucle sur chaques numeros
                my $com;
                my $name;
                my @nm=$tel->types;
                if    (defined($nm[0]))         { $com=$nm[0]; }
                elsif (defined($tel->group))    { $com=$tabgr{$tel->group}; }
                else                            { $com="Other"; }
                my $telnumber=$tel->value();
                $telnumber=~s/\+33/0/g;
                $telnumber=~s/#31#//g;
                $telnumber=~s/[^0-9\+]//g;
                if(!defined($vcard->fullname()))    { $name="<$telnumber>"; }
                else                                { $name=$vcard->fullname();}
                $CacheData{$telnumber}= $name."($com)";
                $count++;
                }
            }
        }
    if($count) { store(\%CacheData,$CacheFile); } #On ne stocj pas si on a rien lu
    }

localbwlist

exten => s,n,AGI(localbwlist,${CALLERID(num)},"LOCALBLACKLISTRC","/usr/local/etc/asterisk_blacklist.txt","LOCALBLACKLISTEX")
#!/usr/bin/perl
 
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
 
use Asterisk::AGI;
use strict;
use warnings;
 
my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
 
my $returncode=10;
my $returnstr;
 
if(!defined($ARGV[0]))                      { $returncode=2; $returnstr="No number given"; }
elsif(!defined($ARGV[1]))                   { $returncode=3; $returnstr="No comment"; }
elsif(!defined($ARGV[2]) or (!-e $ARGV[2])) { $returncode=4; $returnstr="No X-list File"; }
 
if($returncode == 10) {
    open(BWLF,"< $ARGV[2]")  or  $returncode=5;
    if($returncode != 5) {
        $returnstr="Not in the file";
        $returncode=6;
        while(<BWLF>) {
            if(/^$ARGV[0];/ or /^$ARGV[0]$/) {
                chomp();
                $returncode=0;
                $returnstr=$_;
                ### Ici il faudrait trouver l'instruction pour sortir de la boucle en express
                }
            }
        close(BWLF);
        }
    else { $returnstr="Pb access X-list File"; }
    }
 
if(defined($ARGV[1])) { $AGI->set_variable("$ARGV[1]", $returncode); }
if(defined($ARGV[3])) { $AGI->set_variable("$ARGV[3]", $returnstr); }
 
exit($returncode);

add2localbwlist

exten => SPAM,n,AGI(add2localbwlist,${CALLERID(num)},${SPAMDISCOVER},${SPAMSCODE},"localblacklist","/usr/local/etc/asterisk_blacklist.txt")
#!/usr/bin/perl
 
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
 
use Asterisk::AGI;
use POSIX;
use strict;
use warnings;
 
my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
 
# 0 Call number
# 1 Who want to add
# 2 With spam score
# 3 in which list (to avoid doublon...) but a fake...
# 4 in which file
 
 
if(defined($ARGV[1]) and defined($ARGV[2])) {
    if($ARGV[1] ne $ARGV[3]) {
        if(defined($ARGV[0]) and defined($ARGV[3]) and defined($ARGV[4])) {
            open(BWF,">>$ARGV[4]") or die;
            my $nwl=$ARGV[0].";".$ARGV[1]."(".$ARGV[2].");".strftime("%F %T", localtime $^T);
            print BWF $nwl."\n";
            close(BWF);
            }
        }
    }

phonespamfilter.php

Je vous invite aller voire l'AGI proposé sur le site : FIXME

Je la reecrirais un jour, de tel facon a ce qu'elle accpete plus de parametre, dont le callerid

fr.spampages.info

Je trouve ma facon de travailler pas tres correcte, desole pour eux… :/

Il faudra tout de meme qu'un jour je prenne la peine de les contacter…

exten => s,n,AGI(fr.spampages.info,${CALLERID(num)},"SPAMPAGEINFORC","SPALPAGEINFOEX")
#!/usr/bin/perl
 
# License
#   GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt)
# Authors
#   DELAPORTE Antoine
 
use Asterisk::AGI;
use strict;
use warnings;
use LWP;
 
my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
my $browser = LWP::UserAgent->new;
$browser->timeout(2);
 
 
my $response = $browser->get("http://fr.spampages.info/".$ARGV[0]);
my $returncode;
my $retstr;
 
 
$_=$response->status_line;
if((!defined($ARGV[0])) or ($ARGV[0] eq "")) {
    $returncode=4; $retstr="Bad argument";
    }
elsif(/^500 /)    { $returncode=2; $retstr="Service Unavailable"; }
elsif(/^200 /)    { $returncode=0; $retstr="Number declared"; }
elsif(/^404 /)    { $returncode=1; $retstr="Number not declared"; }
else              { $returncode=3; $retstr="Script Lost"; }
 
if(defined($ARGV[1])) { $AGI->set_variable("$ARGV[1]", $returncode); }
if(defined($ARGV[2])) { $AGI->set_variable("$ARGV[2]", $retstr); }
 
 
exit($returncode);

Remerciments