Как найти причину отказа PJSIP в Asterisk
Если 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-транкам.
- `asterisk -rvvv` — открыть CLI
- `pjsip set logger on` — включить SIP-трассировку
- `pjsip set logger off` — выключить трассировку
- Записать время и направление тестового вызова
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 не работает».
- 401: проверьте challenge и повтор с Authorization
- 403: выясните, какая сторона запретила запрос
- Сверьте направление и первый неудачный этап
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 или другим интерфейсом, выясните, какой слой владеет параметром. Ручная правка файла, который интерфейс перезаписывает, — краткий способ получить временное облегчение и постоянную загадку.
- `pjsip show endpoints` — список endpoint
- `pjsip show contacts` — известные контакты
- `pjsip show registrations` — регистрации транков
- `auth` для входящих запросов; `outbound_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, но её поведение и доступность зависят от версии и конфигурации, поэтому не обещаю эффект без проверки. Перед плановым рестартом оцениваю влияние на текущие звонки, согласую окно и сохраняю предыдущий конфиг.
- Сначала проверьте, приходит ли SIP-запрос
- Не расширяйте bind без сетевой причины
- Изменения transport требуют проверки документации вашей версии
- Перезапуск планируйте с учётом активных вызовов
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?
Только если это соответствует сетевой схеме и политике доступа. Это не универсальный способ исправить авторизацию или межсетевую доступность.
Источники
- Asterisk Documentation — PJSIP Troubleshooting Guide — Проверены команды диагностики, включая уровни verbose/debug, трассировку PJSIP, сопоставление endpoint и разбор отказов: https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/Asterisk-PJSIP-Troubleshooting-Guide/
- Asterisk Documentation — PJSIP Authentication — Проверены параметры auth_type, username, password, auth и outbound_auth; значения userpass и md5 отмечены устаревшими: https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/PJSIP-Authentication/
- Asterisk Documentation — res_pjsip Configuration Reference — Проверены объекты endpoint, AOR, transport, bind и требование перезапуска для изменения транспорта: https://docs.asterisk.org/Asterisk_20_Documentation/API_Documentation/Module_Configuration/res_pjsip/
- Asterisk Documentation — Basic Logging Commands — Проверены синтаксис core set verbose и core set debug: https://docs.asterisk.org/Operation/Logging/Basic-Logging-Commands/


