MAATRIX / Блог / FreePBX в бою: обновления, транки и внезапная односторонняя слышимость

FreePBX в бою: обновления, транки и внезапная односторонняя слышимость

MAATRIX

Первую неделю после установки FreePBX всё звонит, как задумано: внутренние номера соединяются, транк регистрируется, IVR отвечает голосом, который вы сами записали в мастере. Проходит полгода — и внезапно один из менеджеров жалуется, что клиент его слышит, а он клиента нет; обновление модуля через веб-интерфейс подвешивает очередь звонков; а провайдер транка вдруг требует другой формат Caller ID, о котором никто не предупреждал. FreePBX — графическая надстройка над Asterisk, и её проблемы редко лежат в самом голосовом движке: он как раз работает стабильно. Ломается тонкий слой вокруг — модули, обновляющиеся независимо друг от друга, транки с живым провайдером со своей политикой, и сеть с NAT, которая рано или поздно даёт о себе знать. Разберём, что именно стреляет через несколько месяцев эксплуатации и как проверять систему, не дожидаясь звонка от рассерженного клиента.

Почему FreePBX стабилен внутри и хрупок на границах

Внутри FreePBX два слоя, которые стоит держать в голове отдельно. Первый — сам Asterisk: движок, который устанавливает и маршрутизирует звонки, работает с диалпланом, транскодирует кодеки. Это давно обкатанный код, и если сервер не перегружен и диски не забиты, он способен месяцами работать без единого перезапуска. Второй слой — сама FreePBX: PHP-приложение с базой MySQL/MariaDB, которое генерирует конфиги Asterisk (extensions_additional.conf, pjsip_additional.conf и десятки других) из настроек, введённых через веб-интерфейс, и раскладывает их через fwconsole reload.

Проблема в том, что эти два слоя не всегда синхронизированы идеально. Модуль FreePBX можно обновить, а движок Asterisk снизу останется прежней версии — и наоборот, если вы вручную обновляли Asterisk, часть модулей может ожидать директивы, которых в новой версии уже нет или которые переименованы. К этому добавляется третий источник нестабильности — сеть и SIP-транк, то есть то, что происходит за пределами вашего сервера, но напрямую влияет на слышимость звонка. Дальше разберём каждый из этих трёх источников отдельно, потому что диагностика для них принципиально разная.

Если вы ещё выбираете между самостоятельно поднятым Asterisk/FreePBX и облачной телефонией «за место», экономика этого решения — отдельный вопрос; здесь же речь про то, что происходит с уже развёрнутой FreePBX через несколько месяцев боевой работы, независимо от исходного выбора.

Обновления модулей: откуда берётся несовместимость

FreePBX построена как набор независимых модулей (Core, PJSIP, Voicemail, Queues, IVR, System Admin и десятки платных и бесплатных дополнений), каждый со своей версией и своим циклом обновлений через Module Admin (fwconsole ma). На первый взгляд это удобно — можно обновить один модуль, не трогая остальные. На практике здесь и кроется источник поломок через полгода-год:

  • Модули обновляются не синхронно. Если репозиторий EDGE (тестовые сборки) включён хотя бы для одного модуля, а остальные сидят на Stable, между ними накапливается рассогласование структур базы или API-вызовов. Симптом обычно тихий: страница модуля в UI работает с ошибкой в консоли браузера, а не падает сервис целиком.
  • Обновление ядра тянет новую схему базы, а самописный модуль её не ждёт. Миграции при обновлении core-модуля иногда переименовывают таблицы или столбцы. Кастомный модуль, написанный под конкретную интеграцию, продолжает обращаться к старой структуре и начинает падать с ошибками PHP, видимыми только в логе.
  • Обновление Asterisk «под капотом» меняет поведение chan_pjsip. Переход между версиями (например, между соседними LTS-ветками) может менять значения по умолчанию для директив PJSIP или формат событий AMI/ARI, от которых зависят модули очередей и отчётности. Звонки продолжают идти, но статистика очереди или CDR начинает съезжать.
  • Отложенное обновление превращается в рывок. Если модули не обновлялись полгода, разрыв между установленной и актуальной версией растёт, и обновление за один проход тянет сразу несколько миграций, каждая из которых может конфликтовать с правками, внесёнными в обход GUI (прямая правка .conf-файлов, кастомные диалпланы в extensions_custom.conf).

Проверить состояние модулей и обновить их с логом изменений:

fwconsole ma list
fwconsole ma listonline
fwconsole ma upgradeall
fwconsole reload

Перед upgradeall на боевой системе стоит взять снапшот сервера или как минимум резервную копию через модуль Backup — не потому что обновление обязательно всё сломает, а потому что откат вручную из разных версий модулей — задача на порядок дольше, чем восстановление снапшота. Если сервер стоит на VPS, снапшот перед плановым обновлением обычно занимает пару минут и снимает большую часть риска.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер для АТС

SIP-транки: что провайдеры меняют без предупреждения

Транк — самое живое место конфигурации FreePBX, потому что на другом конце не ваш код, а инфраструктура стороннего оператора связи, которая меняется по его собственному графику. За полгода-год эксплуатации типично всплывают такие вещи:

  • Провайдер меняет требования к Caller ID или формату номера. Часть операторов ужесточает валидацию исходящего номера (строго E.164, отказ от коротких внутренних номеров в заголовке From) без предупреждения — звонки начинают срываться с 403 Forbidden на конкретных направлениях, а не повсеместно.
  • Меняются IP-адреса или диапазоны для регистрации/сигнализации. У крупных провайдеров адреса шлюзов периодически обновляются (балансировка нагрузки, новые дата-центры). Если в firewall или в самом транке жёстко прописан IP вместо доменного имени, транк молча перестаёт регистрироваться после смены адреса.
  • Меняется политика по кодекам. Провайдер может отключить кодек (например, G.729 из-за лицензии) или начать требовать другой первым в списке. Если настройки транка не пересмотрены, согласование (SDP negotiation) срывается либо проходит с кодеком, который сервер вынужден транскодировать — незаметная деградация качества и лишняя нагрузка CPU.
  • Меняется интервал регистрации. Часть провайдеров снижает допустимую частоту REGISTER-запросов и банит IP при слишком агрессивном qualify в PJSIP — транк то падает, то поднимается сам по себе без видимой причины.

Быстрая диагностика состояния транка прямо из консоли Asterisk:

asterisk -rx "pjsip show registrations"
asterisk -rx "pjsip show endpoint имя_транка"
asterisk -rx "pjsip show contacts"

Если регистрация в статусе Rejected или Unregistered, а конфиг не менялся — первым делом проверяйте изменения на стороне провайдера (статус-страница, письмо от техподдержки, changelog в личном кабинете), а не свою конфигурацию: часто это единственная переменная, которая реально изменилась. Полезно завести отдельный лог именно транковых инцидентов — дата, что случилось, что оказалось причиной — потому что у части провайдеров такие изменения повторяются с определённой регулярностью (например, ежегодная плановая миграция инфраструктуры).

Односторонняя слышимость: классика NAT и RTP

Это, пожалуй, самая частая жалоба на боевой FreePBX спустя несколько месяцев — «клиент меня не слышит» или «я слышу клиента, а он меня нет». Причина почти всегда одна и та же: сигнализация (SIP) и медиапоток (RTP) проходят по-разному через NAT, и без явных настроек Asterisk путает, куда на самом деле отправлять голос.

SIP-заголовки содержат приватный IP-адрес сервера или телефона, а не тот публичный адрес, через который реально идёт трафик, если сервер стоит за NAT (например, у облачного провайдера с приватной сетью и внешним IP через 1:1 NAT, или если внутренние SIP-телефоны сидят за офисным роутером). Если Asterisk доверяет заголовкам буквально, он пытается слать RTP-пакеты на приватный адрес, который снаружи недостижим — и получается ровно ситуация с односторонней слышимостью: одна сторона своей исходящий поток слышит, а входящий до неё не доходит.

Ключевые настройки, которые нужно проверить в PJSIP (в FreePBX это разделы Settings → Asterisk SIP Settings и настройки конкретного транка/расширения):

external_media_address = <публичный IP или FQDN сервера>
external_signaling_address = <публичный IP или FQDN сервера>
local_net = 192.168.0.0/16
local_net = 10.0.0.0/8
local_net = 172.16.0.0/12

local_net перечисляет диапазоны, которые Asterisk считает «внутренними» — если звонок приходит из такого диапазона, PJSIP не подменяет адрес в SDP, потому что предполагает, что стороны и так в одной сети. Если сервер стоит на VPS с публичным IP напрямую (без NAT со стороны хостинга), этот блок обычно не нужен вовсе — типичная ошибка на таких серверах, наоборот, включить NAT-режим там, где он не требуется, и получить обратную проблему с медиапотоком.

Отдельно стоит проверить диапазон RTP-портов и то, что он реально открыт на файрволе — Responsive Firewall в FreePBX иногда закрывает диапазон RTP для «незнакомых» IP даже после того, как SIP-сигнализация уже прошла:

# /etc/asterisk/rtp.conf
rtpstart=10000
rtpend=20000
firewall-cmd --list-ports
iptables -L -n | grep 10000

Живая диагностика конкретного звонка с зависшим медиапотоком:

asterisk -rx "rtp set debug on"
asterisk -rx "pjsip set logger on"
tcpdump -i any -n udp portrange 10000-20000 -w /tmp/rtp.pcap

Если tcpdump показывает, что RTP-пакеты идут только в одну сторону, а вторая сторона молчит — почти наверняка проблема на стороне сети (файрвол блокирует входящий диапазон, симметричный NAT у клиента переписывает исходящий порт не так, как ожидает сервер) а не в конфигурации диалплана. Общая механика того, почему NAT ломает именно двустороннее соединение, разобрана подробнее в статье про то, как работает NAT и почему устройства не видят друг друга напрямую — там же объясняется, зачем вообще нужны STUN и hole punching, которые лежат в основе многих SIP-настроек NAT traversal.

Отдельный неприятный случай — когда проблема повторяется стабильно у одного конкретного удалённого сотрудника или у одного офиса, а у всех остальных всё в порядке. Здесь чаще всего работает не общая настройка NAT на сервере, а двойной NAT или CGNAT именно на стороне этого клиента — диагностика такого случая (и почему сервер тут почти всегда ни при чём) разобрана в статье про двойной NAT у одного клиента: подход применим и к SIP-телефонии почти без изменений, только вместо видеозвонка ломается голос.

Что ещё копится и стреляет через полгода

