Как найти сбой TLS в Asterisk и вернуть звонки
Если после включения TLS в Asterisk не проходят звонки, сначала выясните, где обрывается цепочка: TCP-соединение, проверка сертификата, SIP-обмен или RTP-аудио. Я разбираю эти уровни по порядку, показываю корректные параметры PJSIP и объясняю, почему один открытый порт не чинит всё сразу.
Сначала определите, на каком этапе рвётся звонок
TLS защищает SIP-сигнализацию между участниками соединения. Сам по себе включённый TLS не означает, что аудио тоже зашифровано: голос обычно передаётся отдельно по RTP, а для шифрования медиапотока настраивают SRTP. Поэтому фраза «включили TLS — звонки сломались» пока не диагноз. Это только отметка времени, после которой нужно сравнить поведение до и после изменения. В сложных случаях я подключаю поддержку ИТ-инфраструктуры и начинаю с трёх вопросов: устанавливается ли TCP-соединение, проходит ли TLS-рукопожатие, видит ли Asterisk SIP-запрос INVITE? Если INVITE уже дошёл, сертификатная часть могла отработать, и искать причину нужно дальше по SIP-ответам и маршруту вызова.
Сначала откройте консоль Asterisk и снимите короткий фрагмент лога во время одной контрольной попытки. Для PJSIP включите протокольную трассировку командой pjsip set logger on, затем сразу воспроизведите сбой; после сбора выключите её командой pjsip set logger off, чтобы не оставлять подробный лог включённым без нужды. Смотрите, дошёл ли INVITE, что отвечает удалённая сторона и на каком шаге появляется ошибка. Если нужна базовая схема объектов, пригодится разбор настройки PJSIP в Asterisk. Для проверки загруженных объектов подойдут pjsip show transports, pjsip show endpoints и pjsip show endpoint <имя>. Команда sip show peers относится к chan_sip; при PJSIP она не является проверкой регистрации или состояния endpoint. Команды должны соответствовать драйверу, а не привычке.
Не привязывайте любой отказ к сертификату. Ответ SIP 403 — это отказ на уровне SIP-политики или авторизации, а не универсальный код «сертификат не подошёл». Ошибка TCP-соединения означает, что удалённый узел не установил транспорт; сообщение о TLS handshake указывает на TLS-уровень; полученный INVITE без подходящего маршрута ведёт уже к диалплану. Разные причины дают разные следы. Сохраните время попытки и небольшой участок лога вокруг неё, иначе в общем журнале легко смешать регистрацию, входящий вызов и фоновый обмен OPTIONS. Это скучная дисциплина, зато она дешевле гадания по конфигу.
Условный пример: на одной АТС регистрация телефона оставалась активной, а исходящий вызов не соединялся после смены транспорта. Мы бы не стали немедленно перевыпускать весь парк сертификатов. Сначала проверили бы, какой endpoint инициирует вызов, какой transport к нему привязан и виден ли INVITE в PJSIP-логе. Если INVITE уходит, а ответ не возвращается, проверяем путь обратно и внешние адреса; если он не уходит, проверяем состояние endpoint и правила набора. Если рукопожатие вообще не состоялось — возвращаемся к сертификату, версии TLS, имени узла и TCP-доступности. Такой порядок не обещает чудес, но быстро отсекает неподходящие версии.
- PJSIP: `pjsip set logger on`, затем одна контрольная попытка.
- Проверьте объекты командами `pjsip show transports` и `pjsip show endpoints`.
- Сопоставьте этап сбоя: TCP, TLS, SIP или RTP.
Проверьте сертификат и ключ как пару
Для PJSIP в секции transport используются cert_file и priv_key_file; tls_cert_file и tls_private_key — неверные названия параметров для этого примера. Сертификат и закрытый ключ должны соответствовать друг другу, быть доступны процессу Asterisk и иметь читаемый формат. Сертификатный файл сам по себе не обязан содержать ключ: в конфигурации можно указать отдельные файлы. В официальном примере Asterisk также используется отдельная цепочка CA для проверки доверия. Не копируйте названия полей между sip.conf и pjsip.conf: у старого chan_sip и PJSIP разные настройки, а похожее имя файла ещё не делает параметр совместимым.
Проверьте, что именно лежит в путях, указанных в активном transport, а затем выведите срок действия и subject сертификата: openssl x509 -in /путь/к/cert.pem -noout -subject -issuer -dates. Эта команда помогает прочитать сертификат; она не подтверждает сама по себе, что ключ ему соответствует, что цепочка доверия полная или что имя сервера совпало с тем, которое проверяет клиент. Проверьте также владельца и права доступа файла от имени пользователя службы. Не выкладывайте ключ в тикет, чат или статью — закрытый ключ не диагностический лог. Если требуется взаимная аутентификация, отдельно разберитесь с ca_list_file, verify_client и require_client_cert в документации именно вашей версии.
Сопоставление имени важно для стороны, которая проверяет сертификат сервера: ожидаемое DNS-имя или адрес должны соответствовать сертификату и настройке клиента. Но утверждение «CN не совпал — звонок всегда не пойдёт» слишком грубое: результат зависит от того, кто выступает TLS-клиентом, включена ли проверка сервера и как устроена проверка имён в конкретном стеке. Не лечите ошибку отключением проверки на постоянной основе. Сертификатная проверка — часть общей безопасности Asterisk. Для диагностики сначала установите, какую сторону и какое имя проверяет лог, затем исправьте сертификат, доверенную CA или адрес подключения. Если проверка отключается ради изолированного теста, верните её в штатную конфигурацию до публикации сервиса.
Утилита ast_tls_cert присутствует в официальном руководстве Asterisk как способ создать тестовый CA, сертификат сервера и клиентские сертификаты. Её ключи и ожидаемые файлы зависят от конкретного скрипта, поэтому команда из чужой статьи вроде ast_tls_cert -C /etc/asterisk/keys не годится как универсальная инструкция: -C задаёт common name, а не каталог назначения. В официальном учебном примере команда выглядит так: ./ast_tls_cert -C pbx.example.com -O "Example" -d /etc/asterisk/keys -b 2048. Это пример генерации самоподписанного CA и сертификата, а не команда для слепого копирования в рабочую систему. Для боевого сервиса обычно используют сертификат от доверенного CA и процедуру его регулярного обновления; наличие скрипта в пакете не делает самоподписанный сертификат автоматически подходящим для телефонов.
- Сверьте `cert_file`, `priv_key_file` и при необходимости `ca_list_file`.
- Проверьте срок действия: `openssl x509 -in cert.pem -noout -dates`.
- Права проверяйте от имени пользователя Asterisk; ключ не раскрывайте.
Настройте PJSIP transport, не смешивая его с endpoint
Минимальная основа TLS-транспорта в pjsip.conf выглядит так; реальные пути и сетевые адреса подставляют свои. Здесь показаны параметры транспортного объекта, а не весь телефонный профиль: endpoint, AoR, авторизация и dialplan настраиваются отдельно.
[transport-tls] type=transport protocol=tls bind=0.0.0.0:5061 cert_file=/etc/asterisk/keys/asterisk.crt priv_key_file=/etc/asterisk/keys/asterisk.key
Нельзя свести рабочий вызов к наличию transport=tls. PJSIP связывает транспорт с endpoint, AoR, правилами определения входящего endpoint и контекстом диалплана. Параметр allow задаёт список допустимых кодеков; он не включает TLS и не устраняет ошибку рукопожатия. Если список кодеков пуст или не совпадает с возможностями второй стороны, сигнализация может пройти, но медиасогласование вызова завершится неудачно или без общего кодека. Поэтому allow=all — не волшебный ремонт. Укажите только реально нужные и поддерживаемые кодеки по политике вашей АТС.
Не объявляйте порты 5060 и 5061 обязательной парой и не называйте сам факт их использования конфликтом. В примере Asterisk TLS привязан к TCP-порту 5061, но конкретный порт задаётся bind; одновременно два transport не могут занять один и тот же адрес с одним и тем же портом. Это ограничение сокета, а не запрет иметь UDP и TLS рядом. Проверьте, на каком адресе и порту действительно слушает процесс, какой порт указан в телефоне или транке и совпадает ли это с сетевым фильтром. У одного из узлов может быть нестандартная схема — универсальное значение из примера её не отменяет.
Transport-конфигурация PJSIP имеет важную особенность: после её правки обычно нужен полный перезапуск Asterisk; одной перезагрузки конфигурации модуля недостаточно, если только транспорт не настроен для допустимой перезагрузки и это поддерживает ваша версия. Планируйте его в согласованное окно, потому что перезапуск влияет на вызовы. Перед ним проверьте синтаксис по документации сборки и сохраните копию исходного файла. В CLI после запуска посмотрите pjsip show transports и проверьте журнал старта на ошибки разбора. Если transport не загрузился, дальнейшие изменения кодеков и dialplan не исправят первичную ошибку.
- PJSIP TLS использует `protocol=tls`, `cert_file`, `priv_key_file`.
- `allow` относится к кодекам, не к TLS-рукопожатию.
- После изменения transport проверьте требования к полному перезапуску Asterisk.
Разделите TCP-сигнализацию, firewall и NAT
Для SIP over TLS нужен доступ к TCP-порту, на котором слушает TLS transport. Правило iptables -A INPUT ... из случайной инструкции — не универсальный фикс: на сервере могут работать nftables, firewalld, облачный firewall, ACL маршрутизатора и отдельные правила на телефонии. Открывайте ровно тот порт и только с тех адресов, которым он нужен, учитывая входящее и ответное направление в вашей политике. Убедитесь, что правило попало в активную цепочку и не перекрыто более ранним запретом. Проверить, что процесс слушает, можно средствами ОС, а доступность с другой стороны проверяйте с того сетевого сегмента, откуда подключается телефон или транк.
TLS защищает SIP-сигнализацию по TCP, а RTP-медиа остаётся отдельным потоком. Поэтому ситуация, когда регистрация и вызов устанавливаются, но нет аудио или слышит только одна сторона, обычно требует проверки SDP, RTP-маршрута, NAT и диапазона медиапортов, а не повторного выпуска сертификата. TLS не «переносит» голос через свой порт. В разборе звонка сопоставьте адреса и порты в SDP с тем, что реально доступно на маршрутизаторе, и проверьте обе стороны аудиопотока. Если нужен шифрованный голос, отдельно настраивается SRTP и согласуется совместимость клиентов; одного TLS для этого недостаточно.
При размещении за NAT официальное руководство PJSIP описывает local_net, external_signaling_address и external_media_address в секции transport. Они решают разные задачи: внешний адрес сигнализации и адрес RTP в SDP не являются взаимозаменяемыми. Asterisk применяет внешние адреса с учётом локальной сети и условий обмена, а не просто заменяет любой адрес во всех пакетах. Не вставляйте случайный IP из примера в конфиг; используйте адрес своей схемы и корректную маску локальной сети. Если у сигнализации и медиа разные внешние адреса или есть SIP-прокси, конфигурация будет зависеть от топологии.
Если регистрация отображается как успешная, это ещё не гарантия, что исходящий INVITE пройдёт тем же путём или что ответ и аудио вернутся. Проверьте настройки транспорта у конкретного endpoint, контакт в AoR, адрес назначения транка и маршрут в dialplan. На сети проверьте состояние TCP-сессии и прохождение пакетов, а для медиапроблем отдельно изучите RTP. Если используется SIP ALG, проверьте документацию маршрутизатора и наблюдаемое поведение: не объявляйте его причиной без подтверждения. Сетевые устройства иногда переписывают SIP-содержимое и мешают согласованности адресов, но это гипотеза для проверки, не диагноз по умолчанию.
- TCP-порт TLS должен совпадать с `bind` активного transport.
- Для NAT проверьте `local_net` и оба внешних адреса; для аудио — отдельно RTP/SDP.
- TLS шифрует сигнализацию; медиапоток требует отдельной настройки SRTP.
Проверьте исправление одним контролируемым вызовом
После правки я фиксирую исходное состояние, перезапускаю Asterisk только если менялся transport или этого требуют настройки, затем проверяю, что transport загрузился и endpoint виден. В CLI помогают pjsip show transports, pjsip show endpoints и pjsip show endpoint <имя>. Далее включаю pjsip set logger on, выполняю один тестовый звонок и записываю, дошёл ли INVITE, какой ответ вернулся и состоялось ли завершение вызова. Затем выключаю трассировку. Не считайте строку «Registered» доказательством исправного аудио: она говорит о регистрации, а не о маршруте RTP или совместимости кодеков.
Для отдельной проверки TLS-слушателя можно использовать openssl s_client -connect имя-узла:порт -servername имя-узла -showcerts. Укажите тот порт, который реально настроен, и DNS-имя, ожидаемое сертификатом. Успешное TLS-соединение показывает, что удалённый процесс ответил на TLS и передал сертификатную цепочку; оно не проверяет регистрацию SIP, настройки endpoint, авторизацию, маршрут набора или наличие RTP. При тестировании от самого сервера результат может отличаться от теста с телефона за NAT или с внешней сети, поэтому проверяйте с нужной точки подключения.
Проведите вызов в обе стороны и отдельно проверьте слышимость обоих абонентов. Смотрите на SIP-ответы, SDP, согласованный кодек и факт двусторонней передачи RTP. Если соединение установлено, но нет медиа, возвращайтесь к сетевым адресам, диапазону медиапортов, direct media и настройкам SRTP; если INVITE не появился, разбирайте transport, endpoint и dialplan. Сравните результаты до и после изменения, не меняя сразу несколько параметров. Одно изменение за раз — не медлительность, а способ понять, что именно помогло.
Сертификаты требуют учёта срока действия и проверки процедуры обновления. Уведомление заранее полезно, но конкретное число дней — внутренняя политика, а не встроенное правило Asterisk. После обновления проверьте, подхватил ли файл процесс и требуется ли для этого полный перезапуск в вашей версии; отдельно убедитесь, что клиенты доверяют CA и видят правильное имя сервера. Для транспортов без allow_reload=yes документация предупреждает, что изменения вступают в силу только после полного перезапуска. Не запускайте его автоматически посреди рабочего дня: предусмотрите окно и контрольный вызов после работ.
- Проверьте transport и endpoint после перезапуска.
- Сделайте один исходящий и один входящий контрольный звонок.
- Проверьте сигнализацию и двустороннее аудио раздельно.
Частые вопросы
Какие параметры сертификата нужны для PJSIP TLS?
В секции transport указывают `cert_file` и `priv_key_file`; при проверке доверия настраивают CA и соответствующие параметры проверки. Точные параметры сверяйте с документацией вашей версии.
Почему при рабочей регистрации не проходит звонок?
Регистрация не подтверждает, что INVITE проходит по нужному endpoint и маршруту. Проверьте PJSIP-лог, ответы SIP, транспорт и dialplan.
Порт 5061 обязателен для TLS?
Нет. Это типичный пример из документации Asterisk; фактический порт задаётся в `bind` TLS transport и должен совпадать с настройками клиента и firewall.
Шифрует ли SIP TLS голос?
TLS защищает SIP-сигнализацию. Для шифрования медиапотока отдельно настраивают SRTP и проверяют совместимость устройств.
Нужно ли перезапускать Asterisk после правки transport?
Документация PJSIP указывает, что изменения transport обычно применяются только после полного перезапуска; проверьте условия своей версии и планируйте окно.
Источники
- Asterisk Secure Calling Tutorial — Пример PJSIP TLS transport с cert_file и priv_key_file; отдельно показаны TLS-сигнализация и SRTP-медиа. https://docs.asterisk.org/Deployment/Secure-Calling/Secure-Calling-Tutorial/
- Asterisk res_pjsip configuration reference — Параметры transport и сертификатов; изменения transport обычно требуют полного перезапуска Asterisk. https://docs.asterisk.org/Latest_API/API_Documentation/Module_Configuration/res_pjsip/
- Asterisk PJSIP Troubleshooting Guide — Команды PJSIP CLI, просмотр endpoint и диагностика конфигурации. https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/Asterisk-PJSIP-Troubleshooting-Guide/
- Configuring res_pjsip to work through NAT — Назначение local_net, external_media_address и external_signaling_address для NAT. https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/Configuring-res_pjsip-to-work-through-NAT/
- PJSIP Configuration Sections and Relationships — Разделение объектов transport, endpoint, AoR и ограничения транспортов. https://docs.asterisk.org/Configuration/Channel-Drivers/SIP/Configuring-res_pjsip/PJSIP-Configuration-Sections-and-Relationships/



