![](https://habrastorage.org/webt/ln/ou/2y/lnou2yoot3ov5unuov2q-ksl8_o.jpeg)
В начале этого лета в России произошли изменения в тарифах на рассылку SMS-сообщений. Правила игры изменились, цены выросли на порядок. Кто бы мог подумать, что такое может произойти с технологией, которая уже более 20 лет существует в нашей обыденной жизни. По моему мнению, «большая тройка» решила, что отправка SMS стала использоваться только в корпоративных целях (физики давно мигрировали в различные интернет-мессенджеры), следовательно, на ней можно хорошенько заработать, не боясь потерять пользовательскую симпатию. В статье представлен вариант отказа от подобных сервисов в сторону Asterisk на примере Hotspot, когда на указанный номер телефона поступает звонок и диктор сообщает пароль доступа. Тарифы отличные, расходы минимальные, работаем дальше.
▍ Введение
21 июля в курируемом мной проекте перестала работать рассылка SMS-сообщений, содержащих пароль для доступа к общедоступному Wi-Fi, организованному в интересах международной компании Coffee Cup, имеющей как собственные бары формата «кофе с собой» в разных городах, так и дилеров по всей России и в странах СНГ. Все технические подробности о том, как это было изначально сделано, можно посмотреть здесь. Для рассылки самих сообщений в силу лёгкости решения, гибкости и удобства администрирования были задействованы сторонние ресурсы, счета на которых в июле стремительно обнулились. Что, собственно говоря, произошло, стало понятно после общения с технической поддержкой:
Переписка
Я: у меня перестали отправляться смс. С ошибкой «незарегистрированный sender id».
Поддержка №1: На XXX и XXX отправка возможна только от платных имён с абонентской платой 2 000 руб./мес за каждого оператора. Если нужна временная отправка от общего имени на данных операторов в ближайшее время, есть тариф около 16 руб. за SMS на XXX и 20,30 руб. на XXX.
Или вот такой:
Я: Ищу простой способ отправки SMS, без лишних заморочек. Подойдёт любой исходящий номер.
Поддержка №2: Без регистрации и абонентской платы можно отправлять сообщения от общих имён операторов, но по повышенному тарифу (XXX: 18 руб. за SMS, XXX: 20,30 руб. за SMS). К сожалению, такая заградительная цена — ограничение, наложенное операторами.
Поддержка №1: На XXX и XXX отправка возможна только от платных имён с абонентской платой 2 000 руб./мес за каждого оператора. Если нужна временная отправка от общего имени на данных операторов в ближайшее время, есть тариф около 16 руб. за SMS на XXX и 20,30 руб. на XXX.
Или вот такой:
Я: Ищу простой способ отправки SMS, без лишних заморочек. Подойдёт любой исходящий номер.
Поддержка №2: Без регистрации и абонентской платы можно отправлять сообщения от общих имён операторов, но по повышенному тарифу (XXX: 18 руб. за SMS, XXX: 20,30 руб. за SMS). К сожалению, такая заградительная цена — ограничение, наложенное операторами.
Действительно, если поискать информацию на сайтах операторов сотовой связи, то можно увидеть примерно то же самое:
![](https://habrastorage.org/webt/xf/lz/fa/xflzfawy83ethfhjvzyyh9iu2og.png)
▍ Технические варианты уведомления пользователей
Называть такие тарифы заградительными весьма уместно. Пришло время искать другие решения.
Отправка SMS через собственные модемы (ведь некоторые бары оборудованы таковыми, как, например, на фото из заголовка) отпала сразу. Причины следующие:
- потенциальные проблемы и танцы с бубнами при отправке сообщений через устройства различных производителей, моделей, прошивок,
- потенциальные проблемы с зависаниями устройств,
- сложность централизованного администрирования территориально-распределённого оборудования,
- высокие риски быть заблокированными со стороны сотовых операторов, которые знают толк не только в том, как заработать, но и как вычислить таких, как мы, и ввести против нас
и не толькоразличные ограничения.
Третий вариант — это задействование возможностей открытого программного обеспечения Asterisk, когда на номер пользователя поступает автоматизированный звонок, и необходимо в качестве пароля указать последние цифры звонящего номера. Сейчас много где так организовано. Этот способ имеет преимущество — отсутствие длительности разговора, ведь после поднятия трубки АТС самостоятельно разрывает соединение. Однако имеются другие накладные расходы – необходим определённый пул арендуемых номеров (и желательно большой), который стоит денег. Например, аренда одного городского номера выходит порядка 350 рублей в месяц. Если использовать вместо арендуемых номеров обычные модемы – минусы такого решения рассмотрены выше.
Четвёртый вариант — использование Asterisk, когда на номер пользователя поступает автоматизированный звонок, и робот голосом сообщает пароль. Корпоративный арендуемый номер у компании Coffee Сup уже был, тарификация посекундная, следовательно, накладные затраты должны быть адекватными. Как это всё интегрировать в имеющуюся инфраструктуру (с учётом того, что сеть за эти годы значительно подросла), подробно рассмотрим ниже. Непосредственно общая настройка АТС к рассматриваемой теме не относится, поэтому концентрироваться на ней не будем.
▍ Hotspot с идентификацией пользователей посредством Asterisk
Изначально проект казался более сложным, чем вышел на самом деле, благодаря гибкости имеющихся решений и используемого программного обеспечения. Казалось, что нужна будет интеграция с API, например, от Google, по переводу текста в голос для работы диктора. Однако это избыточно, ведь Asterisk имеет на борту заготовленные звуковые файлы различного содержания, в том числе подходящие для нашего проекта. Общая схема следующая: пользователь подключается к Hotspot, получает приглашение на ввод номера телефона, который посредством HTTP GET передаётся на сервер АТС, где обрабатывается и формируется задание для Asterisk. Ответом на запрос является пароль доступа к Hotspot. После этого осуществляется звонок на номер пользователя, при котором проигрываются необходимые аудиозаписи с кодом доступа. Далее в рефакторинг не лезем, всё работает по старой схеме. Для начала подготовим аудиофайлы для Asterisk. Скорее всего, они не будут предустановлены:
ls /usr/share/asterisk/sounds/
apt-cache search asterisk | grep sounds-ru
apt install asterisk-core-sounds-ru asterisk-core-sounds-ru-gsm asterisk-core-sounds-ru-wav asterisk-core-sounds-ru-g722 -y
ls –l /usr/share/asterisk/sounds/ru/
В нашем проекте пароль доступа к Hotspot представляет четырёхзначное число. Здесь лежат звуки пауз, например, длительностью в 1 секунду: /usr/share/asterisk/sounds/ru/silence/1. Здесь имеются записи произношения диктором цифр: /usr/share/asterisk/sounds/ru/digits/0. Кстати, на борту представлен простой и удобный способ записи собственных сообщений. Для этого внесём изменения в имеющийся диалплан:
# nano /etc/asterisk/extensions.conf
[test-record]
exten => _1000,1,Wait(2)
exten => _1000,n,Record(/tmp/sound${EXTEN:2}:wav)
exten => _1000,n,Wait(1)
exten => _1000,n,Playback(/tmp/sound${EXTEN:2})
exten => _1000,n,Wait(2)
exten -> _1000,n,Hangup()
Укажем данный extension нужному endpoint:
# nano /etc/asterisk/pjsip.conf
[3002]
type=endpoint
context=test-record
# systemctl restart asterisk
Звоним с указанного endpoint на номер 1000, говорим что-нибудь, после чего слышим произнесённое, а качественная запись голоса будет сохранена в файле /tmp/sound00.wav. Чтобы инициировать звонок от имени АТС, можно использовать либо CLI, либо командный файл. Пример работы посредством консоли представлен ниже:
/usr/sbin/asterisk -rx "channel originate pjsip/3001/3002 application playback /var/lib/asterisk/sounds/custom/sound00"
/usr/sbin/asterisk -rx "channel originate pjsip/+71111111111@siplink-74992222222 application playback /var/lib/asterisk/sounds/custom/sound00"
Кстати, вместо проигрывания звуковых файлов может быть использовано встроенное в Asterisk приложение, которое умеет произносить цифры (для озвучивания чисел есть другое приложение) однако придётся позаниматься русификацией:
channel originate pjsip/3001/3002 application saynumber 123
В проекте вместо CLI использовался командный файл. Чтобы инициировать звонок на номер +71111111111, подготавливаем:
# nano /var/spool/asterisk/tmp/test.call
Channel: PJSIP/+71111111111@siplink-74992222222
Application: Playback
Data: /var/lib/asterisk/sounds/custom/sound00
Чтобы воспроизвести несколько файлов, их нужно перечислить через амперсанд. Копируем командный файл в нужное место, и АТС сразу выполнит полученные инструкции:
cp /var/spool/asterisk/tmp/test.call /var/spool/asterisk/outgoing/test.call
Приведу пример используемого extension:
# nano /etc/asterisk/extensions.conf
[siplink-out-74992222222]
exten => _XXXX,1,Dial(PJSIP/${EXTEN})
exten => _+X.,1,Dial(PJSIP/${FILTER(+0-9,${EXTEN})}@siplink-74992222222)
Здесь хочу порекомендовать провайдера IP-телефонии Siplink — профессиональные ребята. Давно пользуюсь их услугами, приятно работать: хорошая поддержка, адекватные тарифы.
На этом настройка Asterisk заканчивается, осталось доработать веб-сервер и RouterOS. В скрипте для работы Hotspot удалим использование API сторонних сервисов и добавим следующее:
:local SITE pbx.tratata.ru;
:local PORT 443;
:local APIKEY 0123456789;
…
local pass ([/tool fetch url="https://$SITE:$PORT/\?secret=$APIKEY&msisdn=$uname" output=user as-value]->"data")
Пароль пользователя и командный файл для Asterisk будем генерировать прямо на АТС. Для этого настроим любой веб-сервер, активируем HTTPS. Как это сделать, упускаем, инструкций более чем достаточно. Подготовим index.php:
<?php
$api = '0123456789';
$key_from_get = trim(htmlspecialchars($_GET["secret"]));
$dir = '/usr/share/asterisk/sounds/ru';
$silence = "$dir/silence/1";
$sip1 = "@siplink-74992222222";
$sip2 = trim(htmlspecialchars($_GET["msisdn"]));
$fileWeb = 'file.txt';
$fileAsterisk = 'file2.txt';
if ( $key_from_get === $api AND strlen("$sip2") === 10 AND ctype_digit("$sip2") ) {
$pas1d = random_int(0, 9);
$pas2d = random_int(0, 9);
$pas3d = random_int(0, 9);
$pas4d = random_int(0, 9);
echo "$pas1d$pas2d$pas3d$pas4d";
$myfile = fopen("$fileWeb", "w");
$txt = "Channel: PJSIP/+7$sip2$sip1\n";
fwrite($myfile, $txt);
$txt = "Application: Playback\n";
fwrite($myfile, $txt);
$txt = "Data: $silence&$dir/digits/$pas1d&$silence&$dir/digits/$pas2d&$silence&$dir/digits/$pas3d&$silence&$dir/digits/$pas4d\n";
fwrite($myfile, $txt);
fclose($myfile);
rename("$fileWeb", "$fileAsterisk");
}
?>
Веб-сервер получает номер пользователя, генерирует ему пароль доступа, возвращает его в качестве ответа и подготавливает соответствующее задание для АТС. Непосредственный перенос файла в папку Asterisk выполняет bash-скрипт. Такая прослойка сделана для возможности прикручивания допов на будущее, работает стабильно. PHP-cкрипт валидирует и проверяет длину и состав номера пользователя, при звонке сам подставляет телефонный код +7, чтобы отсутствовала возможность списывать деньги со счёта посредством звонков, например, на Марс. Здесь необходимо отметить, что используемый скрипт RouterOS содержит проверку и блокировку множественных однотипных запросов:
#Cheks user from spam
:local sendtest yes;
:foreach i in=[/ip firewall address-list print as-value where list=spam_cheks_list] do={
:if (($i->"address")=$uname) do={
:set $sendtest no;
}
}
:if ($sendtest=yes) do={
/ip firewall address-list add list=spam_cheks_list address=$uname timeout=00:05:00;
…
}
JavaScript на странице Hotspot никакой реальной защиты не добавляет, а только помогает пользователю не ошибиться при наборе цифр. На страницу добавлено уведомление о том, что поступит звонок от робота с арендуемого нами корпоративного номера:
![](https://habrastorage.org/webt/ng/ij/j4/ngijj4vo77t-etv_udae2h4pfz0.png)
Готово! Получаем приятную стоимость одного такого звонка в 20-30 копеек, что даже дешевле, чем отправка SMS по «старым» доиюльским ценам:
![](https://habrastorage.org/webt/vi/nb/yp/vinbypn0sv16forokh4ib3slcxq.png)
▍ Заключение
В статье мы рассмотрели доработку Hotspot до идентификации пользователей посредством звонка от Asterisk и диктовки пароля с целью миграции от SMS-gateway-шлюзов из-за значительного удорожания их сервисов. Минусом такой организации является то, что на время приёма звонка сотовый телефон посетителя отключается от Wi-Fi, что не такая уж и проблема, так как при повторном подключении имеется возможность выбрать «У меня уже есть код». Решение рабочее, следующая точка отказа – борьба большой тройки с IP-телефонией, как уже некоторые начинают делать, безразборчиво блокируя подобные входящие вызовы, ссылаясь на противодействие мошенничеству. Как видно из кода, несложно всё доработать на использование пула номеров и идентификацию посредством ввода последних цифр звонящего номера, без длительности разговора и списания денег. Полученное решение достаточно гибкое, много что можно нарастить. Моё личное мнение: Open-source Software — сила, особенно в очумелых руках.
Telegram-канал с полезностями и уютный чат
![](https://habrastorage.org/webt/sz/7j/pf/sz7jpfj8i1pa6ocj-eia09dev4q.png)