Один из краеугольных вопросов в зарубежных поездках — это вопрос связи. С одной стороны — вроде как проблемы и нет, к вашим услугам туристические и предоплаченные сим-карты, точки доступа Wi-Fi, на худой конец есть обыкновенный роуминг. Но стоит попробовать залогиниться в какой-нибудь сервис с многофакторной аутентификацией (будь то криптобиржа или банк-клиент) — тут же всплывают нюансы. SMS не приходят или приходят слишком поздно, когда срок действия одноразового кода уже вышел. В некоторых регионах возникают сложности как с исходящими, так и с входящими вызовами. В лучшем случае все это становится мелкими неудобствами, а в худшем — часть ваших возможностей существенно ограничивается или вовсе недоступна. Возможно, пришло время добавить очередную сущность в инфраструктуру — АТС с GSM шлюзом.

В первую очередь нужен модем. Лучше всего разжиться 3G модемом от Huawei — несмотря на то, что сами по себе 3G модемы считаются морально устаревшими, именно на них удобнее всего организовать GSM шлюз (к тому же на вторичке их отдают почти что даром). Я использую модем Huawei E1550, но можно смело рассматривать модели E169, E620, E800. Перед дальнейшими действиями нужно убедиться, что соблюдены необходимые критерии:

  • На модеме активированы голосовые вызовы
  • Модем разлочен от оператора
  • Выставлен режим «только модем» (без виртуального CD-ROM, Card Reader и т.д.)

По этим моментам я не буду проходиться отдельно, подробные сведения можно найти на 4pda или других ресурсах — всё, что связано с этими модемами было разжевано множество раз. Единственное, что уточню — во время разлочки модема и работы с утилитами следует заранее себе выписать IMEI модема и IMSI номер SIM карты — они еще пригодятся. Соответствующие АТ команды привожу ниже:

AT+CGSN (информация о IMEI модема)
AT+CIMI (информация об IMSI SIM карты)

Во вторую очередь — нужна АТС. Раньше для этих целей у меня жил отдельный компьютер (который когда-то был тонким клиентом), сейчас же я держу АТС в виртуальной машине, используя VMware с проброшенным USB портом — к которому и подключен 3G модем. В качестве дистрибутива возьмем MikoPBX, подробные инструкции по установке можно найти на официальном Wiki проекта. Особо стоит оговорить, что «фирменная» инструкция по сопряжению MikoPBX с 3G модемами Huawei есть, но в ней есть несколько ошибок — одну из которых (а она «блокирующая») пользователь без опыта работы с Asterisk просто не распознает.

Итак, продолжим. Подключаем 3G модем к АТС и сами подключаемся к АТС через SSH — нас встретит меню MikoPBX. Выходим из меню в консоль (Shell), командой lsusb проверяем перечень подключенных USB устройств:

Bus 001 Device 002: ID 12d1:1001
Bus 001 Device 001: ID 1d6b:0002
Bus 002 Device 003: ID 0e0f:0002
Bus 002 Device 002: ID 0e0f:0003
Bus 002 Device 001: ID 1d6b:0001

Вот такой вывод получился у меня. Несколько лет назад эта же самая команда в MikoPBX выдавала и текстовое описание, помимо «сырых» ID устройств:

Bus 001 Device 002: ID 12d1:1001 Huawei Technologies Co., Ltd. E1550 HSDPA Modem
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 003: ID 0e0f:0002 VMware, Inc. Virtual USB Hub
Bus 002 Device 002: ID 0e0f:0003 VMware, Inc. Virtual Mouse
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub

Так или иначе, нас интересует устройство с ID 12d1:1001 — это наш искомый модем.

12d1 — идентификатор производителя.
1001 — идентификатор модема

Чтобы убедиться, что это действительно модем, используем команду lsusb -v с параметром расширенного вывода:

Bus 001 Device 002: ID 12d1:1001
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x12d1
idProduct 0x1001
bcdDevice 0.00
iManufacturer 3 HUAWEI Technology
iProduct 2 HUAWEI Mobile

Дальше ищем информацию о модеме по идентификатору производителя, вводим в консоль команду dmesg | grep 12d1 и получаем вывод:

usb 1-1: New USB device found, idVendor=12d1, idProduct=1001, bcdDevice= 0.00

Отлично, теперь вводим в консоль команду dmesg | grep ‘usb 1-1’ для получения информации по устройству usb 1-1:

usb 1-1: new high-speed USB device number 2 using ehci-pci
usb 1-1: New USB device found, idVendor=12d1, idProduct=1001, bcdDevice= 0.00
usb 1-1: New USB device strings: Mfr=3, Product=2, SerialNumber=0
usb 1-1: Product: HUAWEI Mobile
usb 1-1: Manufacturer: HUAWEI Technology
usb 1-1: GSM modem (1-port) converter now attached to ttyUSB0
usb 1-1: GSM modem (1-port) converter now attached to ttyUSB1
usb 1-1: GSM modem (1-port) converter now attached to ttyUSB2

Теперь нам известны идентификаторы COM-портов модема: ttyUSB0, ttyUSB1, ttyUSB2. Если вы видите похожую картину — то половина пути уже позади, если же COM-портов нет, то, возможно, вы не перевели модем в режим «только модем».

На некоторых устройствах режим «только модем» отображается как 140c, а не 1001

Третий этап, идём в веб-интерфейс MikoPBX, слева в меню ищем раздел «Система», в нём — «Кастомизация системных файлов». Открываем файл /etc/asterisk/modules.conf в режиме «Добавлять в конец файла», дописываем:

load => chan_dongle.so
load => app_system.so
load => func_base64.so

Нажимаем кнопку «Сохранить». Теперь открываем файл /etc/asterisk/dongle.conf в режиме «Заменять полностью», копируем конфигурацию:

[general]
interval=15

 

[defaults]
context=public-direct-dial
group=0
rxgain=0
txgain=0
autodeletesms=yes
resetdongle=yes
u2diag=-1
usecallingpres=yes
callingpres=allowed_passed_screen
disablesms=no

 

language=en
smsaspdu=yes
mindtmfgap=45
mindtmfduration=80
mindtmfinterval=200

 

callwaiting=auto
disable=no
initstate=start
dtmf=relax

 

[dongle0]
audio=/dev/ttyUSB1
data=/dev/ttyUSB2

imei=123456789098765
imsi=987654321012345

Вот где нужны ранее выписанные IMEI и IMSI, без их указания в конфигурации у меня не получалось добиться работоспособности. Сохраняем изменения.

Теперь нужно создать контексты для USSD и SMS. И, если USSD меня не сильно интересует как явление, то вот SMS — один из ключевых пунктов ради чего всё это затевалось. Наиболее удобным способом принимать SMS для меня является Telegram, особенно это актуально для тех случаев, когда физически модем и АТС расположены в зоне устойчивого покрытия, а сам я нахожусь в дальних далях, где сотовой связи практически нет, но в моем распоряжении рабочая станция или ноутбук с проводным подключением к сети Интернет. Перед дальнейшими действиями нужно создать бота Telegram (просто получить токен, больше ничего не нужно) и узнать свой ID для отправки уведомлений. Когда токен и ID на руках — открываем файл /etc/asterisk/extensions.conf в режиме «Добавлять в конец файла» и вписываем контексты:

[dongle-incoming-ussd]
exten => ussd,1,Noop(Incoming USSD: ${BASE64DECODE(${USSDBASE64})})
exten => ussd,n,Hangup()

 

[public-direct-dial]
exten => sms,1,Noop(Incoming SMS from ${CALLERID(num)} ${BASE64_DECODE(${SMS_BASE64})})
exten => sms,n,System(echo '${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} — ${DONGLENAME} — ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}' >> /var/log/sms.txt)
exten => sms,n,System(curl —data "text=${STRFTIME(${EPOCH},,%Y-%m-%d %H:%M:%S)} — ${DONGLENAME} — ${CALLERID(num)}: ${BASE64_DECODE(${SMS_BASE64})}&chat_id=<CHAT_ID>" "https://api.telegram.org/bot<TOKEN>/sendMessage")
exten => sms,n,Hangup()