Кроме модулей, транков и NAT есть набор менее очевидных вещей, которые деградируют тихо и линейно во времени, а не одномоментно:

  • Истекает TLS-сертификат для веб-интерфейса или SIP over TLS. Если автопродление через модуль Certificate Manager перестало срабатывать (сменился DNS, истёк challenge-метод Let's Encrypt), интерфейс администрирования начинает выдавать предупреждение браузера, а телефоны на TLS-транспорте — вовсе перестают регистрироваться.
  • Растёт база CDR и хранилище записей разговоров. Если включена запись всех звонков, а ротация и архивация не настроены, /var/spool/asterisk/monitor и таблица CDR в MySQL растут месяцами без внимания — а потом сервер упирается в лимит диска в самый неподходящий момент. Если запись разговоров критична для бизнеса (например, для колл-центра или медцентра), стоит заранее продумать хранение отдельно от самого голосового движка — этот кейс на примере своей АТС разобран в статье про запись разговоров с пациентами на своём сервере.
  • Fail2ban банит легитимных пользователей. Джейлы freepbx-* и asterisk-* защищают от брутфорса на SIP, но при агрессивных порогах могут забанить сотрудника, у которого телефон несколько раз подряд неудачно переподключился после смены Wi-Fi — итог похож на «пропали звонки», хотя причина в блокировке по IP.
  • Backup module не проверяется, пока не понадобится восстановление. Резервные копии могут исправно создаваться месяцами и оказаться битыми именно в момент, когда нужны — например, если целевой каталог для бэкапа незаметно кончился по месту.
  • Cron-задачи перестают выполняться после смены системного времени или часового пояса — редкая, но реальная причина, почему voicemail-уведомления или маршрутизация по времени суток вдруг «съезжают».

Проверка сертификата и статуса Fail2ban:

echo | openssl s_client -connect ваш-домен:443 -servername ваш-домен 2>/dev/null | openssl x509 -noout -dates
fail2ban-client status
fail2ban-client status asterisk-iptables
du -sh /var/spool/asterisk/monitor

Регламент: что проверять на боевой FreePBX регулярно

Минимальный набор проверок, который снимает большую часть неожиданностей и укладывается в 20-30 минут в месяц при аккуратной организации:

ПериодичностьЧто проверять
Раз в неделюСтатус регистрации всех транков (pjsip show registrations); список забаненных IP в Fail2ban на предмет ложных срабатываний
Раз в месяцСвободное место на диске и размер /var/spool/asterisk/monitor; успешность последнего резервного копирования (реальная проверка восстановления, а не только «бэкап создан»)
Раз в кварталСрок действия TLS-сертификатов; сверка списка модулей с обновлениями EDGE/Stable на предмет рассогласования версий
После каждого крупного обновления FreePBX/AsteriskТестовый звонок с проверкой двусторонней слышимости на внешний номер и обратно; проверка работы очередей и IVR вручную, а не только по статусу «обновление прошло без ошибок»

Отдельно стоит держать документ (даже простую таблицу) с параметрами каждого транка: у какого провайдера какие требования к Caller ID, кодекам, диапазону IP для регистрации, и дата последнего подтверждённого рабочего состояния. Это единственный способ быстро отличить «у нас что-то сломалось» от «провайдер тихо поменял правила игры» — сама FreePBX такой сводки не ведёт.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер для АТС

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

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

Обновление модулей FreePBX может уронить уже установленные звонки?

Само обновление файлов и fwconsole reload обычно не разрывает активные звонки. А вот перезапуск самого Asterisk (иногда требуется, например, при обновлении ядра) завершает их принудительно — планируйте на не пиковое время.

Почему транк вдруг перестаёт регистрироваться без изменений конфигурации с нашей стороны?

Чаще всего меняется что-то у провайдера: IP шлюза, требования к частоте регистрации, срок действия учётных данных. Проверяйте статус-страницу провайдера раньше, чем перепроверять стабильный месяцами локальный конфиг.

Односторонняя слышимость пропадает и появляется сама по себе — это баг Asterisk?

Практически никогда. Это почти всегда промежуточная сеть — нестабильный NAT на стороне клиента, CGNAT мобильного оператора, файрвол, теряющий состояние для длительных UDP-сессий RTP. Логика диалплана здесь чаще всего ни при чём.

Стоит ли отключать Responsive Firewall, если он мешает диагностике?

Полностью отключать на боевой системе не стоит — это снижает защиту от брутфорса SIP. Для диагностики удобнее временно добавить конкретный IP в доверенные сети, а не выключать защиту целиком.

Как понять, что причина в кодеке, а не в NAT?

Если голос не идёт совсем в одну сторону — почти всегда NAT/маршрутизация RTP. Если идёт, но с искажениями и обрывами — стоит проверить согласование кодеков и лишнее транскодирование, нагружающее CPU.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →