NAT, SIP и Asterisk

NAT, SIP и Asterisk

Трансляция сетевых адресов (NAT) является обычной практикой в сети и нередко мешает прохождению голосовых пакетов (нет звука) и инициализации соединений (нет соединения). Решение этой проблемы требует понимания принципов работы NAT и VoIP. В этой статье рассматривается протокол SIP и Asterisk, но проблемы и решения применимы и к большинству других приложений и протоколов.

NAT используется, чтобы скрыть многочисленные локальные адреса, за каким-то внешним узлом, обеспечивая безопасность и структуризацию сети.
Когда пакет проходит шлюз (gateway), IP-адрес локального источника заменяется на внешний IP-адрес. При ответе шлюз направляет пакет на исходный локальный адрес. Также шлюз блокирует внешние запросы не имеющие явных внутренних источников, но возможно пробросить пакеты пришедшие на определенные порты, на заранее заданные IP адреса внутри сети.
Если у вас нет звука, нет звука в одну сторону, нет слышимости, прочтите внимательно эту инструкцию.

Reinvite

NAT, SIP и Asterisk

Первый абонент запрашивает соединение у второго , сообщая свой IP адрес. Второй отвечает, сообщая свой IP. Голосовые пакеты направляются напрямую абонентам, минуя SIP сервер. Передача голосовых пакетов напрямую абонентам, минуя Asterisk, называется RE-INVITE или Native Bridge.
NAT может вызвать проблемы в нескольких местах.
Если одна из АТС находится за NAT, другая АТС не сможет связаться с ней, без проброса портов.
Если телефон находится за NAT, голосовые пакеты могут быть направлены на немаршрутизируемый адрес в сети, что приведет к потере звука.

Клиент за NAT

NAT, SIP и Asterisk

В простейшей ситуации SIP клиент находясь за NAT, обращается к внешнему интерфейсу Asterisk. SIP клиент при регистрации на сервере создает запись в таблице трансляций, которая сохраняется, пока проходит хотя бы один пакет в минуту. В файле sip.conf требуется определить параметры сети и свойства удаленного пира.
[general]
localnet=192.168.0.0/255.255.255.0 ; локальная сеть
externip=x.x.x.x ; внешний ip адрес

[sip_phone]
nat=yes
qualify=300 ; проверять соединение каждые 300 мс.

Начиная с версии Asterisk 11: ‘nat=yes’ устарело, используйте ‘nat=force_rport,comedia’

nat=force_rport,comedia

nat=force_rport,comedia
directmedia=nonat

При такой конфигурации Asterisk использует внешний IP адрес externip для вызовов клиентов с параметром nat=yes. Дополнительно параметр qualify=yes поддерживает соединение, не позволяя удалять запись из таблицы трансляций.

SIP клиенты и Asterisk за NAT

NAT, SIP и Asterisk
Все усложняется если и Asterisk, и клиенты, находятся за NAT. Клиенты с внешней стороны не смогут получать SIP сообщения и принимать звонки. Или в SIP сообщении будет указан локальный IP адрес телефона, что приведет к потере звука.
Чтобы избежать потери звука запретите re-invite в файле sip.conf

[general]
canreinvite => no

Опция canreinvite устарела. Используйте ‘directmedia’.

  • directmedia=yes
  • directmedia=nonat
  • directmedia=update
  • directmedia=outgoing

Но клиенты находящиеся за NAT, все равно не смогут инициировать соединение с Asterisk и направить голосовые пакеты RTP на требуемый екстеншен. Для того чтобы это работало, надо пробросить требуемые порты через брандмауер на Asterisk. Диапазон RTP портов используемых Asterisk, назначается в файле rtp.conf.

[general]
rtpstart=10000
rtpend=10100

По умолчанию задан диапазон от 10000 до 20000. Измените диапазон в соответствии с вашими потребностями (3 порта на каждый конкурирующий вызов).
Для нормальной работы за NAT, потребуется пробросить диапазон RTP портов в соответствии с настройками в файле rtp.conf и порт SIP (обычно 5060). В iptables это будет выглядеть так:

iptables -t nat -A PREROUTING -i eth0 -p udp -m udp --dport 10000:10100 -j DNAT
 --to-destination 192.168.1.10
iptables -t nat -A PREROUTING -i eth0 -p udp -m udp --dport 5060 -j DNAT
 --to-destination 192.168.1.10

Где eth0 – внешний интерфейс, а 192.168.1.10 – IP адрес Asterisk.

Основные параметры конфигурации NAT для Asterisk

localnet

Параметр ‘localnet’ список сетевых адресов, которые считаются «внутренними».

localnet=192.168.0.0/255.255.0.0 - RFC 1918 адреса
localnet=10.0.0.0/255.0.0.0 - Также RFC1918
localnet=172.16.0.0/12 - Другое RFC1918 с CIDR обозначением
localnet=169.254.0.0/255.255.0.0 - Zeroconf локальная сеть

externaddr

Внешний адрес щлюза (маршрутизатора) во внешнюю сеть. «externaddr = hostname[:port]» указывает статический адрес[:port] который будет использован в SIP и SDP сообщениях. Имя хоста (hostname) поднимается каждый раз, когда [пере]загружается sip.conf. Если порт не назначен, используется значение указанное в параметре «udpbindaddr». примеры:

externaddr = 123.34.56.78: - использовать этот адрес.
externaddr = 123.34.56.78:9900 - использовать этот адрес и порт.
externtcpport = 9900 - отображаемый наружу tcp порт
externtlsport = 12600 - отображаемый наружу tcp порт; 'externtlsport' по рекомендации RFC назначенный порт 5061.

externhost

«externhost = hostname[:port]» то же что и «externaddr» только это ‘hostname’ обновляемое через «externrefresh» секунд (по умолчанию 10 сек.).

externhost=foo.dyndns.net - обновлять периодически
externrefresh=180 - задать интервал обновления

В дополнение к вышесказанному Asterisk имеет дополнительный параметр «NAT» для разрешения вопросов, связанных со входящими SIP или медиа сессиями. В частности, в зависимости от настроек ‘NAT=’ как описано ниже, Asterisk может переопределить адрес/порт информацию, указанную в SIP/SDP сообщениях.

nat = no - без NAT RFC3581
nat = force_rport - использовать rport, даже если его нет
nat = comedia - отправить медиа поток на порт Asterisk, независимо от указаний SDP.
nat = auto_force_rport - установить 'force_rport' параметр если Asterisk обнаружил NAT (по умолчанию)
nat = auto_comedia - установить 'comedia' параметр если Asterisk обнаружил NAT

настройки могут совмещаться:

nat=force_rport,comedia
RFC 3581 определяет что ‘rport’ позволяет клиенту запросить, чтобы Asterisk отправлял SIP ответы на него через исходный IP и порт, с которого был направлен запрос, вместо адреса/порта из самого верхнего Via заголовка.
Установка force_rport принуждает Asterisk всегда передавать ответы обратно на адрес/порт, с которых он получил запросы, даже если другая сторона не поддерживает добавления параметра ‘rport’.

media_address

IP адрес используемый для медиа (аудио, видео и текста) в SDP может быть переназначен параметром ‘media_address’. Данный параметр может быть использован только в секции [general].

media_address = 172.16.42.1

icesupport

ICE/STUN/TURN использование может быть включено глобально или для конкретного пира с помощью ‘icesupport’ опции.

icesupport = yes

directmedia

Для отключения прямых RTP потоков (peer-to-peer) используйте опцию:

directmedia=nonat

устаревшие настройки sip.conf

port = Порт используемый SIP протоколом для сигнализации (default=5060)
bindaddr  = IP адрес Asterisk, если указано 0.0.0.0, то любой адрес.

externip= Этот параметр задается в секции [general] файла sip.conf и указывает внешний IP адрес, или имя хоста на вашем устройстве NAT.

externip=123.123.123.123

Этот адрес будет использован для общения с устройствами с установленным параметром nat=force_rport.
localnet = Этот параметр задается в секции [general] файла sip.conf и указывает на локальную сеть и используется для обращения к устройствам с параметром nat=no.

localnet=192.168.0.0/255.255.255.0

NAT

Возможные значения:
NAT= yes, no, never, route

NAT=route

Начиная с версии Asterisk 11: nat=yes is deprecated, use nat=force_rport,comedia instead

  • nat = no – без NAT RFC3581
  • nat = force_rport – использовать rport, даже если его нет
  • nat = comedia – отправить медиа поток на порт Asterisk, независимо от указаний SDP.
  • nat = auto_force_rport – установить ‘force_rport’ параметр если Asterisk обнаружил NAT (по умолчанию)
  • nat = auto_comedia – установить ‘comedia’ параметр если Asterisk обнаружил NAT

Asterisk будет отправлять голосовые пакеты на порт и IP адрес с которого их получает а не указанные в SIP и SDP сообщениях.
Это будет работать только, если телефоны за NAT будут использовать для одинаковый порт для голосовых пакетов RTP и одинаковый (но отличный от голосового) для сигнализации RTCP.

directmedia

  • directmedia=yes
  • directmedia=nonat
  • directmedia=update
  • directmedia=outgoing

qualify = Эта опция имеет два назначения.Первое – поддерживать запись в таблице трансляций NAT и контролировать регистрацию телефона.
Возможные значения:

qualify=yes

Этот параметр задает проверку по умолчанию каждые 2 секунды.

qualify=no

Это выключает проверку.

qualify=300

ключает проверку через заданное время в 300 ms.

rtp.conf

rtpstart=10000

Задает первый порт диапазона для приема и оправки голосовых пакетов RTP.

rtpend=10100

Задает последний порт диапазона для приема и оправки голосовых пакетов RTP.

stunaddr=sip.stun.tld

В Asterisk начиная с версии 11 появилась поддержка stun. icesupport должно быть включено.

Настройка res_pjsip для работы через NAT

В данной статье приведены примеры рабочей конфигурации драйвера канала PjSIP, когда Asterisk находится за NAT (Network Address Translation). Asterisk подключается через NAT к провайдеру IP телефонии (ITCP).
Этот пример подходит для большинства простых сценариев NAT при следующих условиях: Asterisk и телефоны находятся в частной сети. Маршрутизатор имеет локальный и публичный интерфейсы. Маршрутизатор реализует функции Трансляции Сетевых Адресов (NAT) и файерволла. На маршрутизаторе настроен проброс SIP и RTP портов на локальный IP адрес сервера Asterisk. В данном примере проброшены порты 5060 TCP/UDP и UDP 10000-10100 на LAN 10.10.2.10.
Устройства используемые в примере:

Устройство IP адрес в примере
VOIP телефон (7777) 10.10.2.77
PC/Asterisk 10.10.2.10
Маршрутизатор LAN: 10.10.2.1
WAN: 123.123.123.123
ITSP SIP шлюз 203.0.113.1(gw1.example.com)
203.0.113.2(gw2.example.com)

Для наглядности, в примере использованы фальшивые детали:
TSP номер аккаунта : 123456789 и DID номер входящий от провайдера IP телефонии (ITSP): 3216111.