Однажды заказчик, которому я разворачивал офисную телефонию, спросил меня: «А можно нашим сотрудникам поставить на телефоны SIP клиенты, чтобы их разговоры с клиентами проходили через офис, попадали в CRM и записывались?»
Мысль заказчика понятна: Почему бы просто не поставить софтофон на мобильник и не настроить его на свой сервер?
Но есть несколько причин, почему это работает откровенно плохо:
Софтофону придётся разрешить постоянную фоновую работу, иначе нет входящих звонков. Но это очень быстро «сушит» батарею. Конечно же, я знаю про схему linphone + Flexisip, но если честно, я тупо не смог нормально собрать Flexisip.;)
Проблемы с удержанием сессии. SIP протокол не любит клиентов со внезапно меняющимися IP адресами. А мобильный телефон делает это довольно часто.
SIP за NAT это отдельный вид мазохизма. Особенно весело, когда звук динамически пропадает на любой из сторон при каждом отдельном вызове.;)
Светить SIP сервер в мир без SBC — не хорошо. Жирный пароль не спасёт от постоянных сканов и брутфорса ботами, а fail2ban вместо защитника порой выполняет функцию вредителя.
В последний раз при необходимости экстренно обеспечить связь с офисом я второпях пустил SIP через OpenVPN. Но туннель регулярно отваливался, а в некоторых случаях вообще отказывался работать через мобильный интернет.
В какой‑то момент я подумал: Почему, чёрт возьми, мобильный софтофон не работает так же просто, как это делают мессенджеры?
Так родился открытый проект Sip2Go.

Идея
Суть задумки была в том, чтобы избавиться сразу от всех проблем SIPа на смартфоне, заставив голосовую связь работать точно так же, как она работает у мессенджеров.
В Sip2Go телефон вообще не является SIP‑клиентом.
Схема выглядит иначе:
┌──────────────┐ │ Android │ │ SIP2GO App │ └──────┬───────┘ │ │ WSS / TLS │ ▼ ┌──────────────────┐ │ SIP2GO Gateway │ │ │ │ WebSocket │ │ ↕ │ │ SIP / RTP │ └────────┬─────────┘ │ │ SIP ▼ ┌──────────────────┐ │ PBX / Asterisk │ └──────────────────┘
Получилось довольно изящно:
SIP остаётся там, где он гарантированно работает, а мобильное устройство разговаривает с сервером обычным защищённым WebSocket‑соединением. Шлюз может подключаться к АТС как обычный SIP клиент, не требуя никаких специфических настроек на её стороне, что кардинально упрощает интеграцию этого софта в уже рабочую систему.

Почему именно WebSocket
Мне нужен был транспорт, который:
нормально работает сквозь NAT;
обходит кривые хелперы, типа SIP ALG, которые частенько вредят.
выглядит как обычный https;
позволяет стабильно удерживать двустороннее соединение;
одинаково хорошо подходит для управляющих сообщений и передачи аудио.
Работает сквозь любой веб сервер в режиме реверс прокси (хоть через cloudflare).
WebSocket здесь оказался практически безальтернативным выбором.
Телефон устанавливает WSS‑соединение с Sip2Go Gateway, после чего через него идут управляющие сообщения и аудио. При этом серверная часть продолжает работать с обычной SIP‑инфраструктурой. А это залог того, что для шлюза нет принципиальной разницы, к какой именно АТС его подключат: будь то условный FreePBX, проприетарная коробочка с лампочками или вовсе SIP провайдер с неизвестно чем под капотом.
Что происходит при звонке
Допустим, пользователь хочет позвонить с мобильного приложения.
Android отправляет запрос через WebSocket на gateway.
Gateway уже сам взаимодействует с SIP‑сервером:
Android │ │ "позвонить на 123" ▼ SIP2GO Gateway │ │ SIP INVITE ▼ PBX │ ▼ SIP абонент
В обратную сторону всё работает почти так же, но с небольшим нюансом.
Когда на соответствующий номер приходит входящий звонок, PBX передаёт его gateway (как своему абоненту), а дальше немного магии: шлюз отправляет серверу прогресс звонка, а сам в это время отправляет мобильному клиенту FCM (push пробуждение) и ждёт, когда подключится к шлюзу.
При этом мобильный клиент не обязан постоянно висеть на сессии и ждать звонка. Шлюз будет «искать» его и держать статус RINGING до тех пор, пока клиент не примет звонок или не наступит таймаут. Тут практически как у мобильных операторов.:)
Что там с RTP?
На стороне PBX мы остаёмся в привычном мире SIP, работая на кодеках PCMU/PCMA (ulaw/alaw).
На стороне мобильного устройства аудиопоток кодируется в Opus и бегает через WebSocket.
Gateway выступает посредником и транскодером между этими двумя мирами:
SIP / RTP │ PCMU/PCMA | ▼ ┌─────────────────┐ │ Gateway │ │ │ │ audio bridge │ │ │ └────────┬────────┘ │ Opus │ ▼ Android
В результате мобильному приложению не нужно реализовывать весь зоопарк SIP/RTP/NAT traversal, который обычно сопровождает VoIP‑клиент. Ему достаточно поддерживать собственный небольшой протокол общения с gateway.
Удерживаем связь до последнего
Разрыв соединения может случиться по самым разным причинам, начиная со смены IP адреса, при переключении между сетями и заканчивая полным закрытием приложения.
Например, если соединение было потеряно в момент, когда звонок уже поступил, приложение не должно считать, что ничего не происходило.
Даже в сценарии рестарта приложение, как только оно снова подключится к шлюзу, тот сообщит о наличии активной сессии и попытается её возобновить, не роняя вызов.
Для этого gateway и клиент умеют синхронизировать состояние активного вызова после повторного подключения. Время, отведённое на попытки восстановления соединения настраиваются на стороне шлюза.
Если же восстановить связь вовремя не удалось — шлюз отправляет АТС грустный Bye.;)
А что происходит с SIP?
PBX продолжает заниматься своей работой. Для неё Sip2Go Gateway выглядит как ещё один SIP endpoint. Можно использовать существующую инфраструктуру телефонии, а мобильный доступ добавляется отдельным слоем. Это позволяет использовать Sip2Go вместе с существующей телефонией, не превращая PBX в экспериментальную лабораторию.
Правда, тут имеется маленький нюанс: я не стал реализовывать множественную регистрацию. То есть, если работать через регистрацию — получится прокинуть только один endpoint. А вот если нужно запихать сразу много, то нужно подключить шлюз в режиме транка (авторизация по IP) и маршрутизировать в его сторону вызовы на номера всех его подопечных. Наиболее удобный вариант в данном случае — выделить мобильным клиентам свой внутренний пул (например 7XXX)

