NAT, SIP и Asterisk
Трансляция сетевых адресов (NAT) является обычной практикой в сети и нередко мешает прохождению голосовых пакетов (нет звука) и инициализации соединений (нет соединения). Решение этой проблемы требует понимания принципов работы NAT и VoIP. В этой статье рассматривается протокол SIP и Asterisk, но проблемы и решения применимы и к большинству других приложений и протоколов.
NAT используется, чтобы скрыть многочисленные локальные адреса, за каким-то внешним узлом, обеспечивая безопасность и структуризацию сети.
Когда пакет проходит шлюз (gateway), IP-адрес локального источника заменяется на внешний IP-адрес. При ответе шлюз направляет пакет на исходный локальный адрес.
Также шлюз блокирует внешние запросы не имеющие явных внутренних источников, но возможно пробросить пакеты пришедшие на определенные порты, на заранее заданные IP адреса внутри сети.
Если у вас нет звука, нет звука в одну сторону, нет слышимости, прочтите внимательно эту инструкцию.
Reinvite
Первый абонент запрашивает соединение у второго , сообщая свой IP адрес. Второй отвечает, сообщая свой IP. Голосовые пакеты направляются напрямую абонентам, минуя SIP сервер. Передача голосовых пакетов напрямую абонентам, минуя Asterisk, называется RE-INVITE или Native Bridge.
NAT может вызвать проблемы в нескольких местах.
- Если одна из АТС находится за NAT, другая АТС не сможет связаться с ней, без проброса портов.
- Если телефон находится за NAT, голосовые пакеты могут быть направлены на немаршрутизируемый адрес в сети, что приведет к потере звука.
Клиент за NAT
В простейшей ситуации 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
Все усложняется если и 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
sip.conf
Поддержка NAT в Asterisk 12
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
Устройства используемые в примере:
Устройство | 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) |
Для наглядности, в примере использованы фальшивые детали:
ITSP номер аккаунта : 123456789 и DID номер входящий от провайдера IP телефонии (ITSP): 3216111
pjsip.conf конфигурация
Подразумевается, что вы ознакомились со статьей о конфигурации Asterisk pjsip.conf и имеете основные представления о работе Asterisk. Для этого примера, важно отметить опции - local_net, external_media_address и external_signaling_address в transport секции и direct_media в endpoint секции. Остальные параметры могут зависеть от конкретной конфигурации, модели телефона, сетевых настроек, специфики провайдера IP телефонии и т.д.
local_net
Диапазон адресов локальной сети.
external_media_address
Внешний IP адрес используемый для обработки RTP трафика. Когда запрос или ответ на запрос отправляется из Asterisk и IP адрес назначение находится за пределами сетей указанных в параметре 'local_net', а медиа адрес в SDP сообщении из локальной сети, тогда медиа адрес из SDP сообщения перезаписывается значением назначенным в параметре 'external_media_address'.
external_signaling_address
Это тоже самое что и 'external_media_address', только для SIP сигнализации, вместо RTP медиа трафика. Этим двум опциям внешних адресов, должен быть назначен один и тот же IP адрес, если вы, конечно, не хотите разделить сигнальный и медиа трафик и направить на разные IP адреса или сервера.
direct_media
Управляет медиа потоком, направляя RTP трафик непосредственно между конечными точками, или через Asterisk. (вспомните canreinvite из sip.conf) Вместе, использование этих опций, обеспечивает правильное прохождение SIP и RTP пакетами сетевых узлов, а 'direct_media=no' указывает, что именно Asterisk должен обрабатывать медиа трафик. Это важно, т.к. наша система Asterisk имеет локальный IP адрес и провайдер IP телефонии (ITCP) не может маршрутизировать трафик напрямую к нему, поэтому мыдолжны убедится что SIP и RTP трафик возвращается на WAN публичный интернет адрес нашего роутера. В секциях имена которых начинаются с «sip_provider_*», настраиваются входящие и исходящие подключения SIP транка, а в секциях [7777] VoIP телефон.
[transport-udp-nat] type=transport protocol=udp bind=0.0.0.0 local_net=10.10.2.0/24 local_net=127.0.0.1/32 external_media_address=123.123.123.123 external_signaling_address=123.123.123.123 [sip_provider_reg] type=registration transport=transport-udp-nat outbound_auth=sip_provider_auth server_uri=sip:gw1.example.com client_uri=sip:123456789@gw1.example.com contact_user=3216111 retry_interval=60 [sip_provider_auth] type=auth auth_type=userpass password=************ username=123456789 realm=gw1.example.com [sip_provider_endpoint] type=endpoint transport=transport-udp-nat section=from-trunk disallow=all allow=ulaw outbound_auth=sip_provider_auth aors=sip_provider_aor direct_media=no from_domain=gw1.example.com [sip_provider_aor] type=aor contact=sip:gw1.example.com contact=sip:gw2.example.com [sip_provider_identify] type=identify endpoint=sip_provider_endpoint match=203.0.113.1 match=203.0.113.2
[7777] type=endpoint section=from-internal disallow=all allow=ulaw transport=transport-udp-nat auth=7777 aors=7777 direct_media=no [7777] type=auth auth_type=userpass password=********* username=7777 [7777] type=aor max_contacts=2
Удаленные телефоны за NAT
Выше приведенный пример подразумевает, что телефон находится в локальной сети, так же как и сервер Asterisk.
Но может так статься, что Asterisk расположен на внешнем IP адресе, а удаленные телефоны находятся за NAT, или же и Asterisk, и телефоны расположены за NAT, т.е. имеет место двойной NAT?
В этих случаях пригодятся следующие настройки оконечных точек (ENDPOINTS)
media_address
IP адрес используемый SDP для обработки медиа трафика.
В момент создания SDP сообщения, IP адрес назначенный здесь(media_address=1.2.3.4), используется как медиа адрес для потока SDP. At the time of SDP creation, the IP address defined here will be used as the media address for individual streams in the SDP. Помните также , что опция 'external_media_address', заданная в секции transport , установит окончательный адрес для возврата медиа трафика.
rtp_symmetric
Обязательный симметричный RTP. Отправлять RTP назад на тот же адрес/порт с которого он был получен.
force_rport
Поведение обязательно совместимое с RFC 3581, т.е., если rport не указан, отправлять SIP ответы на тот же порт с которого были получены запросы.
direct_media
Управляет медиа потоком, направляя RTP трафик, непосредственно, между конечными точками, или через Asterisk.