Успешная регистрация почти ничего не говорит о звуке. Программный телефон может часами держать действительную привязку к офисной PBX и всё равно передавать тишину. Туннель несёт только те пакеты, которые кто-то намеренно в него отправляет, а вызов использует три отдельных пути: привязку, установление диалога и поток RTP. Как только вы их разделите, сбой приходится на один путь, а не на слово VPN.

Представьте ноутбук в домашней сети Wi-Fi, который набирает офисный добавочный номер через одобренный туннель. PBX аутентифицирует пользователя, принимает REGISTER, и добавочный номер отображается как доступный, но вызов соединяется с полной тишиной в одном направлении.

Регистрация привязывает контакт, а не путь медиа

Запрос REGISTER просит регистратор сохранить соответствие между адресом записи и одним или несколькими контактными URI. Это соответствие отвечает на узкий вопрос: куда сейчас нужно отправить новый диалог. Оно ничего не говорит о том, где находятся медиа, и принятая регистрация не доказывает, что последующий INVITE несёт достижимый адрес медиа. Регистрации также истекают по таймеру, поэтому телефон, переставший обновляться, теряет входящие вызовы, хотя его туннель по-прежнему выглядит здоровым. Следите за сроком действия контакта, а не за состоянием туннеля.

Когда программный телефон находится за туннелем, заголовок контакта может нести частный адрес. PBX, который пересылает его другой конечной точке, создаёт диалог, направленный в сеть, недоступную вызываемому. Настройка rewrite_contact=yes на конечной точке PJSIP заставляет PBX подставить наблюдаемый адрес источника, и это часто и есть разница между вызовом и тайм-аутом.

Что предлагает INVITE и кто может этим пользоваться

INVITE с телом SDP предлагает место, где вызывающий хочет получать медиа: адрес, порт и список кодеков. Вызываемый отвечает своим адресом и портом, после чего каждая сторона отправляет RTP туда, что предложила другая. Если вызывающий предложил адрес 192.168.x.x, существующий только в его домашней сети, вызываемому некуда отправлять звук, каким бы чистым ни был сигналинг. Маскирование переписывает заголовки IP при выходе пакетов из маршрутизатора, но никогда не переписывает текст внутри тела SDP.

Этот разрыв объясняет классический односторонний вызов: сигналинг работает, потому что обе конечные точки достигают PBX, а звук не идёт, потому что одной конечной точке велели отправлять на адрес, существующий только за другим NAT.

PathWho picks the addressTypical failure
REGISTERSoftphone, rewritten by the registrar if configuredBinding expires or points at a private address
INVITE and SDPEach endpoint in its own offer or answerOffer names a media address nobody can route to
RTPPBX relay policy or the two endpointsPort range blocked, or no return path

Кто несёт звук — это выбор конфигурации

Сигналинг и медиа — разные роли. Прокси может оставаться на пути сигналинга весь вызов и ни разу не коснуться ни одного пакета RTP. Станет ли PBX ретранслятором медиа, зависит от конфигурации, а не от наличия туннеля.

При прямых медиа конечные точки сами обмениваются RTP, что хорошо работает в одной локальной сети и плохо, когда одна сторона находится за узким диапазоном портов.

Настройка direct_media=no вводит PBX в путь медиа, чтобы оба плеча завершались на адресе, который он контролирует, в обмен на предсказуемую адресацию за счёт полосы пропускания и процессора. При ретрансляции PBX всё равно должен объявлять достижимый адрес. На хосте с несколькими сетями external_media_address и external_signaling_address в pjsip.conf определяют, что появится в SDP и в заголовках Via. Если оставить их незаданными, PBX может предложить свой адрес LAN вызывающему, единственный путь которого — дальняя сторона туннеля.

Проследите каждое направление, прежде чем трогать настройки

Начните с таблицы сокетов на PBX, пока вызов активен: ss -uanp | grep -E '5060|10000' показывает, привязаны ли порты RTP и какой локальный адрес они используют. Если в диапазоне медиа ничего не привязано, ретранслятор не задействован, и конечные точки общаются напрямую. Затем сделайте запись на стороне программного телефона с помощью tcpdump -ni any -s0 udp portrange 10000-20000 -w rtp.pcap. Исходящие пакеты без входящих сужают проблему до обратного пути или до адреса, который дальней стороне велели использовать, а пустая запись означает, что медиа вообще не дошли до интерфейса туннеля. Запись сигналинга с помощью sngrep отвечает на другую половину, показывая строку соединения SDP такой, какой она была отправлена.

Сравните адрес в этой строке соединения с адресом, до которого дальняя сторона действительно может маршрутизировать. Это единственное сравнение решает большинство сообщений об одностороннем звуке быстрее, чем любой обзор конфигурации.

Шифрование заканчивается на краю туннеля

SIP поверх TLS защищает тот скачок сигналинга, для которого он настроен, SRTP защищает медиа, когда обе стороны об этом договариваются, а туннель защищает трафик между своими конечными точками. Ни одно из них не даёт остальные. Вызов, зашифрованный внутри туннеля, может выйти из шлюза открытым текстом в сторону PBX, и это проектное решение, а не дефект.

Прежде чем закрыть заявку, подтвердите три вещи по порядку: регистрация свежая, SDP несёт адрес, достижимый для дальней стороны, и пакеты идут в обе стороны на портах медиа. Если что-то из этого неверно, проблема не в туннеле. Исправьте путь, который отказал, и затем повторите ту же запись, чтобы подтвердить изменение. Сохранение записей до и после превращает следующее сообщение об одностороннем звуке в пятиминутную проверку вместо целого дня.

Похожие статьи