По заявкам радиослушателей читателей продолжу публиковать мои экзерсисы с Asterisk. На этот раз про мобильные клиенты с поддержкой push. Снова не буду сильно распинаться, только основное и по-делу.

На рынке существует несколько SIP-клиентов с поддержкой push, как минимум мне известны Groundwire и Bria Mobile. Последней я пользуюсь много лет и повествование будет о ней. Хоть опция push и платная (все таки это требует от разработчика приложения инфраструктуры), она сильно экономит трафик и расход батареи.

Asterisk и push

Push в VoIP приложниях реализован следующим образом: приложение передает реквизиты соединения на сервера разработчика, в свою очередь они поддерживают SIP-соединение с Asterisk и в случае входящего звонка или сообщения будят приложение на телефоне push-ом. Оно просыпается, быстро регистрируется и получает входящий вызов.

Для передачи соединения между push-серверами и клиентом поддерживаются разные стратегии: стандартная (я так и не понял, в чем ее особенность), continuous (push-сервера перманентно поддерживают соединение вне зависимости от того, активен клиент или нет), single device emulation и single device takeover (различные варианты работы соединения с одним активным подключением). В ходе своих экспериментов я остановился на сontinuous, как наиболее стабильном и гарантирующим доставку звонков.
Такое подключение требует поддержки нескольких контактов в AOR у pjsip.

[bria](!)
type=aor
max_contacts=10

NAT traversial

Как и в предыдущей публикации, повторюсь, что Mikrotik имеет вполне неплохой SIP ALG, главное, ему не мешать делать свою работу. Отключите на Mikrotik опцию Direct media в SIP ALG и не используйте external_media_address в настройках pjsip, тогда Mikrotik отлично справится с проброской RTP и подстановкой правильных адресов в SIP SDP в зависимости от маршрута.

Далее, Bria имеет свои особенности при работе через мобильную сеть, она просто не может разрешить свой адрес и в SIP SDP в качестве обратного адреса для медиа приходит 192.0.0.2. Благо она использует симметричный RTP для пробивки NAT (nat punch), так что проблема решается довольно легко:

[bria](!)
type=endpoint
direct_media=no
rtp_symmetric=yes

Борьба с SIP-сканерами

Открывая ваш SIP в публичный домен вы автоматически становитесь объектом атаки любителей халявы и ваш Asterisk регулярно подвергается сканированию. Для борьбы с этой напастью я нашел весьма действенный метод: как правило хаявшики ничего не знают об имени вашего домена, так что вы можете создать на Mikrotik Firewall свой L7 protocol, указав в нем регулярное выражение для вашего домена. Затем создайте фильтр для udp 5060 укажите этот L7 protocol. Не забудьте также указать домен в настройках клиента.

К сожалению, push-сервера Bria также игнорируют имя домена, но эта проблема решается созданием address list с адресами, которые следует исключить из фильтрации. Список адресов можно взять тут - https://support.counterpath.com/hc/en-us/articles/9937493488919-Bria-Mobile-Push-Notifications

Dialplan

Чтобы о входящем звонке информировались как push-сервера, так и клиент, используйте в Dial() PJSIP_DIAL_CONTACTS, тогда все контакты аккаунта будут получать вызов. В случае использования очередей это не обязательно - звонок прийдет на все контакты аккаунта.

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


  1. TerAnYu
    08.10.2024 20:08

    Для полноты вашего поста, на мой взгляд, не хватает примеров:

    • Как создать нужное правило и фильтр для L7

    • Пример использования для Dial

      Новичкам это очень не хватает.


    1. performer Автор
      08.10.2024 20:08
      +1

      1. можно через WinBox или WebFig, но если в терминале - то

        /ip firewall layer7-protocol

        add name="sip-pass" regexp="sip[.]mydomain[.]ru"
        Дальше drop rule как-то так:

      2. Dialplan - штука очень интимная :(

        К сожалению или к счастью, статья не для новичков, а то делов можно натворить :(


      1. TerAnYu
        08.10.2024 20:08
        +1

        1. Отлично.

        2. Я имел ввиду пример вызова функции Dial, например так:

          exten => _[1]xx,1,NoOp(Набран номер ${EXTEN})
              same => n,Dial(${PJSIP_DIAL_CONTACTS(${EXTEN})},20,tr)
              same => n,Hangup()

          где при наборе внутреннего номера, согласно маске, 1XX буду звонить все Contacts/Endpionts набранного номера, например 102

          Endpoints:

           Endpoint:  102                                                  Not in use    0 of 1
               InAuth:  102/102
                  Aor:  102                                               10
                Contact:  102/sip:102@192.168.189.4:46452            1c002cad22 Avail        46.569
                Contact:  102/sip:102@192.168.253.200:38526          b82d62e82f Avail         6.445
            Transport:  udp_transport             udp      3     96  0.0.0.0:5060


          Contacts:

            Contact:  102/sip:102@192.168.189.4:46452                1c002cad22 Avail        46.569
            Contact:  102/sip:102@192.168.253.200:38526              b82d62e82f Avail         6.445