Где <CHAT_ID> — это ID пользователя или чата, а <TOKEN> — токен вашего бота. Особо стоит оговорить, что после модификации файла dongle.conf и сохранения изменений в нём требуется перезагрузить АТС чтобы произведенные изменения вступили в силу, однако работа с этим файлом еще не закончена.

dongle0 — произвольное имя линии (модема)
audio, data — значения этих параметров — COM-порты устройств, определенных на предыдущем этапе. Если не будет звука, то поменять местами.

Возвращаемся к SSH сеансу. Командой asterisk -r запускаем консоль Asterisk, после чего с помощью команды dongle show devices смотрим на перечень модемов:

ID Group State RSSI Mode Submode Provider Name Model Firmware IMEI IMSI Number
dongle0 0 Free 14 0 0 AT&T E1550 11.609.20.00.00 123456789098765 987654321012345 +79998877666

Если после IMEI и IMSI не указан номер, то его следует указать вручную через АТ команды:

dongle cmd dongle0 AT+CPBS=\"ON\"
dongle cmd dongle0 AT+CPBW=1,\"+79998877666\",145

Настраиваем маршрут входящих. В веб-интерфейсе MikoPBX слева в меню ищем раздел «Маршрутизация», переходим в пункт «Входящие маршруты». Создаем новый маршрут после удаление дефолтного или полностью переделываем дефолтный:

Иллюстрация

Суть сводится к тому, что в поле «Дополнительный номер» (он же DID) нужно указать номер SIM-карты, куда дальше пойдет переадресация вызова — тут смотрите сами.

Следующий этап — настройка исходящего маршрута. Здесь чуть сложнее и не совсем очевидно, но я постараюсь провести короткой дорогой. В разделе «Маршрутизация» выбираем пункт «Провайдеры», удаляем дефолтную запись и создаём новую, нажав на кнопку «Подключить SIP». Конечно, никакого SIP-провайдера мы здесь подключать не будем, достаточно задать имя оператора, указываем хост 127.0.0.1, а тип учетной записи ставим «Аутентификация по IP адресу без пароля». Сохраняем изменения.

Иллюстрация

Теперь самое важное — в адресной строке браузера из URL вычленяем ID только что созданного провайдера:

https://domain.com/admin-cabinet/providers/modifysip/SIP-TRUNK-1150B6D2

Слева в меню идём в раздел «Система», выбираем пункт «Кастомизация системных файлов». Снова открываем файл файл /etc/asterisk/extensions.conf в режиме «Добавлять в конец файла» (я ведь обещал, что к этому файлу мы еще вернемся) и дописываем в самом конце контекст исходящих звонков:

[SIP-TRUNK-1150B6D2-outgoing-custom]
exten => _[0-9*#+]!,1,Set(DIAL_COMMAND=Dongle/dongle0/${number})
same => n,return

Последние штрихи — возвращаемся в раздел «Маршрутизация», переходим в пункт «Исходящие маршруты». Изменяем дефолтный или создаём новый:

Иллюстрация

Здесь можете «поиграться» с параметрами отсечения и добавления цифр в начале номера.

Итак, что мы получили на выходе:

  • Полноценную АТС с голосовым меню, расписанием, записью звонков и прочими возможностями из мира серьезной телефонии
  • Возможность звонить в GSM-сети из SIP клиента
  • Входящие SMS нам пересылает бот в Telegram

PS: время от времени нужно очищать память модема от скопившихся SMS сообщений. Это можно сделать двумя командами (которые лучше всего подвязать в cron):

asterisk -rvx 'dongle cmd dongle0 AT+CPMS=\"ME\",\"ME\",\"ME\"'
asterisk -rvx 'dongle cmd dongle0 AT+CMGD=1,4'