Лёгкое подключени
Понимая, кто будет пользоваться этим приложением я решил, что нужно максимально упростить его настройку.
В голову мысль: а почему бы не сделать настройку как у eSIM? Отсканил одноразовый QR, либо кликнул на одноразовую ссылку и ты в сети!
Реализация такого подхода моментально избавила меня от необходимости лишнего сопровождения пользователей.
Боевые испытания
Одним из первых пользователей Sip2Go в реальных условиях стал руководитель предприятия, которое я обслуживаю.
До этого мы с ним использовали схему с SIP‑клиентом поверх OpenVPN, и периодическая диагностика глюков этой связки меня однажды прилично достала.
Когда появилась первая рабочая версия Sip2Go, я предложил ему стать добровольным испытателем.
Тестирование получилось особенно значимым, поскольку в данном случае удалось испытать работу софта за пределами страны, где был расположен сервер.
Честно говоря, я даже не знаю, кто из нас был больше впечатлён результатом: Шеф, который внезапно получил простое решение наболевшей проблемы или я, который офигел от положительных отзывов весьма требовательного пользователя.:)
Open source
Sip2Go состоит из двух основных частей:
Исходный код открыт, Шлюз можно развернуть на собственной инфраструктуре и использовать собственные Firebase credentials для push‑уведомлений. Также, придётся собрать и приложение, добавив в него свои ключи от firebase. Инструкция по установке имеется тут и на репозитории проекта.

Заранее поясню, что это за настройка "Push relay URL" и "Push relay API key".
Данная настройка предназначена для коммерческих клиентов, которые пользуются официальной сборкой приложения с Google Play с привязкой к моему аккаунту Firebase. Она используется исключительно для того, чтобы не хранить приватный токен на серверах клиентов и не является обязательной, поскольку при добавлении своего токена в .env шлюз сможет отправлять FCM без всяких дополнительных релеев. Более подробная информация об этом находится тут.
Абсолютно весь функционал программы, без каких либо ограничений доступен бесплатно, при условии самостоятельной сборки приложения с привязкой к своему аккаунту Firebase.
А где клиент под iOS?
Увы, у меня нет аккаунта разработчика для apple. Собственно, как и нет устройств, на которых можно тестировать софт.
Впрочем, я был бы искренне рад, если бы за это взялся кто‑то другой.:)
Комментарии (23)

funchaser
20.09.2026 16:28TG2sip кажется уже есть много лет...
https://github.com/Infactum/tg2sip
И форки есть разные, например:
https://github.com/foobar26/tg2sip

MegaCrash Автор
20.09.2026 16:28Имеет место быть, но мой проект полностью self hosted и никак не зависит от инфраструктуры сторонних мессенджеров.

ddv2005
20.09.2026 16:28А можно по подробнее про форки потому что оригинальный проект уже устарел и не работает с новыми версиями официальных клиентов. Я попытался найти что то рабочее, но нашел только 2 проекта один из которых облачный, а второй (tg2sip_tgcalls_webrtc) хоть и мимикрирует под opensource, но на самом деле кода нет даже по запросу.

funchaser
20.09.2026 16:28https://github.com/foobar26/tg2sip
Вроде - рабочий вариант... (запустил - звонки проходят, качество хорошее, когда VPN работает ;-) ) Проверял Yealink SIP Phone <-> Asterisk<-> Android TG client v12.10.3

