Траблшутинг односторонней слышимости (One-Way Audio) и NAT в Asterisk PJSIP
- Абонент А слышит абонента Б, но абонент Б ничего не слышит (или оба не слышат друг друга).
- Звонок завершается ровно через 30 секунд (RTP Timeout / No RTP incoming).
- В SIP SDP-пакетах передается локальный серый IP-адрес (например, 192.168.1.50) вместо публичного IP сервера.
- Медиапакеты RTP отбрасываются межсетевым экраном из-за несоответствия диапазонов портов.
1. Настройка сетевого транспорта в pjsip.conf
Укажите параметры локальных подсетей и внешнего адреса в объекте [transport-udp]:
[transport-udp]
type=transport
protocol=udp
bind=0.0.0.0:5060
local_net=192.168.0.0/16
local_net=10.0.0.0/8
local_net=172.16.0.0/12
external_media_address=198.51.100.25
external_signaling_address=198.51.100.252. Настройка эндпоинтов за NAT (абоненты и транки)
В секциях эндпоинтов включите принудительный sym_nat и перенаправление RTP:
[endpoint_template](!)
type=endpoint
rtp_symmetric=yes
force_rport=yes
rewrite_contact=yes
direct_media=no3. Конфигурация диапазона портов RTP и Firewall
В файле /etc/asterisk/rtp.conf:
[general]
rtpstart=10000
rtpend=20000Откройте UDP-порты в фаерволе операционной системы:
# UFW (Ubuntu/Debian)
ufw allow 5060/udp
ufw allow 10000:20000/udp
# Firewalld (RHEL/Rocky)
firewall-cmd --permanent --add-port=5060/udp
firewall-cmd --permanent --add-port=10000-20000/udp
firewall-cmd --reload4. Диагностика прохождения SIP/RTP через sngrep
# Установка sngrep
apt-get install sngrep -y || dnf install sngrep -y
# Запуск интерактивного анализатора
sngrep -cНажмите Enter на вызове и проверьте вкладку RTP Flow: пакеты должны идти в обоих направлениях между публичными IP клиентов и Asterisk.
Частые вопросы (FAQ)
Почему direct_media=no решает проблему односторонней слышимости?
По умолчанию direct_media=yes пытается направить RTP-трафик напрямую между двумя телефонами (Re-INVITE). Если телефоны находятся за разными NAT, они не могут связаться напрямую. direct_media=no заставляет Asterisk оставаться в центре медиапотока и ретранслировать RTP.
Зачем нужны параметры rtp_symmetric=yes и force_rport=yes?
force_rport заставляет Asterisk отвечать на тот IP и порт, откуда физически пришел SIP-пакет, игнорируя заголовки Via. rtp_symmetric заставляет отправлять медиа на тот порт, откуда поступил первый входящий RTP-пакет от клиента.
Почему звонок сбрасывается ровно через 30 секунд?
Asterisk отслеживает наличие входящего RTP-потока. Если из-за закрытых портов фаервола или ошибки NAT RTP от удаленной стороны не поступает в течение rtpkeepalive / rtptimeout секунд, канал принудительно завершает сессию.
Что делать, если у сервера Asterisk динамический внешний IP?
В chan_pjsip для внешнего адреса можно указать DNS-имя вместо IP: external_media_address=pbx.mydomain.com. Asterisk будет периодически резолвить обновленный адрес.