Делаем Callback с сайта с помощью Askozia PBX
Популярность сервисов callbackhunter и zingaya посеяла в мою голову идею, реализовать возможность обратного звонка с нашего сайта, используя уже работающую много лет в компании IP ATC Askozia. Ранее я писал про нее в отдельном посте.
Ситуация также усложнялась тем, что сайт расположен в публичной сети, а 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
При настройке firewall я выбрал вариант установки Askozia в облаке и получил такие параметры блокировки по умолчанию
На всякий случай указал свой домашний IP адрес для доступа к web интерфейсу Askozia в случае неправильных настроек firewall, иначе можно больше не попасть в админку :)
Далее активируем fail2ban для блокировки подбора паролей. Это делается одной галочкой, остальные все настройки оставим по умолчанию.
Добавим кастомное правило для iptables, чтобы сайт мог достучаться до AMI интерфейса сквозь Firewall.
Для этого в секции расширенные, добавим такую строчку:
iptables -A INPUT -p tcp -s 93.188.40.98 --dport 5038 -j ACCEPT
Должно получиться как на картинке:
На этом настройку firewall можно завершить, сохранить изменения и перейти к настройке AMI интерфейса.
Создадим нового пользователя webcall с минимальными правами и разрешим ему доступ только с одного IP адреса, нашего сайта.
Дадим ему сложный-сложный пароль: 9[U.[2o{9$? H$$su
Теперь нам нужно понять, куда мы будем направлять звонок с Web сайта. Я решил не придумывать ничего хитрого и отправить его по тому же маршруту, по которому нам звонят клиенты в HOTLINE. Это очередь вызовов с внутренним номером 93
Ну и последнее что нам понадобится, это получить контекст провайдера, через которого будем осуществлять звонок клиенту. Для этого открываем карточку редактирования настроек провайдера и копируем из адресной строки его контекст.
Теперь у нас есть всё необходимое для настройки обратного звонка со стороны сайта:
- IP Адрес Askozia: 93.188.40.99
- Логин AMI пользователя: webcall
- Пароль AMI пользователя: 9[U.[2o{9$? H$$su
- Контекст провайдера: SIP-PROVIDER-1646711234f40d80266c2f
- Внутренний номер маршрута вызова: 93
Настройка скриптов на стороне сайта
Для начала нам нужно нарисовать простую форму ввода номера телефона на сайте.
//Подключаем битриксовский хидер страницы
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Звонок в компанию МИКО");
?>
//Подключаем обработчик вызовов через Askozia
// текст
$APPLICATION->IncludeFile("/ajax/ajax_call_handler_inc.php", Array(), Array(
"MODE" => "html",
"NAME" => "Редактирование включаемой области раздела"
));
?>
//Рисуем форму для указания номера клиента для обратного звонка
Бесплатный звонок
Мгновенный callback
Если вы находитесь в России, то можете заказать обратный звонок на свой телефон.
//Наводим красоту при вводе номера, рисуем красивую маску
//Подключаем битриксовский футер страницы
";
$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 '
';
}
else
{
echo ' ';
unset($_SESSION['call_send']);
}
}
?>
Что получилось в итоге: