Делаем Callback с сайта с помощью Askozia PBX

Популярность сервисов callbackhunter и zingaya посеяла в мою голову идею, реализовать возможность обратного звонка с нашего сайта, используя уже работающую много лет в компании IP ATC Askozia. Ранее я писал про нее в отдельном посте.
88e45540ec0a437386aa263d303fc048.png
Ситуация также усложнялась тем, что сайт расположен в публичной сети, а Askozia внутри локальной, и публиковать ее в открытый доступ было страшновато.
Алгоритмов реализации механизма обратного звонка с сайта для Asterisk написано достаточно много. Самый распространенный — это генерация AMI команды Originate после того, как клиент введет свой номер телефона на сайте. И так приступим.

Настройка на стороне Askozia


В последней версии Askozia наконец появился механизм активной защиты от атак на SIP телефонные системы в виде широко известной в Linux кругах пары iptables_fail2ban. А это в связке с тем, что Askozia имеет read-only linux ядро, сильно повышает защиту от взлома даже относительно такого распространенного дистрибутива как FreePBX. Хотя конечно вы можете со мной поспорить :)

Итак, исходные данные:
Сайт www.telefon1c.ru имеет ip адрес 93.188.40.98
Askozia развернута в виде виртуальной машины с публичным адресом 93.188.40.99

Настойка файрвола и fail2ban
Первым делом активируем firewall и разрешаем доступ к системе из своей локальной сети, указывая ее подсеть. В данном случае настройка 172.16.32.0/24 означает все адреса в диапазоне 172.16.32.0 ~ 172.16.32.255

ee2c82f5b96d4430bb53c60c219640ee.png

При настройке firewall я выбрал вариант установки Askozia в облаке и получил такие параметры блокировки по умолчанию

0a91c82f05784104bbad90d223713bf1.png

На всякий случай указал свой домашний IP адрес для доступа к web интерфейсу Askozia в случае неправильных настроек firewall, иначе можно больше не попасть в админку :)

Далее активируем fail2ban для блокировки подбора паролей. Это делается одной галочкой, остальные все настройки оставим по умолчанию.
7b1eeb78a7a749b4a4d151b19bc62828.png

Добавим кастомное правило для iptables, чтобы сайт мог достучаться до AMI интерфейса сквозь Firewall.
Для этого в секции расширенные, добавим такую строчку:
iptables -A INPUT -p tcp -s 93.188.40.98 --dport 5038 -j ACCEPT

Должно получиться как на картинке:
38a4f6a821564c0caab797145dd06512.png

На этом настройку firewall можно завершить, сохранить изменения и перейти к настройке AMI интерфейса.
Создадим нового пользователя webcall с минимальными правами и разрешим ему доступ только с одного IP адреса, нашего сайта.

709b1139f13a48a9a9142bb76d91c674.png
Дадим ему сложный-сложный пароль: 9[U.[2o{9$? H$$su

Теперь нам нужно понять, куда мы будем направлять звонок с Web сайта. Я решил не придумывать ничего хитрого и отправить его по тому же маршруту, по которому нам звонят клиенты в HOTLINE. Это очередь вызовов с внутренним номером 93

48b7080435fc423d920fa50f94c15d8a.png

Ну и последнее что нам понадобится, это получить контекст провайдера, через которого будем осуществлять звонок клиенту. Для этого открываем карточку редактирования настроек провайдера и копируем из адресной строки его контекст.

91a338bc722349fc8db1ad132c58232b.png

Теперь у нас есть всё необходимое для настройки обратного звонка со стороны сайта:

  • IP Адрес Askozia: 93.188.40.99
  • Логин AMI пользователя: webcall
  • Пароль AMI пользователя: 9[U.[2o{9$? H$$su
  • Контекст провайдера: SIP-PROVIDER-1646711234f40d80266c2f
  • Внутренний номер маршрута вызова: 93

Настройка скриптов на стороне сайта
Для начала нам нужно нарисовать простую форму ввода номера телефона на сайте.

aee23db30f644975bc097b253d053b6d.png

Код формы с сайта на Битриксе call.php
SetTitle("Звонок в компанию МИКО");
?>  

//Подключаем обработчик вызовов через Askozia IncludeFile("/ajax/ajax_call_handler_inc.php", Array(), Array( "MODE" => "html", "NAME" => "Редактирование включаемой области раздела" )); ?> //Рисуем форму для указания номера клиента для обратного звонка

Бесплатный звонок

Мгновенный callback

Если вы находитесь в России, то можете заказать обратный звонок на свой телефон.
Перезвонить
//Наводим красоту при вводе номера, рисуем красивую маску //Подключаем битриксовский футер страницы


Код php обработчика для генерации AMI команды /ajax/ajax_call_handler_inc.php
";

        $length = strlen($strwebnum);

        if ($length == 11 && is_numeric($strwebnum))
        {

                $oSocket = fsockopen($strHost, 5038, $errnum, $errdesc,30) or die("Connection to host failed");
                stream_set_timeout($oSocket, 0, 500000);

                fputs($oSocket, "Action: login\r\n");
                fputs($oSocket, "Events: off\r\n");
                fputs($oSocket, "Username: $strUser\r\n");
                fputs($oSocket, "Secret: $strSecret\r\n\r\n");

                while ($line = fgets($oSocket))
                        $result .= $line;

                fputs($oSocket, "Action: originate\r\n");
                fputs($oSocket, "Channel: $strChannel\r\n");
                fputs($oSocket, "WaitTime: $strWaitTime\r\n");
                fputs($oSocket, "CallerId: $strCallerId\r\n");
                fputs($oSocket, "Exten: $strExten\r\n");
                fputs($oSocket, "Context: $strContext\r\n");
                fputs($oSocket, "Priority: $strPriority\r\n\r\n");

                while ($line = fgets($oSocket))
                        $result .= $line;

                fputs($oSocket, "Action: Logoff\r\n\r\n");

                while ($line = fgets($oSocket))
                        $result .= $line;

                fclose($oSocket);

                echo '
Производится вызов на номер '.htmlentities($_REQUEST["txtphonenumber"], ENT_QUOTES, "UTF-8").'. Подождите пока Ваш телефон зазвонит! Если телефон не позвонил в течении минуты, попробуйте ещё раз.
'; } else { echo '
Не верно указан номер телефона. Номер должен состоять из 11 цифр, например +7 (495) 229-30-42
'; unset($_SESSION['call_send']); } } ?>

Что получилось в итоге:

© Habrahabr.ru