WebRTC-софтфон в браузере на Asterisk: без лишних программ
Москва, Щёлковское шоссе, д. 92, корп. 7 · Пн–Пт 9:00–19:00 · +7 903 729-62-41
АйТи Фреш
Серверы и инфраструктура

Звонить из браузера через свой Asterisk: WebRTC без облака и без Zoiper

Автор: , директор ООО «АйТи-Фреш» · · ~17 мин чтения
Ноутбук с браузером соединён телефонным проводом с серверной стойкой Asterisk — WebRTC-софтфон без установки
Звонить можно прямо из браузера, а коробку с диском выбросить.

Чтобы сотрудники звонили из браузера через собственный Asterisk, нужны chan_pjsip, wss на порту 8089 с доверенным сертификатом, endpoint с webrtc=yes и открытый RTP-диапазон. Ниже конфиги, проверки и три места, где всё ломается.

Зачем звонить из браузера и почему Zoiper надоедает

Звонок директору, у которого «не работает телефон после обновления Windows», — классика жанра. Менеджер сидит на удалёнке, софтфон на ноутбуке вчера ещё регистрировался, сегодня молчит, а вместе с ним молчит отдел продаж. Если у вас собственный Asterisk и внедрение открытых решений давно не новость, то логичный вопрос: зачем вообще ставить на каждый ноутбук отдельную программу, если у человека и так открыт Chrome или Edge?

Ответ на этот вопрос называется WebRTC. Это набор технологий, которые позволяют браузеру самому захватить микрофон, зашифровать голос и отправить его на сервер. Asterisk умеет принимать такие звонки прямо у себя: по WebSocket приходит сигнализация SIP, по отдельному потоку идёт медиа. Сотрудник открывает страницу веб-телефона, вводит логин с паролем и звонит. Ни установщика, ни прав администратора на ноутбуке, ни «а вы точно скачали свежую версию».

Я не буду делать вид, что это волшебная кнопка. Сделать это дорого? Нет. Сделать это правильно с первого раза? Почти никогда: есть три места, где всё ломается стабильно, и я пройдусь по каждому. Сертификат, которому браузер не верит. NAT, из-за которого звук идёт в одну сторону. Кодеки, которые оператор не понимает. Остальное — обычная настройка PJSIP, которую вы наверняка уже видели.

Что именно получится на выходе. Клиентом служит любая страница с JavaScript-библиотекой: у SIP.js и JsSIP есть готовые веб-телефоны, их можно поставить на внутренний сайт или подключить как вкладку к CRM. Логин и пароль в этих телефонах — тот самый логин и пароль из PJSIP-auth, а адрес сервера выглядит как wss://pbx.example.com:8089/ws. Облачная АТС в этой схеме не участвует: вся сигнализация и все разговоры остаются на вашем сервере, как и раньше. Если вы раздумываете, не проще ли всё-таки уйти в облако, у нас есть отдельный разбор, как возвращаться с облачной АТС на свой сервер, и там цифры не в пользу подписки.

Памятка: Зачем звонить из браузера и почему Zoiper надоедает — схема
Памятка: Зачем звонить из браузера и почему Zoiper надоедает. Открыть схему в полном размере

Что поставить на сервер: модули, http.conf и сертификат

Начинать надо с проверки, что у вас вообще есть чем принимать WebRTC. Нужен канал chan_pjsip, а он появился в Asterisk задолго до 15.5, но именно с этой версии WebRTC-клиенты официально поддерживаются так, как описано в документации. В 2026 году живыми ветками считаются LTS 20 и 22; если у вас до сих пор chan_sip, миграцию придётся делать раньше, чем звонки из браузера, и это отдельная история. Нужные модули: res_crypto, res_http_websocket, res_pjsip_transport_websocket и, настоятельно рекомендую, codec_opus. Без Opus всё заведётся, но голос будет на G.711, а смысл WebRTC во многом в нормальном кодеке для плохих каналов.

Если Asterisk собран из исходников, модули выбираются в menuselect. Codec_opus там особенный: это бинарный модуль от Sangoma, а не исходный код, и он подтягивается отдельно. В пакетах из репозиториев и в готовых образах панелей набор модулей отличается, а Opus там бывает отдельным пакетом или не бывает вовсе. Не гадайте — спросите у самого сервера:

asterisk -rx "module show like websocket"
asterisk -rx "module show like res_crypto"
asterisk -rx "module show like opus"

Каждая команда должна вернуть строку с модулем и статусом Running. Если Opus нет, не паникуйте: рабочая схема получится и с ulaw или alaw, просто CPU и пропускная способность будут хуже.

Теперь HTTP-сервер. WebRTC в Asterisk приходит именно через него: встроенный http.conf поднимает и обычный порт, и защищённый. Минимальный рабочий вариант:

[general]
enabled=yes
bindaddr=0.0.0.0
bindport=8088
tlsenable=yes
tlsbindaddr=0.0.0.0:8089
tlscertfile=/etc/asterisk/keys/asterisk.crt
tlsprivatekey=/etc/asterisk/keys/asterisk.key

После перезагрузки проверьте asterisk -rx "http show status". В выводе должен быть HTTPS-сервер на порту 8089 и включённый URI /ws. Если /ws нет, значит не загрузился res_http_websocket, и никакие сертификаты вам не помогут. Порт 8088 без TLS нужен лишь для проверок на самом сервере; наружу его не публикуйте, браузер всё равно потребует wss.

Сертификат — главное место, где у меня ломалось чаще всего. В исходниках Asterisk лежит скрипт contrib/scripts/ast_tls_cert, он делает самоподписанный сертификат, и для тестов этого хватает. Следите за ключом: параметр -b 2048 работает начиная с версий 13.32.0, 16.9.0 и 17.3.0; старые версии создавали ключи в 1024 бита, а свежий OpenSSL их отвергает с ошибкой «key too small». Но боевой вариант другой. Самоподписанный сертификат браузер отвергает молча: страница телефона грузится, кнопка «Позвонить» нажимается, а в консоли разработчика лишь безликий WebSocket error. Для боя берите доверенный сертификат Let's Encrypt на имя pbx.example.com, копируйте его в /etc/asterisk/keys и следите, чтобы читать его мог пользователь, под которым работает Asterisk.

Продление сертификата — тоже часть эксплуатации. Let's Encrypt выдаёт сертификаты на короткий срок, и если обновлённые файлы просто лежат в каталоге certbot, а Asterisk читает копию в /etc/asterisk/keys, через три месяца у вас снова «молчит браузер». Я добавляю в certbot deploy-хук, который копирует файлы в /etc/asterisk/keys и перечитывает встроенный HTTP-сервер командой asterisk -rx "module reload http" — полный перезапуск Asterisk и обрыв разговоров ради сертификата не нужны. Чтобы убедиться, что после продления всё жило, достаточно снова выполнить http show status и открыть https://pbx.example.com:8089/ws в браузере: вместо ошибки сертификата вы увидите короткий ответ сервера, и это нормально.

Звонить из браузера через свой Asterisk: WebRTC без облака и без Zoiper — схема
Схема к статье. Открыть схему в полном размере

Как выглядит pjsip.conf для браузерного абонента

Дальше идёт самая приятная часть, потому что в ней почти нет сюрпризов. Для WebRTC нужен свой транспорт типа wss и один набор объектов на каждого абонента: AOR, auth и endpoint. Имена у всех трёх одинаковые, так проще читать конфиг, а различает их строка type. Я пишу так:

[transport-wss]
type=transport
protocol=wss
bind=0.0.0.0

[webrtc-anna]
type=aor
max_contacts=5
remove_existing=yes

[webrtc-anna]
type=auth
auth_type=userpass
username=webrtc-anna
password=ДЛИННЫЙ-СЛУЧАЙНЫЙ-ПАРОЛЬ

[webrtc-anna]
type=endpoint
aors=webrtc-anna
auth=webrtc-anna
dtls_auto_generate_cert=yes
webrtc=yes
context=from-webrtc
disallow=all
allow=opus,alaw

В транспорте wss остальные параметры игнорируются: адрес и порт берутся из http.conf, поэтому поиск «куда прописать 8089» в pjsip.conf — тупик. Для максимальной надёжности перечитайте конфиг (pjsip reload) и проверьте командой pjsip show transports.

Теперь про webrtc=yes. Одна строка включает за вас набор опций, которые иначе пришлось бы писать вручную и в которых легко ошибиться: use_avpf=yes, media_encryption=dtls, dtls_verify=fingerprint, dtls_setup=actpass, ice_support=yes, media_use_received_transport=yes и rtcp_mux=yes. Раньше все эти строки торчали в каждом endpoint и съезжали при копировании. Теперь их нет, и это хорошо; запомните только, что при поиске причины «почему нет звука» вы смотрите именно на эти умолчания, а не на ваш конфиг.

Пароль. В документации Asterisk есть учебный пример клиента webrtc_client с готовым паролем. Использовать его в интернете нельзя, и я говорю это потому, что видел такие пароли в проде на третий день после запуска. Длинный случайный пароль, не короче 20 символов, генерируйте менеджером паролей и храните в хранилище секретов, а не в письме менеджеру. Параметр max_contacts=5 означает, что один логин может одновременно держать до пяти регистраций (ноутбук, второй браузер, телефон); remove_existing=yes при превышении лимита вытесняет старые регистрации, и сотрудник не остаётся «заблокированным» с призраком вчерашней вкладки.

Кодеки здесь важнее, чем кажется. Порядок такой: сначала disallow=all, затем перечисление разрешённых, в порядке предпочтения. Для браузера Opus — первый выбор. Второй зависит от транка. Для российских операторов обычно ходит alaw, и логично писать allow=opus,alaw, но проверьте, что оператор действительно отдаёт именно alaw, а не только ulaw. Если у клиента Opus, а у транка alaw, Asterisk будет перекодировать на лету, и каждый такой звонок стоит процессорного времени. Для шести-восьми параллельных разговоров на обычном сервере это не заметно, для шестидесяти уже считается. Типовые ошибки с кодеками разбирает статья пять ошибок в кодеках, которые ломают звонки, перечитайте её перед запуском.

Пароль из примера документации — это не пароль, а приглашение. В интернете такая запись регистрируется чужими скриптами за считанные часы, а потом звонит в дорогие направления за ваш счёт.

NAT, ICE и фаервол: здесь ломается почти всё

Типичная картина: регистрация зелёная, сотрудник нажимает «Позвонить», слышит гудки, собеседник отвечает, и... тишина. Или в одну сторону слышно, в другую нет. Первый раз я два часа искал ошибку в диалплане, и это были лучшие два часа, потраченные не на то. Причина была в медиа. SIP-сигнализация ходит по wss через уже установленное соединение, ей NAT не мешает. Голос идёт отдельно, по UDP, и вот здесь начинается самое интересное.

За медиа в WebRTC отвечает ICE: браузер и сервер обмениваются списком адресов, по которым до них можно достучаться, и выбирают работающую пару. Если Asterisk сидит в офисе за NAT, а менеджер дома за другим NAT, нужен STUN, чтобы стороны узнали свои внешние адреса, а при симметричном NAT — ещё и TURN. В rtp.conf это выглядит так (формат значений и поддержку параметров проверьте в своей версии):

[general]
rtpstart=10000
rtpend=20000
icesupport=yes
stunaddr=stun.example.com:3478
; turnaddr=turn.example.com
; turnport=3478

Диапазон rtpstart и rtpend по умолчанию 10000–20000. Он должен быть открыт для UDP на фаерволе и проброшен на сервер. Если вы пробросили 5060 и 8089, а про диапазон забыли, получите ровно тот самый звук в одну сторону. Подробнее о том, как проверять путь медиа от клиента до сервера, мы писали в материале диагностика RTP и NAT в Asterisk.

Сценарий, который всех удивляет: звонок установился, собеседник ответил, а через 30–40 секунд всё рвётся. Это не «Asterisk устал». У обычного SIP за NAT в таком случае первым делом ищут потерянный ACK, но у WebRTC сигнализация ходит по уже установленному wss-соединению, и эта причина отпадает. Остаётся медиа: ICE не нашёл рабочую пару адресов, и Asterisk завершает звонок, когда проверка связности проваливается; реже виноват rtp_timeout, если вы сами задали его в endpoint. Диагностика одинаковая: включаем pjsip set logger on и rtp set debug on, делаем тестовый звонок и смотрим, какие кандидаты ICE попали в SDP и куда реально летят пакеты. Если там только приватные адреса клиента — вот и ответ. Отдельный разбор такого поведения есть в статье почему звонки в очереди падают через 30 секунд, там та же логика на другом примере.

Теперь, что обязательно открыть и что нельзя:

# нужно: TCP 8089 (wss), UDP 10000-20000 (RTP), UDP 3478 (STUN/TURN, если свой)
# не публиковать: TCP 8088 (http без TLS)
nft list ruleset | grep -E '8089|8088|10000'
asterisk -rx "pjsip set logger on"
asterisk -rx "rtp set debug on"

Порт 3478 в списке встречается потому, что это типовой порт STUN; если вы используете внешний STUN-сервис, открывать его у себя не нужно. И последнее: браузер принимает только wss. Подключение ws без TLS заблокирует и Chrome, и Edge, поэтому «а давайте для начала без сертификата» не работает вообще, как ни искушает.

Если до рабочего WebRTC у вас остановка на сертификате или звуке в одну сторону, мы разберём ваш Asterisk, настроим wss, ICE и фаервол и проверим звонки из домашних сетей. Обсудить задачу
Цифры и версии: NAT, ICE и фаервол: здесь ломается почти всё — схема
Цифры и версии: NAT, ICE и фаервол: здесь ломается почти всё. Открыть схему в полном размере

Кейс: логистическая компания «Три Моста»

К нам пришла логистическая компания «Три Моста»: 27 рабочих мест, из них 8 менеджеров на удалёнке. Asterisk 20 на Debian 12 стоял в офисе за NAT, внешний SIP-транк подключали давно и никому не показывали. Менеджеры звонили через Zoiper на личных ноутбуках, и, по словам директора, половина «не работала после обновления Windows»: кто-то терял регистрацию, у кого-то пропадал микрофон, один сотрудник полгода звонил через мобильный и присылал чеки на возмещение. Задача звучала просто: дайте им звонить из браузера и перестаньте носить софтфон на каждый ноутбук.

Мы уложились в два рабочих дня. В первый день подняли http.conf с TLS на 8089, завели wss-транспорт, создали по одному endpoint на сотрудника и выпустили доверенный сертификат. Именно здесь случилась первая неприятность: на тестовом стенде был самоподписанный сертификат от скрипта, и браузер молча отверг wss. Страница веб-телефона открывалась, кнопка была живая, а звонок не стартовал, и в консоли только WebSocket error. Мы потратили полтора часа, прежде чем открыли https://pbx.example.com:8089/ws напрямую и увидели предупреждение. Поставили сертификат Let's Encrypt, и регистрация появилась с первой попытки.

Второй день ушёл на NAT. Звонки из офиса шли идеально, а вот у двух удалённых сотрудников собеседник не слышал их голос. Виноваты были пробросы: порт 8089 открыли, а UDP-диапазон нет. Мы сузили диапазон RTP до 10000–10199, чего хватало с запасом на 6 одновременных звонков, пробросили его на фаерволе и указали STUN в rtp.conf. TURN не понадобился: все восемь удалённых сотрудников прошли проверку из домашних сетей. Кодеки: браузер говорит Opus, оператор — alaw, перекодировку делает Asterisk, и нагрузка на сервер от шести одновременных разговоров заметно не выросла.

Итог через неделю. Ни одной заявки «не работает софтфон после обновления», регистрация держится, пиковая нагрузка — до 6 одновременных звонков, а на каждый новый ноутбук теперь нужна ссылка и логин, а не установка программы. Директор говорил, что отдельным плюсом оказалось другое: больше не нужно просить сотрудников «обновите программу», и подключение нового менеджера занимает минут десять. Мы не обещаем, что у вас получится так же быстро, у «Трёх Мостов» была чистая сеть и аккуратный Asterisk, но порядок работ у вас будет тот же.

Сертификат, который браузер не принимает, не пишет в консоль «сертификат плох». Он пишет «WebSocket error» и молчит. Проверяйте https://pbx.example.com:8089/ws руками до того, как начнёте искать проблему в конфиге.

Безопасность: что закрыть до выхода в интернет

Открытый порт 8089 в интернет — это приглашение, и первые гости приходят через сутки. Боты ищут Asterisk и пробуют перебирать пароли на регистрацию. WebRTC-эндпоинты тут не исключение, и защита нужна та же, что для обычного SIP: fail2ban или правила nftables на неудачные регистрации, ограничение по странам или подсетям, где это возможно. Я рекомендую начать с настройки fail2ban для защиты Asterisk от SIP-атак: принцип там общий, нужно только подобрать лог-фильтр под ваш вывод.

Дальше идёт то, что чаще всего забывают. Отдельный контекст диалплана для браузерных абонентов: например, from-webrtc, в котором нет выхода на международные направления и нет лишних внутренних номеров. Лимит max_contacts, чтобы чужой скрипт не плодил регистрации. Ограничение исходящих звонков по числу и по направлениям: про это у нас отдельный материал ограничения исходящих звонков против мошенничества. И, конечно, длинные пароли, у каждого сотрудника свой. Не выставляйте http.conf без TLS в интернет ни под каким предлогом: пароли и SIP-сообщения полетят открытым текстом, а в 2026 году это уже не «небрежность», а ошибка.

Если политика безопасности в компании вообще не описана, начинайте не с Asterisk, а с общей базовой информационной безопасности: кто и откуда ходит, где хранятся пароли, кто получает уведомление о неудачных входах. Это скучно, но именно скучные вещи отличают телефонию, которая работает, от телефонии, которая однажды выставила счёт на сотни тысяч рублей за одну ночь звонков в дальние направления.

Перед запуском я прохожу короткий список. Сертификат доверенный и продлевается автоматически. Порт 8088 закрыт снаружи. RTP-диапазон проброшен и совпадает с rtp.conf. У каждого абонента свой пароль и свой логин. Диалплан для браузерных абонентов отделён. Работает fail2ban. Если какой-то пункт не отмечается, запуск откладывается: это не паранойя, а те десять минут, которые экономят выходные.

Частые вопросы

Какая версия Asterisk нужна для WebRTC?

Нужен chan_pjsip и Asterisk 15.5 или новее. В 2026 году разумно использовать LTS-ветки 20 и 22. Список модулей проверьте командой module show like в своей версии.

Можно ли обойтись самоподписанным сертификатом?

Для теста можно: откройте https://pbx.example.com:8089/ws в браузере и примите исключение. Для работы нужен доверенный сертификат, например Let's Encrypt, иначе браузер отвергает wss молча.

Почему регистрация есть, а звука нет в одну сторону?

Чаще всего это ICE и NAT: не настроен STUN или TURN либо закрыт UDP-диапазон RTP из rtp.conf. Проверьте rtpstart и rtpend, включите rtp set debug on и посмотрите, куда идут пакеты.

Какие кодеки указать для WebRTC-абонента?

Сначала disallow=all, затем opus и тот кодек, который отдаёт ваш оператор: для России обычно alaw. Перекодирование opus и alaw нагружает процессор, поэтому проверьте нагрузку на реальных звонках.

Какие порты нужно открыть на фаерволе?

TCP 8089 для wss и UDP-диапазон RTP из rtp.conf (по умолчанию 10000–20000). Порт 8088 без TLS в интернет публиковать нельзя. Для STUN или TURN добавляются их порты, если они на вашем сервере.

Столкнулись с похожей задачей? Обращайтесь — решим

Если у вас происходит что-то из описанного в этой статье — или любая другая проблема с ИТ-инфраструктурой, — обращайтесь в любое время. Мои специалисты и я лично разберём ситуацию, найдём настоящую причину и доведём до решения.

Возьмёмся и за разовую задачу, и за постоянное обслуживание. Первичная консультация — бесплатно и без обязательств.

📞 +7 903 729-62-41 ✈ Telegram @ITfresh_Boss

С уважением, Семёнов Евгений Сергеевич, директор «АйТи Фреш» — IT-аутсорсинг для компаний до 50 рабочих мест, 15+ лет практики

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи
АйТи-Фреш (ООО «АЙТИ-ФРЕШ») · г. Москва, Щёлковское шоссе, д. 92, корп. 7 · +7 903 729-62-41 · info@itfresh.ru · Пн–Пт 9:00–19:00