Модуль сервера SER - mediaproxy
Обзор.
Модуль Mediaproxy разработан для поддержки автоматического определения и обеспечения работы с большинством существующих SIP клиентов, которые находятся за маршрутизатором с трансляцией адресов - NAT. Это означает, что не будет потребности что-либо конфигурировать для устройств, которые находиться за маршрутизатором с NAT, позволяя им работать с нашим сервером через NAT, с использованием модуля mediaproxy.
Принципы работы
Решение задачи по обеспечению работы с клиентами, которые находятся за маршрутизаторами с NAT, заключается в размещении mediaproxy сервера в промежутке между двумя SIP пользовательскими агентами. Модуль исправляет содержимое SDP сообщений для обеих сторон, указывая им пропускать RTP трафик через mediaproxy, в то время как они думают, что работают напрямую друг с другом.
Для достижения этого результата, сам mediaproxy фактически состоит из 2 компонентов:
- Собственно, сам SER модуль mediaproxy.
- Внешний прокси сервер, который называется MediaProxy (можно найти по ссылке: http://mediaproxy.ag-projects.com).
Чтобы избежать путаницы в этом описании мы будем называть сам модуль mediaproxy - 'модулем' или 'mediaproxy модулем', в то время как mediaproxy сервер будем называть 'прокси сервером', начиная с этого момента.
Прокси сервер может быть запущен на той же машине, где и сам модуль, либо на отдельной машине. Кроме того, имеется возможность, чтобы один модуль управлял несколькими прокси серверами, которые географически разнесены по разным местам. Для получения дополнительной информации об архитектуре MediaProxy, обратитесь к документации, которая идет вместе с ним.
Для обеспечения возможности проксирования потоков между двумя клиентами, у машины(ах), где запущен модуль или прокси сервер должен быть назначен IP адрес из публичной сети.
Модуль будет запрашивать у прокси сервера выделения такого количества сокетов, сколько указано потоков медиаданных (media stream) в теле SDP в SIP сообщениях INVITE/OK. Прокси сервер будет отправлять обратно модулю адреса и номера портов для запрашиваемых медиапотоков. После этого модуль заменит оригинальный IP адрес и порт для RTP протокола в SDP сообщении на предоставленные прокси-сервером. После этого оба клиента будут пробовать соединиться с прокси-сервером вместо того, чтобы соединяться непосредственно друг с другом.
Как только клиенты соединяются с прокси-сервером, он запомнит адреса, с которых пришли RTP данные и будут знать, куда отправлять пакеты, полученные от другой стороны, Это необходимо, т.к. IP адрес и порт, который распределит маршрутизатор с NAT для исходящих потоков, не известны до того, как они выйдут за пределы маршрутизатора с NAT. В тоже время адрес прокси-сервера известен всегда (он выделен из публичной части IP адресов), таким образом, обе наши стороны знают куда соединиться, а затем, после того, как это произойдет, прокси сервер получит IP адрес и порт источников пакетов и сможет переправлять данные между нашими SIP клиентами.
Типы SIP клиентов.
SIP клиенты, которые работают через маршрутизаторы с NAT, используя модуль mediaproxy, называются симметричными клиентами. Такие клиенты имеют особенность, которая заключается в том, что для отправки данных и для их приема используется один и тот же номер порта. Другими словами, если они, например, сконфигурированы на использование порта с номером 5060 для SIP сигнализации, то они будут использовать тот же самый порт, как для отправки данных, так и для их приема. Это должно быть так, как для SIP сообщений, так и для RTP потоков, чтобы клиент имел возможность взаимодействовать с модулем mediaproxy без какой-либо дополнительной настройки на маршрутизаторе с NAT.
Эта особенность очень важна, т.к. единственный способ отправить данные клиенту позади маршрутизатора с NAT состоит в том, чтобы отправить их на тот IP адрес и порт, с которого они поступили к нам. Как только пакет данных отправляется клиентом за NAT во внешний мир, открывается канал связи на NAT маршрутизаторе, который открыт в обоих направлениях в течении некоторого времени (он будет сохранен в активном состоянии в течении некоторого времени после последней попытки отправки данных через это соединение, и его можно поддерживать в активном состоянии, передавая данные через регулярные интервалы времени).
Пока этот канал открыт, любые данные, посланные на реальный IP адрес и порт, который назначил NAT маршрутизатор для IP адреса и порта клиента внутри сети, при отправке им данных (и гарантируется, что это соответствие является уникальным), попадут на IP адрес и порт, который назначен ему внутри сети, с которых он изначально начал их отправлять. Это то, из чего вытекает требование к симметричности клиента. Если они принимают данные на тот же номер порта, с которого их отправляет, то ответные данные, направленные на публичный адрес, (назначенному маршрутизатором с NAT для исходящих пакетов), фактически достигнут порта, на которых принимает данные клиент, находящийся за NAT.
Некоторые SIP клиенты реализуют свои специфические алгоритмы для обнаружения присутствия NAT маршрутизатора на пути до сервера, пробуя самостоятельно определить свой публичный IP адрес, который им назначит NAT маршрутизатор (или просто позволяют вручную выставить этот адрес в конфигурации устройства). Затем используют этот адрес в SIP и SDP сообщениях, вместо их внутреннего IP адреса. Эта ситуация может ввести в заблуждение данный модуль. Т.к. он пытается осуществить прозрачный обход маршрутизатора с NAT и может неправильно определить такого клиента, который фактически находиться за NAT, с тем, который имеет публичный IP адрес. Однако для модуля mediaproxy не важно, применяют ли клиенты эти методы или нет, поскольку он в состоянии самостоятельно справиться с этими ситуациями.
Все это не означает, что mediaproxy не в состоянии работать с асимметричными SIP клиентами, находящимися за NAT, но в таких случаях требуется наличие специальных правил для статической трансляции адресов для NAT маршрутизатора.
Mediaproxy содержит в себе специальную поддержку асимметричных клиентов, он может их обнаруживать и отправлять данные на порт, где клиент их ожидает. Однако этот способ работает только с NAT маршрутизаторами, если для них есть набор правил для статической трансляции адресов, т.к. иначе нет возможности отправить данные на этот внутренний адрес/порт, с которого предварительно не был открыл канал передачи данных через NAT. Однако поддержка асимметричных клиентов является довольно важным моментом, т.к. без этого с ними невозможно будет работать, даже когда они имеют публичные интернет-адреса. Также поддержка таких клиентов, которые находятся за NAT, позволяет работать с ними, если они могут управлять NAT маршрутизатором, чтобы он переправлял данные им предназначенные.
Единственное требование для прозрачной работы через NAT маршрутизаторы с использованием mediaproxy модуля к симметричным SIP клиентам, состоит в том, что они должны быть сконфигурированы для работы с использованием outbound proxy, и этот прокси сервер должен быть запущен с загруженным модулем mediaproxy.
Возможности.
- Обеспечивает прозрачное обслуживание клиентов за маршрутизаторами с NAT, если они используют SIP сервер в качестве outbound proxy server.
- Обрабатывает все медиапотоки, указанные в теле SDP сообщения. Существует ограничение в 64 RTP потока на один сеанс, но это вряд ли является серьезным ограничением в данный момент.
- Может распределять RTP трафик на несколько прокси серверов, которые работают на различных машинах.
- Имеет возможность определить, какой прокси сервер будет использоваться, в зависимости от SIP домена вызывающего или вызываемого абонента (функционал обеспечивает dispatcher модуль прокси сервера).
- Корректно обслуживает асимметричных клиентов. Они могут работать через NAT, если для них указаны статические правила проброса портов.
Экспортируемые параметры.
mediaproxy_socket (string)
Путь в файловой системе до сокета, где прокси сервер ожидает команд из этого модуля.По умолчанию: "/var/run/proxydispatcher.sock".
Пример использования параметра mediaproxy_socket:
...
modparam("mediaproxy", "mediaproxy_socket", "/var/run/proxydispatcher.sock")
...
sip_asymmetrics (string)
Тут указывается путь к файлу, в котором содержаться список регулярных выражений для проверки полей 'User-Agent' или 'Server' в сообщениях от клиентов, для определения того, что они используют асимметричную SIP сигнализацию. Необходим для определения клиентов с асимметричной SIP сигнализацией. Файл с примером можно найти в поддиректории: config/ .По умолчанию: "/etc/openser/sip-asymmetric-clients".
Пример использования параметра sip_asymmetrics:
...
modparam("mediaproxy", "sip_asymmetrics", "/etc/openser/sip-asymmetrics-clients")
...
rtp_asymmetrics (string)
Тут указывается путь к файлу, в котором содержаться список регулярных выражений для проверки полей 'User-Agent' или 'Server' в сообщениях от клиентов, для определения того, что они используют асимметричный RTP протокол. Необходим для определения клиентов, которые используют асимметричный RTP протокол. Файл с примером можно найти в поддиректории: config/ .По умолчанию: "/etc/openser/rtp-asymmetric-clients".
Пример использования параметра rtp_asymmetrics:
...
modparam("mediaproxy", "rtp_asymmetrics", "/etc/openser/rtp-asymmetrics-clients")
...
natping_interval (integer)
Параметр, с значением в виде целого числа, которое определяет, как часто этот модуль будет отправлять пакеты всем зарегистрированным клиентам, находящимся за NAT, для поддержания канала связи в активном состоянии. Значение указывается в секундах.По умолчанию: 60 сек.
Пример использования параметра natping_interval:
...
modparam("mediaproxy", "natping_interval", 20)
...
signaling_ip_avp (string)
Имя для AVP, которая будет содержать IP адрес, с которого поступила SIP сигнализация. Если установлено значение для этой AVP, то она будет использоваться для получения IP адреса источника сигнализации, иначе будет использоваться IP адрес полученного SIP сообщения. Эта AVP предназначена для использования в тех случаях, когда на пути установления вызова содержится более одного прокси сервера, а прокси сервер, на котором был запущен mediaproxy, получает SIP сообщения не непосредственно с пользовательского агента и не может определить IP адрес NAT маршрутизатора, с которого поступила SIP сигнализация. В этом случае первый прокси сервер добавляет SIP заголовок и его значение копируется в signaling_ip_avp на прокси сервере, где запускается mediaproxy, что позволяет получить правильный IP адрес, назначенный NAT маршрутизатором, для SIP сигнализации.По умолчанию: "s:signaling_ip".
Пример использования параметра signaling_ip_avp":
...
modparam("mediaproxy", "signaling_ip_avp", "s:nat_ip")
...
Экспортируемые функции.
client_nat_test(type)
Функция проверяет, находиться ли клиент за NAT или нет. Типы производимых тестов определяются параметром, который представляет собой сумму номеров тестов, которые необходимо выполнить. Тесты определяются следующими числами:- 1 - содержится ли приватный IP адрес (как определено в RFC1918) в поле Contact SIP сообщения.
- 2 - клиент соединился с OpenSER сервером с адреса, который отличается от того, который указан в поле Via.
- 4 - у клиента указан приватный IP адрес (как определено в RFC1918) в самом верхнем поле "Via" SIP сообщения.
Например, вызов client_nat_test("3") в openser.cfg, приведет к выполнению первых двух проверок, указанных выше, и будет возвращено значение true, если хотя бы одна из проверок оказалась успешной, если обе проверки не прошли - функция вернет false.
Эта функция может использоваться из блоков: REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.
Пример использования функции client_nat_test:
...
if (client_nat_test("3")) {
.....
}
...
fix_contact()
Функция заменит IP адрес:Порт в поле "Contact", SIP сообщения, на соответствующие значения из адреса источника полученного SIP сообщения. Для клиентов, которые используют ассиметричную SIP сигнализацию (определяется с помощью проверок в файле, заданном в параметре sip_asymmetrics), значение номера порта изменяться не будет.Обычно вызывается после успешной проверки функцией client_nat_test(type)
Эта функция может использоваться из блоков: REQUEST_ROUTE, ONREPLY_ROUTE, BRANCH_ROUTE.
Пример использования функции fix_contact:
...
if (client_nat_test("3")) {
fix_contact();
}
...
use_media_proxy()
Функция формирует вызов прокси сервера и заменяет IP адреса и номера портов в теле SDP на те, которые вернул прокси сервер для каждого потока медиаданных, которые описаны в SDP. Этим мы указываем, что медиапотоки будут проходить через прокси сервер.Функция вызывается, когда Вы хотите создать сессию с использованием прокси сервера.
Функция имеет следующие коды возврата:
- +1 - сообщение было успешно модифицировано (успешное выполнение)
- -1 - ошибка при обработке сообщения (ошибочный результат)
- -2 - отсутствует SDP сообщение, нечего обрабатывать (ошибочный результат)
Эта функция может использоваться из блоков: REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.
Пример использования функции use_media_proxy:
...
if (method==INVITE) {
use_media_proxy();
}
...
end_media_session()
Функция отправляет вызов прокси серверу с указанием закончить сессии передачи медиаданных, для вызова, который завершился. Указывает прокси серверу освободить ресурсы выделенные для данного вызова, а также занести в лог информацию о совершенном вызове.Функция вызывается, когда сессия должна быть завершена (при приеме сообщений BYE или CANCEL).
Эта функция может использоваться из блоков: REQUEST_ROUTE, ONREPLY_ROUTE, FAILURE_ROUTE, BRANCH_ROUTE.
Пример использования функции end_media_session:
...
if (method==BYE) {
end_media_session();
}
...
Как использовать sip_ping из модуля nathelper.
Модуль nathelper предоставляет дополнительную возможность по поддержанию активного канала через NAT, периодической отправкой (ping) реального SIP сообщения вместо отправки четырех нулевых байтов, этот метод имеет преимущество, которое выражается в том, что обмен является двунаправленным. При этом мы устраняем проблему с теми NAT маршрутизаторами, которые для поддержки канала связи через NAT в активном состоянии используют только те пакеты, которые поступают из внутренней сети (ping, состоящий из 4 нулевых байтов не получает ответа от клиента, который находиться во внутренней сети за NAT).Пример использования sip_ping из модуля nathelper:
...
loadmodule "/lib/openser/modules/mediaproxy.so"
loadmodule "/lib/openser/modules/nathelper.so"
modparam("mediaproxy", "natping_interval", 0)
modparam("nathelper", "rtpproxy_disable", 1)
modparam("nathelper", "natping_interval", 30)
modparam("nathelper", "sipping_from", "sip:ping@sipserver.net")
modparam("registrar", "nat_flag", 6)
modparam("registrar", "sip_natping_flag", 2)
....
....
if (method=="REGISTER") {
setflag(6); # nat
setflag(2); # sip_ping
if (!save("location")) {
sl_reply_error();
}
}
...