FreePBX в Docker: SIP есть, а звука нет?
Москва, Щёлковское шоссе, д. 92, корп. 7 · Пн–Пт 9:00–19:00 · +7 903 729-62-41
АйТи Фреш
Сети и VPN

Как найти обрыв SIP и RTP в FreePBX внутри Docker

Автор: , директор ООО «АйТи-Фреш» · · ~11 мин чтения
Раздельные пути SIP и RTP при диагностике звука в FreePBX Docker
Рабочий SIP ещё не означает, что RTP донёс звук.

Если регистрация SIP проходит, а входящий вызов молчит или звук есть только в одну сторону, проверяйте по цепочке: сигнализацию, адреса в SDP, RTP-порты и публикацию портов Docker. Я покажу, как отделить сетевой сбой от ошибки FreePBX и какие настройки сверить до перезапуска.

Сначала отделяю SIP от звука

Я начинаю не с перезапуска, а с вопроса: вызов вообще устанавливается? Если телефон или транк зарегистрирован, но собеседник не слышит речь, это ещё не «сломался FreePBX». SIP отвечает за установление и управление вызовом, а голос передаётся отдельным медиапотоком RTP. Один путь может работать, пока второй упирается в firewall, неверный адрес или непубликованный UDP-порт. Поэтому фраза «регистрация зелёная» сообщает только часть картины.

В моих проектах полезнее всего взять один контролируемый тест: позвонить с внутреннего номера на заранее известный маршрут, записать время и отметить, кто кого слышит. Оба направления важны. Тишина в обе стороны, односторонний звук и вызов, который даже не устанавливается, ведут к разным участкам диагностики. Для сверки сетевого пути я отдельно смотрю настройки обслуживания IT-инфраструктуры, а в статье разбираю именно сетевой диагноз FreePBX в контейнере.

Если вызовы пропадают именно после перезапуска сервера, это отдельный сценарий с адресацией и восстановлением сетевой конфигурации; в каталоге есть разбор пропажи звонков после перезагрузки Asterisk в Docker. Здесь я рассматриваю другой симптом: сигнализация проходит или частично работает, а медиа не доходит. Такой фокус экономит время: не приходится чинить рестарт, когда проблема в RTP.

Не считайте статус регистрации доказательством, что голосовой трафик проходит.
Схема раздельной проверки SIP и RTP в FreePBX Docker
Проверяйте установление вызова и звук как два потока.

Что проверяю в настройках NAT

В Docker bridge контейнер получает собственный адрес в своей сети. Docker публикует заданные порты на адресах хоста и использует маскарадинг для исходящего доступа; удалённые устройства обычно видят внешний адрес хоста, а не контейнера. Это штатная модель, а не автоматически поломка. Сбой возникает, когда адрес, который Asterisk сообщает в SIP или SDP, не соответствует маршруту, доступному другой стороне, либо входящие пакеты не попадают в контейнер. Документация Docker прямо разделяет внутреннюю сеть bridge и опубликованные порты.

Для PJSIP у Asterisk есть параметры транспорта local_net, external_signaling_address и external_media_address. Первый описывает локальную сеть, второй относится к SIP-сигнализации, третий — к адресу медиа в RTP/SDP. Значения нужны только при соответствующей NAT-схеме: внешний адрес и подсеть должны совпадать с реальной топологией. Не надо вставлять параметры вслепую в случайный pjsip.conf: FreePBX управляет генерируемой конфигурацией, поэтому сначала ищите соответствующие поля в установленной версии интерфейса и проверяйте, что именно сгенерировал Asterisk.

В базе знаний отдельно подтверждены все три настройки PJSIP и их назначение; документация Asterisk поясняет, что переписывание адреса SDP происходит при определённых условиях — адрес назначения вне local_net, а адрес медиа внутри локальной сети. Это не универсальное «включить NAT». Для диагностики сравните внешний адрес, локальную подсеть и адрес в SDP тестового вызова. Если значения уже согласованы, дальнейшее переключение NAT наугад только добавит неизвестных.

Сравнение внутренних и внешних адресов NAT для SIP и RTP
Адрес в SDP должен соответствовать доступному маршруту.

Порты: не открываю всё подряд

Порт 5060 часто используют для SIP по UDP или TCP, а 5061 часто назначают SIP поверх TLS. Это распространённые значения, но не обязательная пара для любой установки: транспорт и порт определяются конфигурацией Asterisk, транка и телефонов. В исходной статье предлагалось открыть оба порта без выяснения протокола — это плохая инструкция. Открывать нужно тот транспорт, который действительно настроен, и только от нужных источников, если провайдер публикует свои диапазоны адресов.

Для RTP важен не мифический универсальный диапазон, а фактический диапазон конкретной установки. В FreePBX его смотрят в SIP Settings; в Asterisk базовая настройка RTP задаётся в rtp.conf параметрами rtpstart и rtpend. В образце конфигурации Asterisk указан диапазон 10000–20000, а значения по умолчанию в том же файле — 5000–31000. В сборке FreePBX настройки могут отличаться, поэтому ориентируйтесь на её фактический диапазон: firewall и Docker должны ему соответствовать. Несовпадение даже на один слой даёт знакомый результат: SIP-сессия установилась, а звук пропал.

Проверяю настройки с обеих сторон проброса: firewall хоста разрешает нужный входящий UDP, а Docker публикует тот же порт контейнера на ожидаемом адресе хоста. docker port <имя_контейнера> показывает опубликованные порты для bridge-сети; ss -lunp помогает увидеть UDP-сокеты на хосте, но сам по себе не доказывает, что внешний трафик доходит. Для режима host логика публикации портов другая: Docker игнорирует -p, потому что контейнер разделяет сетевой стек хоста. Один и тот же чек-лист для обоих режимов не годится. Разрешение порта в панели провайдера также не заменяет проверку локального firewall: пакет должен пройти все применимые фильтры. Если на пути есть маршрутизатор перед Docker-хостом, проверьте его перенаправление отдельно. Слои проверяются по фактическому маршруту, а не по одному зелёному индикатору.

Не проверяйте UDP-порт только внешним TCP-сканером: это другой транспорт.

Bridge или host: решение зависит от схемы

Bridge даёт контейнеру отдельный сетевой адрес и требует явной публикации портов, если к службе должны обращаться извне. Это удобно для изоляции и обычно понятнее в Compose, но для телефонии нужно согласовать SIP, RTP, NAT и правила firewall. Проброс 5060 не означает, что автоматически опубликован весь RTP-диапазон. Нельзя сказать, что bridge ломает звонки: он просто добавляет места, где конфигурации должны совпасть.

Host использует сетевой стек машины-хоста и не создаёт отдельный адрес контейнера. По документации Docker в этом режиме публикация -p не применяется, а сетевое пространство контейнера не изолировано от хоста. Это иногда упрощает работу с большим количеством RTP-портов, однако не исправляет неверный SDP или ошибочную NAT-настройку. Я выбираю режим только после схемы портов, оценки изоляции и требований образа FreePBX. «Поставим host, и точно заработает» — не технический план.

Перед сменой режима фиксирую текущую конфигурацию Compose и правила firewall, затем сверяю, какие порты и интерфейсы реально используются. Если менять сетевой режим в рабочее время без окна и отката, легко получить уже не односторонний звук, а полностью недоступную АТС. При этом перезапуск нужен не после любого изменения: сначала выясняю, применяет ли конкретная настройка FreePBX reload, просит перезапустить Asterisk или требует пересоздания контейнера. Это разные действия.

Команды и наблюдения, которые дают ответ

Сначала смотрю состояние регистрации и транспорта из CLI Asterisk: docker exec <контейнер> asterisk -rx "pjsip show registrations" и docker exec <контейнер> asterisk -rx "pjsip show transports". Для контактов и endpoint в зависимости от версии пригодится docker exec <контейнер> asterisk -rx "pjsip show endpoints". Старую команду sip show peers нельзя выдавать как универсальную: она относится к драйверу chan_sip, тогда как современные установки часто используют chan_pjsip. Если CLI отвечает, что команда неизвестна, это подсказка о драйвере, а не повод копировать случайную команду из форума.

Затем проверяю прохождение пакетов на хосте во время тестового звонка, например sudo tcpdump -ni any udp. Такая команда покажет UDP-трафик, но не объяснит автоматически его смысл: сопоставьте время вызова, адреса и порты с настройками транка и контейнера. Если в дампе виден SIP INVITE, а ожидаемых RTP-пакетов нет, ищите точку потери на медиапути и уточняйте, не использует ли система другой диапазон или транспорт. Если пакеты доходят до хоста, но не до контейнера, исследуйте публикацию портов и фильтрацию Docker/firewall.

Наконец, смотрю логи Asterisk и содержимое SDP в пределах диагностируемого вызова. Для PJSIP важно увидеть адрес и порт, куда абоненту предложено слать медиа; затем проверить, приходит ли RTP от удалённой стороны и уходит ли ответный поток. Не публикуйте полный дамп SIP: в нём могут оказаться номера телефонов и данные авторизации. Для разбора достаточно обезличенных строк, временной отметки и пары адрес/порт из тестового вызова.

Чек-лист поиска потери SIP или RTP в FreePBX Docker
Идите от одного вызова к конкретному участку сетевого пути.

Как закрепляю исправление

Когда причина найдена, меняю один слой за раз: сначала исправляю публикацию или правило firewall, затем проверяю настройки NAT и только после этого повторяю тестовый вызов. Так понятно, какое действие изменило результат. После каждого шага фиксирую направление вызова и слышимость в обе стороны. Если одновременно сменить сетевой режим, диапазон RTP и настройки транспорта, успешный тест не покажет, какое из изменений было необходимым. А следующий сбой придётся разбирать с нуля.

В условном разборе из исходной статьи описывался сбой после перезапуска и внутренний адрес контейнера. Я не выдаю приведённые там 15 минут, 90 % причин, конкретный IP или имя сети за измеренные факты: подтвердить их нельзя. Для реального случая нужно собрать схему, версию образа, режим сети и настройки портов. Сам факт запуска FreePBX в контейнере не доказывает, что одинаково настроены все сборки: образ, версия и файлы Compose меняют детали. Поэтому для диагностики нужны фактические параметры установленной системы, а не чужой пример конфигурации.

После исправления сохраняю схему сетей, перечень опубликованных портов, RTP-диапазон, локальные сети и способ проверки вызова. В мониторинге отдельно отслеживаю регистрацию транка и доступность маршрута; наличие регистрации не подменяет проверку качества аудио. А перед обновлением образа повторяю короткий тест входящего и исходящего вызова. Здесь всё скучно, зато после обновления не приходится выяснять на слух, работает ли телефония.

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

Почему SIP зарегистрирован, а звука нет?

Регистрация подтверждает SIP-обмен, но голос идёт по RTP. Проверьте адрес и порт в SDP, фактический RTP-диапазон и прохождение UDP через firewall и Docker.

Нужно ли всегда открывать UDP 5060 и 5061?

Нет. Откройте настроенный SIP-транспорт и порт. 5060 часто используют для UDP/TCP, 5061 — для TLS, но конфигурация может отличаться.

Какой диапазон RTP у FreePBX?

Сверьте диапазон с SIP Settings и конфигурацией Asterisk в rtp.conf. Часто встречается 10000–20000 UDP, но это значение нельзя считать обязательным для каждой системы.

Как проверить регистрацию в PJSIP?

В CLI Asterisk используйте `pjsip show registrations` и `pjsip show endpoints`. Команда `sip show peers` относится к chan_sip и не универсальна для PJSIP.

Что выбрать для телефонии: bridge или host?

Bridge требует публикации нужных портов, host использует сетевой стек хоста и игнорирует публикацию `-p`. Выбор зависит от схемы, изоляции и требований образа.

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

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

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

📞 +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