17 мая 2012 в 15:55

Защита Asterisk при атаке на номер 8-800

После прочтения этой статьи с ужасом для себя понял, что мы никак не защищены от такой атаки. И легко можем попасть на 10-20 тысяч рублей в день. Решил это дело исправить. Накидал на коленке защитный скриптик — возможно кому-то пригодится…

Подготовка системы
Скрипт написан на php и использует sqlite3 для хранения информации по этому нужно установить php-cli и php5-sqlite3
в моем случае система поднята на убунте, по этому ставится так

sudo apt-get install php5-cli php5-sqlite


Непосредственно сам скрипт.
Принцип работы такой. Скрипту передается номер телефона звонящего. Он заносит номер в базу, проверяет — сколько раз он уже звонил и сверяет это с правилами (они задаются в первой строчка скрипта). Если лимиты превышены — возвращает слово 'stop', в противном случае позвращает 'continue'

<?php
$rules = array( 
                60 => 2, // Не более 2 звонков в минуту ( 60 секунд )
                3600 => 10 // Не более 10 звонков в час ( 3600 секунд )
);

if (!$argv[1] ) die("please use: '" . $argv[0] . " phone_number' \nfor example: ".$argv[0]." 88121234567\n");

// Открываем или создаем БД
$db = new SQLite3('/tmp/sqlite.db');
$db->exec('CREATE TABLE IF NOT EXISTS logs (phone bigint(12), datetime int(12))');

// Добавляем номер и дату звонка в базу
$phone = preg_replace('/[^0-9]/','', $argv[1]);
$db->exec("INSERT INTO logs (phone, datetime) VALUES ( '".$phone."','".time()."' )");

foreach( $rules as $secs => $limit ) {
    $res = $db->query( "SELECT count(*) as `c` FROM logs WHERE `phone` = '".$phone."' AND `datetime` >= " .( time() - $secs ) );
    $row = $res->fetchArray();
    // Если привышен лимит
    if ( $row['c'] > $limit ) {
        die('stop');   // возвращаем stop и выходим из скрипта
    }
}

// Очистка мусора - удаляем старые данные, чтобы не раздувать базу
$max_period = max(array_keys($rules) );
$db->exec("DELETE FROM logs WHERE `datetime` < " .( time() - $max_period ));

// возвращаем continue
die('continue');

?>


Подключение к Asterisk
Важно выполнять скрипт в первых строках — до вызова команды Answer() или любой другой команды, которая открывает «снимает» линию.

exten => 8800XXXXXXX,1,Set(resp=${SHELL(php /home/scripts/antiddos.php ${CALLERID(num)})});
exten => 8800XXXXXXX,2,Gosubif($[${resp}==stop]?${EXTEN},${MATH(${PRIORITY}+1),int}:${EXTEN},${MATH(${PRIORITY}+2),int});
exten => 8800XXXXXXX,3,HangUp();
exten => 8800XXXXXXX,4,Answer();
...


Разберем диалплан по строчкам:
1) Set(resp=${SHELL(php /home/scripts/antiddos.php ${CALLERID(num)})});
вызываем скрипт и присваиваем переменной resp значение, которое скрипт вывел в консоль
2) Gosubif($[${resp}==stop]?${EXTEN},${MATH(${PRIORITY}+1),int}:${EXTEN},${MATH(${PRIORITY}+2),int});
если значение равно 'stop', то переходим на следующую инструкцию текущего диалплана, где нас ожидает компанда HangUp()
в противном случае переходим через строчку, и выполняем дальше диалплан.

Что в итоге происходит.
Если лимит не превышен — получаем такую SIP сессию:
sip provider        me
        invite =>
               <=   trying
               <=   OK
         ack   =>

Значит всё ок, тарификация началась

Если мы делаем HandUp(), то SIP сессия такая:
sip provider        me
        invite =>
               <=   trying
               <=   DECLINE
         ack   =>


Decline означает, что вызываемый пользователь отклонил входящий вызов. Тарификация не должна начинаться, т.к. разговора небыло и сессия прекратилась.

UPD:
При атаке с анонимных номеров можно немного доработать скрипт и установить лимит на номера, закрытые антиАОНом…
Автор: @5hr4M
Ангелы АйТи
рейтинг 30,68
Компания прекратила активность на сайте

Комментарии (36)

  • +9
    Плюсую. На Хабре нужно больше постов про IP телефонию. По статье, скрипт вроде рухнет, если от провайдера не прийдет АОН.
    • +1
      а как же будет тарифицироваться, если номер скрыт? там же тариф зависит от номера звонящего…
      • 0
        Оператор, предоставляющий номер 8800, закроет звонок своим групповым аоном и тарификация все равно будет. Так что при атаке с аноним-номерами это решение неэффективно
        • +1
          можно немного доработать… например не пропускать анонимов или установить на них лимит…
          • 0
            Еще раз повторюсь — у Вас не будет анонимов, оператор подставим Вам свой АОН.
            • 0
              и при каждом звонке он будет новый?? думаю нет. а если нет, то правило сработает по этому номеру…
            • 0
              Сильно зависит от оператора. Скорее придет INVITE вида Anonymous@your-pbx-ip, а не заглушка операторская.
    • +3
      А какие вас статьи по IP телефонии интересуют? Написать то можно. Просто как-то не задумывался, что оно нужно :)
      • +6
        Интересуют отказоустойчивые кластера на астериске, альтернативы астериску, другие проекты с открытым кодом: freeswitch, yate, kamailio. Обзоры различных SOHO IP АТС с астериском внутри, ну и конечно же различные success story в сфере VOIP. Мониторинг качества голоса. Борьба с фродом особенно всевозможные способы обнаружения взлома IP АТС по аномальной активности.
  • +2
    Если бы я начал «просаживать» 8 800, то я бы постарался менять номер каждый раз при новом звонке. Тупо +1 делаем и все.
    • +2
      Это ж откуда взять такую номерную ёмкость?
      • +6
        Легко. Есть «серые» операторы, которые пропускают любой АОН, который Вы им передаете. И отследить таких крайне сложно, но возможно. Как правило, на этой уходит день-два, но источник атаки ищется уже на межоператорском уровне.
        • 0
          да… тогда всё сложно :( значит мой скрип поможет только от школоты :(
          • +4
            Об этом мы в своей статье и говорили — требуется комплекс мер, и основную работу должен делать оператор связи — у него для этого больше ресурсов и возможностей.
            Особенно важно, что люди начали задумываться о том, как работает их телекоммуникационная составляющая бизнеса. Это был основной посыл в статье.
            • +1
              да, мне понравилась ваша статья… я не претендую на коммерческое решение — действительно это привелегия операторов — пусть сами борются… но нахожу свой скрипт полезным хотябы от телефонных хулиганов, звонящих, слушающих приветствие и бросающих трубку…
              • +4
                Операторы не сильно заинтересованы в такой борьбе, они тут за каждый звонок с клиента денег получают.
        • 0
          По закону права не имеют — можно легко обращаться в органы за помощью в таком случае
          • 0
            А как Вы выясните — их это номерная емкость или нет? И в какие именно органы Вы планируете обращаться?
  • 0
    А что если Анти-АОН?
  • 0
    В предыдущей статье речь шла о контроле (незаметного для call-центра) увеличения трафика.
    В ваш скрипт хорошо бы добавить отсылку сообщения превышении числа звонков за час/день. Особенно, звонков, не превышающих порог приветствия.
    • +4
      Скрипт написан за 10 минут для себя… выложил для публики, чтобы модифицировали под свои цели…
      отсылку почты организовать не сложно :)
      • +2
        Скрипт достаточно простой, тем он и хорош. Есть только пара моментов: я бы не стал каждый раз проверять есть ли база или нет. И я бы увел скрипт в выполнение через AGI, там и поболее проверок можно сделать если что, и принять меры по звонку на уровне канала.

        Отправку почты точно не стоит встраивать в скрипт, лучше это делать внешними средствами.
        • 0
          не очень силён в AGI, но неплохо знаю php, по этому сделал именно так…
          на счет почты согласен… скрипт можем кидать в пул для отправки и завершаться или вообще сторонний скрипт по крону подключаться к базе и анализировать её…
          • +2
            Советую посмотреть на phpagi, там и с документацией все в порядке, думаю проблем не возникнет.
            • 0
              Спасибо! Познавательно! Изучу :)
  • +1
    Эх, были времена когда я писал для IP телефонии. Писал сервер для VoIP на платах Ольха (не сочтите за рекламу, но дейстительно хорошие решения). Так вот, когда я работаю с PRI на примую, то в качестве адреса звонящего в D-канал можно передавать любой номер. И будет ваш скрипт получать номера ааааа1, ааааа2, ..., ааааб1… ну вы поняли ))
    • +2
      Слушаейте, но E.164 никто вроде не отменял. Хочешь защищаться — не пытайся всем понравится, не пропускай))
  • 0
    А скрипт не начнёт банить крупные компании, у которых исходящий номер для всех сотрудников — один и тот же?
    • 0
      а с чего это вся фирма начнет звонить на конкретный 8-800?
      • 0
        сорри, я почему-то сразу подумал об универсальной защите телефона от ддоса. Ну, например, можно же легко обвалить корпоративный входящий телефон, а это тоже потери.
        Ну вот. А 8-800, да, Вы правы, такой проблемы скорее не имеем.
  • +1
    Нужна единая база телефоно-спамеров…
    В которую будут пополнять и операторы в том числе…
    • 0
      да можно сделать такой стартап… делов-то на 5 минут…
      • 0
        Также можно было бы добавить базу IP адресов брутафорсеров
  • 0
    Если б ещё все операторы следили за а-номером, который пропускают.
    За обработку номера на входе респект. Хоть тут не поломают :)
  • 0
    Есть много операторов, которые позволяют подставлять при звонке произвольный аон.
    Такой метод защиты не сработает.

    Для обслуживания имеющейся юзербазы поможет белый список, а вот для приёма звонков от потенциальных клиентов, увы, общего подхода нет.

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка