PJSIP в Asterisk: почему вызов получает отказ
АйТи Фреш
Серверы и инфраструктура

Как найти причину отказа PJSIP в Asterisk

Автор: , директор ООО «АйТи-Фреш» · · ~14 мин чтения
Телефонный вызов PJSIP остановился на проверке endpoint и маршрута
Ищите первый сломанный этап вызова

Если PJSIP зарегистрировал телефон, это ещё не значит, что Asterisk разрешит ему звонить или правильно направит вызов. Я начинаю с направления вызова и SIP-диалога, затем проверяю сопоставление endpoint, нужный auth-объект и маршрут. Так отделяю отказ в идентификации от неверного пароля, транспорта и dialplan.

1. С чего начать, если PJSIP не пропускает вызов

Я сначала фиксирую, кто звонит, куда, и в какую сторону идёт вызов: телефон → Asterisk или Asterisk → оператор. Это не формальность. Для входящего запроса Asterisk должен сопоставить SIP-запрос с endpoint, а для исходящего вызова до оператора могут участвовать отдельные endpoint, маршрут и outbound_auth. Один симптом «звонок не пошёл» скрывает несколько разных цепочек. Если нужно проверить не только один отказ, но и всю офисную телефонию, мы проводим аудит ИТ-инфраструктуры, начиная с журналов и конфигурации.

Подключаюсь к CLI: asterisk -rvvv. Для воспроизведения включаю команды, которые рекомендует руководство Asterisk: core set verbose 4, core set debug 4, pjsip set logger on. Затем делаю один тестовый вызов и записываю точное время, вызывающий и вызываемый номера, направление и ответ SIP. Уровень 4 — ориентир из документации по диагностике, а не магическое число: при необходимости повышаю детализацию, а после проверки возвращаю её к обычной.

В SIP-логе ищу не только финальный код. Важны порядок запросов и ответов, Request-URI, From, To, Call-ID, WWW-Authenticate и Authorization. Пароли и полные значения заголовков перед передачей журнала нужно скрыть: диагностический дамп может раскрыть служебную информацию. Вызов без сопоставленного endpoint и вызов с неверным паролем — разные неисправности, хотя оба заканчиваются отказом. Если нужен общий контекст настройки SIP-транка, пригодится руководство по SIP-транкам.

Не публикуйте SIP-трассу целиком: в ней бывают имена пользователей и данные для проверки авторизации.
Схема пути SIP-вызова через endpoint, auth и dialplan в Asterisk
Проверяйте этапы по порядку

2. Что означают 401 и 403 в SIP-логе

Код 401 сам по себе не доказывает, что пароль неверен. В SIP это может быть запрос сервером аутентификации: удалённая сторона отвечает 401 Unauthorized с WWW-Authenticate, после чего клиент должен повторить запрос с Authorization. Смотрите, появился ли повтор и что ответил сервер затем. Если второй запрос принят, первый 401 был штатным шагом обмена. Если повтор не пришёл или снова получил отказ, проверяйте пользователя, пароль, realm и выбранный digest-алгоритм на той стороне, которая выдала challenge.

403 означает, что запрос запрещён, но по одному коду нельзя назвать причину: решают заголовки, направление, настройки АТС и правила оператора. Если отказ приходит от провайдера на исходящий вызов, локальный пароль телефона может быть вообще ни при чём. Если сам Asterisk отвергает входящий запрос, сначала смотрю, определился ли endpoint и какой механизм сопоставления сработал. Нельзя увидеть 403 и автоматически менять пароль — так легко испортить рабочую регистрацию, не затронув настоящую причину.

Разделяю результат на этапы: запрос дошёл до нужной стороны; endpoint определён; авторизация прошла там, где она действительно требуется; dialplan нашёл контекст и маршрут; удалённая сторона приняла вызов. В логе отмечаю первый этап, на котором цепочка ломается. Это точнее, чем лечить все отказы как «ошибку PJSIP». Я также проверяю, не смешаны ли исходящая регистрация транка и исходящий INVITE: успешный REGISTER подтверждает регистрацию аккаунта, но сам по себе не гарантирует разрешение набрать любой номер.

Если это входящий запрос, ищу в CLI сообщение о том, какой endpoint выбран или почему запрос не сопоставился. Руководство Asterisk отдельно разбирает случай, когда endpoint не найден: входящий SIP-трафик должен быть связан с настроенным endpoint, иначе запрос отклоняется ещё до разговоров о пароле. Проверяю, загружен ли объект, соответствует ли его имя и тип, а если используется сопоставление по адресу — совпадает ли реальный адрес источника с настроенным условием. При NAT фактический адрес на стороне АТС может отличаться от того, который администратор ожидает по схеме; сравниваю с трассой и журналом, не с памятью. Здесь не надо создавать широкое правило на весь интернет ради одного теста. Сначала устанавливаю конкретный источник, затем ограничиваю совпадение нужным адресом или диапазоном и повторяю тест. Если уже выбрана неверная точка входа, исправление секции auth будет только маскировать проблему и усложнит следующий аудит.

Для исходящего запроса к оператору смотрю ответ именно оператора и последующий запрос Asterisk. После challenge должна быть попытка с авторизационными данными; затем оператор либо принимает запрос, либо отвечает новым отказом. Сверяю, какой username отправлен, какой realm указан в challenge, назначен ли объект outbound_auth нужному endpoint и совпадает ли сам endpoint с тем транком, который выбрал dialplan. В нескольких местах может храниться похожее имя пользователя — это не значит, что Asterisk выбрал нужный объект. Также различаю отказ на REGISTER и отказ на INVITE: это разные операции, и успешная регистрация транка не обещает, что оператор разрешил данный номер или формат набора. В журнале сохраняю только безопасные поля, достаточные для сравнения, а не весь дамп с идентификаторами и секретами. Так разговор с оператором поддержки строится вокруг одного конкретного запроса и ответа, а не вокруг фразы «у нас PJSIP не работает».

3. Как проверить endpoint, auth и регистрацию

Сначала смотрю объекты, а не редактирую конфиг наугад: pjsip show endpoints, затем pjsip show endpoint ИМЯ. У входящего SIP-запроса Asterisk должен понять, к какому endpoint его отнести. Сопоставление может идти, например, по имени пользователя или по объекту identify, связывающему endpoint с адресом источника. Если endpoint не выбран, исправление пароля не поможет: проверять надо идентификацию входящего запроса и наличие самого объекта типа endpoint.

Затем проверяю связь endpoint с объектом аутентификации. Для входящей авторизации используется auth; для исходящих запросов к оператору — outbound_auth. Это не взаимозаменяемые поля. В объекте type=auth сверяю username, realm и пароль с настройками той стороны, которая проверяет credentials. В актуальной документации допустимым значением auth_type является digest; userpass и md5 помечены устаревшими и автоматически преобразуются. Поэтому совет «поставьте md5, чтобы заработало» — плохая диагностика и неверное описание современной настройки.

Посмотреть контакты можно командой pjsip show contacts, а детали конкретного AOR — pjsip show aor ИМЯ. Регистрация устройства и маршрут набора — отдельные вещи: наличие contact подтверждает, что Asterisk знает адрес устройства, но не доказывает, что вызов попадёт в правильный контекст и будет разрешён. Для транка отдельно смотрю pjsip show registrations. В найденной мной практике у студии «Еврострой-Мед» телефон с добавочным 101 отображался среди контактов, однако исходящий вызов получал отказ; проблема оказалась не в пароле телефона, а в несовпадении объекта авторизации исходящего транка с параметрами оператора.

Удобно проверять связку объектов сверху вниз, но не превращать её в механическое копирование чужого примера. Endpoint содержит параметры SIP-стороны; AOR описывает контакт или адреса, с которыми она связана; auth хранит данные аутентификации; registration описывает исходящую регистрацию транка, когда она нужна. Не каждая конфигурация использует все эти объекты одинаково: телефон, статический IP-шлюз и транк оператора могут быть настроены разными способами. Сравните имя объекта, на который ссылается endpoint, с фактическим именем секции в конфигурации. Проверьте отсутствие опечаток и дублирующих секций; затем выведите объект в CLI и убедитесь, что загружено ожидаемое значение. Если конфигурация генерируется FreePBX или другим интерфейсом, выясните, какой слой владеет параметром. Ручная правка файла, который интерфейс перезаписывает, — краткий способ получить временное облегчение и постоянную загадку.

Если отказы повторяются, я с командой проверю SIP-трассу, сопоставление endpoint, объекты auth и маршрут до оператора. Сначала зафиксируем причину и согласуем безопасное окно для сетевых изменений. Обсудить задачу
Сравнение auth и outbound_auth для входящих и исходящих запросов PJSIP
Выберите auth по направлению

4. Почему нельзя лечить авторизацию заменой bind

Объект transport задаёт, на каком адресе и через какой протокол Asterisk принимает или отправляет SIP-сигнализацию. Значения bind выбирают сетевой интерфейс и порт для самого транспорта; они не «охватывают подсети» и не настраивают правила авторизации. Если запрос не приходит на узел, проверяю адрес назначения, маршрутизацию, межсетевой экран и фактический сокет прослушивания. Если запрос уже виден в PJSIP-логе, сначала ищу проблему выше по цепочке, а не расширяю привязку.

Не копируйте bind=0.0.0.0:5060 как универсальную починку. Такой адрес означает привязку ко всем IPv4-интерфейсам, где это возможно; он не является ни рекомендацией по безопасности, ни гарантией доступности из внешней сети. Выбирайте адрес и протокол по схеме сети и требуемой доступности, а доступ ограничивайте сетевыми правилами. Порт 5060 часто используют для SIP по UDP, но в конкретной установке он может быть изменён или занят другим процессом; TLS и TCP требуют соответствующих настроек и сертификатов, а не просто замены числа на 5061.

Особенно опасен совет изменить bind, выполнить module reload res_pjsip.so и объявить проблему решённой. Официальная документация Asterisk предупреждает: изменения параметров PJSIP-транспорта обычно применяются только после полного перезапуска Asterisk; перезагрузка модуля недостаточна. Есть опция allow_reload, но её поведение и доступность зависят от версии и конфигурации, поэтому не обещаю эффект без проверки. Перед плановым рестартом оцениваю влияние на текущие звонки, согласую окно и сохраняю предыдущий конфиг.

`bind` отвечает за локальную привязку транспорта, а не за пароль и не за доступ между подсетями.

5. Как отделить авторизацию от dialplan и маршрута

Когда запрос сопоставлен и нужный обмен авторизацией завершился, проверяю, что происходит с вызовом дальше. Для входящего звонка важны context endpoint и подходящее правило в extensions.conf; для исходящего — правило набора, выбор endpoint транка и формат номера, который ждёт оператор. Здесь полезно идти по конкретному номеру и контексту. Я не подменяю анализ абстрактным «посмотрите dialplan»: сверяю, какой именно шаблон должен совпасть и какое приложение вызывается.

Проверяю pjsip show endpoint ИМЯ, dialplan show ИМЯ_КОНТЕКСТА и результат одного теста в CLI. Если вызов не дошёл до ожидаемого правила, проверяю контекст и шаблон; если правило выбрало транк, но провайдер ответил отказом, возвращаюсь к его ответу, credentials и формату набранного номера. В примере «Еврострой-Мед» после исправления связи outbound_auth с endpoint регистрация осталась без изменений, а тестовый вызов через нужный транк прошёл. Это полезное напоминание: регистрация может быть исправна одновременно с ошибкой исходящего вызова.

Для направления «кто кому звонит» и разбора соседних уровней настройки полезно отдельно держать под рукой практическое руководство по PJSIP. В этой статье задача уже: локализовать конкретный отказ, сохранить улики, внести одно изменение и повторить тот же тест. После правки сравниваю результат с исходным сценарием: те же абоненты, направление, время и маршрут. Иначе легко принять случайное изменение состояния за доказательство, что настройка исправлена.

Для входящего вызова отдельно сверяю номер, который приходит в To или Request-URI, с шаблоном набора и контекстом endpoint. В CLI можно вывести содержимое контекста командой dialplan show ИМЯ_КОНТЕКСТА; проверяю, есть ли совпадающее правило и куда оно передаёт канал. Для исходящего — смотрю фактическое преобразование номера и выбор транка: локальный шаблон может принять короткий номер, но отправить оператору форму, которую тот не обслуживает. Если провайдер прислал конкретный SIP-ответ, фиксирую его вместе с вызовом, не приписывая причину коду без контекста. Некоторые отказы возникают из-за политики или формата номера на стороне оператора, и тогда править Asterisk следует только после сопоставления с его требованиями. Правило «раз регистрации нет — меняем пароль» в этой части особенно бесполезно: оно не проверит контекст, права на направление и согласованный формат адреса назначения.

6. Как внести правку и подтвердить результат

Перед изменением сохраняю копию относящихся к проблеме файлов и записываю исходные значения. Если менялся обычный объект PJSIP, перечитываю конфигурацию поддерживаемой для этой установки командой и убеждаюсь в CLI, что объект получил ожидаемые параметры. Если менялся transport, не рассчитываю на обычный reload: сверяю документацию именно установленной версии, планирую перезапуск и предупреждаю пользователей о возможном коротком перерыве. Команду core restart now нельзя бросать в рабочую АТС только ради эксперимента.

Повторяю один и тот же тестовый вызов и фиксирую SIP-цепочку до конечного результата. Для успешного вызова ищу корректный ответ и продолжение диалога, а не только отсутствие 401 или 403: нормальная аутентификация тоже может включать challenge 401. Для неуспешного — отмечаю первую сторону и этап, где снова появился отказ. Затем отключаю трассировку командой pjsip set logger off, снижаю временно поднятые уровни core set verbose 0 и core set debug 0, а в журнале оставляю только безопасно отредактированный фрагмент.

В журнале изменений записываю причину, точный объект, изменённые параметры, способ отката и результат контрольного звонка. Ежеквартальный обязательный аудит для каждой АТС обещать не буду: периодичность выбирают по частоте изменений, числу транков и последствиям сбоя. Но после обновления, смены оператора, сетевой схемы или учётных данных проверка маршрута и тестовый вызов должны быть частью приёмки. На этом месте заканчивается диагностика: сначала факт из лога, потом одна правка, затем повторяемый контроль.

У контрольного теста должны быть понятные критерии до внесения правки. Для регистрации это ожидаемый статус транка или появление нужного контакта; для вызова — прохождение по конкретному контексту, выбор ожидаемого endpoint и результат на удалённой стороне. Записываю эти критерии заранее, иначе после нескольких одновременных изменений можно убедить себя в успехе по одному случайно прошедшему звонку. Время теста тоже важно: SIP-трасса должна соответствовать именно ему, а не соседней попытке другого абонента. Если ошибку нельзя повторить, собираю исходные данные и жду следующего воспроизведения вместо того, чтобы менять рабочий bind или credentials вслепую. После фиксации результата удаляю из отчёта номера сотрудников и любые секреты, оставляя техническую последовательность и изменённые имена объектов в обезличенном виде. Такой журнал помогает следующему администратору увидеть, что было изменено и как откатить правку, если появится новый симптом.

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

Означает ли 401, что пароль неверный?

Нет. 401 может быть штатным challenge. Проверьте, повторился ли запрос с Authorization и чем закончился повтор.

Если телефон зарегистрирован, почему вызов не проходит?

Регистрация показывает наличие контакта, но не проверяет контекст, маршрут набора, исходящую авторизацию транка и правила оператора.

Чем отличаются auth и outbound_auth?

`auth` связывает endpoint с авторизацией входящих запросов; `outbound_auth` используется для исходящих запросов, например к оператору.

Можно ли применить изменение transport командой module reload?

Обычно нет: документация Asterisk указывает, что для изменений транспорта требуется полный перезапуск. Уточните поведение конкретной версии и `allow_reload`.

Нужно ли ставить bind на 0.0.0.0?

Только если это соответствует сетевой схеме и политике доступа. Это не универсальный способ исправить авторизацию или межсетевую доступность.

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

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

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

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

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

Источники

© ООО «АйТи-Фреш» · Москва · Все статьи