hwyf17
20.09.2026 16:28Подскажите Уважаемый. А есть возможность поднять gateway в докере?

MegaCrash Автор
20.09.2026 16:28Готового образа нет, если только сами не соберёте. :)

hwyf17
20.09.2026 16:28(голосом Г. Хазанова)Да ежели я это мог бы,
зачем бы я тогда жениться бы сталя ненастоящий сварщик. Может подумаете в эту сторону тоже, обретете немало заинтересовавшихся?

ddv2005
20.09.2026 16:28Да, докера для сборки и для работы очень не хватает. В наше время уже мало кто собирает без докера устанавливая все засисимости проекта на локальную машину.

MegaCrash Автор
20.09.2026 16:28Там из глобальных зависимостей только кодек opus и python venv, всё остальное ставится в виртуальное окружение и ни чему не мешает. Ну если прям уж так сильно нужна изоляция, запустите в докере образ debian 12/13 и ставьте туды. У меня дома он вообще вместе с FreePBX стоит в LXС контейнере под ProxMox.

lifespirit
20.09.2026 16:28Конечно же, я знаю про схему linphone + Flexisip, но если честно, я тупо не смог нормально собрать Flexisip.;)
Удивительно. Особенно то что flexisip не обязательный как бы компонент.
SIP протокол не любит клиентов со внезапно меняющимися IP адресами
Именно sip протокол может работать по TCP и, внезапно, по WSS.
Жирный пароль не спасёт от постоянных сканов и брутфорса ботами
И поэтому нужно включать авторизацию по client cert и всё.
Почему, чёрт возьми, мобильный софтофон не работает так же просто, как это делают мессенджеры?
И он может. WebRTC называется. Решает всё что вы перечислили. Звонить даже можно без АТС собственно.
Так родился открытый проект Sip2Go.

В мире существует 14 несовместимых стандартов... 
MegaCrash Автор
20.09.2026 16:28Удивительно. Особенно то что flexisip не обязательный как бы компонент.
Правда? А как FCM прикрутить к АТС без flexisip, особенно учитывая, что это не обязательно Asterisk?

lifespirit
20.09.2026 16:28Lifephone передаёт UUID для push открытым текстом вх сипе. В exceptions.conf просто выдёргиваешь его и передаёшь любому скрипту при регистрации. При звонке соответственно вызываешь скрипт по номеру, он выбирает из базы токен пуша и пушит. Всяко проще чем целый клиент написать. А под freeswitch и kamailio уже и модули готовые есть, даже скрипт не нужен. Только токен для пуша сохрани.
Даже если там полный самопал поставь kamailio и дергай им. Дел не так и много. Flexisip реально нужен только если хочешь полный стек с конференциямми, чат комнатами и т.д.

Di-Ger
20.09.2026 16:28Поддержу. Не скажу на счет Asterisk(очень давно не пользуюсь), но к тем же Kamailio и FreeSwitch давно есть модули под wss. Да собственно где их нет? Я собирал связку ejabberd + Yate, дак там звонить можно было даже не с SIP клиентов.

ZigFisher
20.09.2026 16:28Добрый день
А как насчет возможности осуществить полноценный или принять односторонний видеозвонок,е сть-ли такая возможность или планы ?
Вопрос не праздный, у нас в openipc.org теперь во всех прошивках видеокамер есть встроенный SIP и какое-то решение с приложением, например ваше, возможно гармонично сложилось-бы в интересный тандем.
Спасибо.
MegaCrash Автор
20.09.2026 16:28Можете форкнуть. :) Если честно, я всем сердцем ненавижу видеозвонки, по этому нагружать этим проект не имею никакого желания.

ZigFisher
20.09.2026 16:28Речь в принципе не о видео-звонках и конференциях, а об создании простой экосистемы подключения к домофонам.
Информация принята, спасибо за вашу разработку, будем наблюдать и возможно пытаться внедрять.

event1
20.09.2026 16:28Вы конечно молодец, что написали такую штуку, но кажется, вы изобрели велосипед. Ведь есть готовые решения: WebRTC в самом Asterisk, плагин для xmpp и, наконец, интеграция с jitsi. Если нет, то стоило упомянуть, почему они не подходят.

antirek
20.09.2026 16:28Круто, недавно делал аналогичную штуку, но на готовом Janus - janus webrtc + sip plugin. Коллеги, кто предлагает webrtc в самом asterisk, kamailio и т.д. не принимают, что вам надо не заморачиваться с sip сервером, а "разделить" sip абонента на две части - sip и webrtc - и это просто удобно - подключить можете любой sip - своего абонента с корпоративной АТС или учетку Мультифона, sipnet'а. https://github.com/antirek/wosobo только приложение не делал, чисто для веб-интерфейсов, типа CRM, встройку звонилки делать.
Uint32
Респект и уважуха!
Обязательно где-нить применю!