В этой статье мы рассмотрим очень популярный кейс (Kamailio в AWS, GCE, Hetzner и любом другом облаке), когда Kamailio находится в приватной сети с одним сетевым интерфейсом, при этом, со стороны провайдера облачных услуг, на маршрутизаторе настроен NAT. Также рассмотрим настройку SIP сигнализации через TCP и поддержку Proxy Protocol
Kamailio через NAT на одном сетевом интерфейсе. Теория и пратика. Возможные варианты в Cloud
Во всех предыдущих статья рассматривалось, как настроить Kamailio с двумя сетевыми интерфейсами, где на первом интерфейсе настроен публичный (белый) IP адрес напрямую в ВМ, второй сетевой интерфейс — настроен приватный (серый, согласно rfc1918) адрес. В данном случае все довольно просто и понятно. Первый интерфейс — для взаимодействия с внешними (белыми) IP адресами (клиентами, транками через интернет…), второй же — для взаимодействия с media серверами (FreeSWITCH, Asterisk или другой Softswitch 5 класса) или приватными SIP trunk
Kamailio перед NAT, NAT в EC2/ВМ
Но эта парадигма не работает в облаках. Дело в том, что в AWS (Elastic IP), GCE и в остальных облаках, как правило, внешний IP адрес не добавляется напрямую в ВМ (AWS EC2, GCE Compute), а выполняется трансляция сетевых адресов (NAT). Схематично это выглядит следующим образом:
Kamailio через AWS NLB/GCE Cloud Load Balancer/Hetzner Load Balancer
При этом возможен другой сценарий, когда Kamailio стоит перед балансировщиком нагрузки, в AWS это называется Network Load Balancer, в Hetzner — Load Balancer, в Google Cloud — Cloud Load Balancer. Схематично это выглядит следующим образом:
В данном случае, это делается для возможности горизонтального масштабирования самого Kamailio, но клиент при этом обращается не напрямую в Kamailio, а через балансировщик нагрузки, который проверяет доступность Kamailio нод, а также распределяет нагрузку в зависимости от выбранного алгоритма
Настройка Kamailio для работы в облаке с одним сетевым (приватным) интерфейсом
Т.к SIP протокол чувствителен к прохождению NAT и нужно корректно настроить это самое прохождение NAT (Kamailio часть 2. Прохождение NAT в SIP протоколе, разбор прохождения NAT в Kamailio), в ином случае SIP сигнализация будет работать некорректно (например, не будет доходить ACK в первой транзакции, как это рассматривалось в 3 части цикла статей).
Мне известно два варианта для корректного проставления публичных и приватных IP адресов:
1) Один сетевой интерфейс, но слушающий разные порты
2) Два сетевых интерфейса
В этой статье рассматривается первый вариант, когда у нас есть только один сетевой интерфейс, но работающий на разных портах
В самом верху конфигурационного файла приведем listen к следующему виду:
listen=udp:LOCAL_IP:5060 advertise PUBLIC_IP:5060 name "public_socket"
listen=udp:LOCAL_IP:5070 name "private_socket"
listen=tls:LOCAL_IP:7777 advertise PUBLIC_IP:7777 name "public_webrtc_socket"
alias=tls:yourdomain.com:7777
alias=udp:yourdomain.com:5060
Где LOCAL_IP — приватный IP адрес сетевого интерфейса сервера
advertise — сообщает, что в Record-Route и Via заголовках необходимо указать другой IP адрес
PUBLIC_IP — публичный IP адрес (напр. Elastic IP или IP адрес балансировщика)
yourdomain.com — ваш домен (для работы TLS)
ВАЖНО
Не забудьте открыть необходимые порты в ACL/Firewall в случае простого NAT (напр. Elastic IP)
При использовании балансировщика необходимо сделать проброс портов с балансировщика на сервер с Kamailio
Далее воспользуемся модулем corex.so, с помощью set_send_socket_name(sname) есть возможность принудительно указывать, с помощью какого сокета (указывается имя сокета, из строки listen берется name) необходимо выполнить обработку запроса.
Изменим следующие блоки в route[DIALOG]:
route[DIALOG] {
if (has_totag()) {
if (loose_route()) {
handle_ruri_alias();
route(RELAY);
}
}
if (is_method("ACK")) {
if ( t_check_trans() ) {
route(RELAY);
exit;
} else {
exit;
}
}
if (!ds_is_from_list("1", "2") && !ds_is_from_list("2")) {
setflag(tswitch);
set_send_socket_name("private_socket");
........................................................
} else {
setflag(fswitch);
set_send_socket_name("public_socket");
........................................................
Изменение FreeSWITCH dialplan
Также необходимо изменить диалплан для медиа серверов. Сам dialplan настраивался в статье 7
Изменим local_call с sofia/softswitch/${destination_number}@sip.ipcalls24.com на:
<action application="bridge" data="{sip_invite_domain=${sip_from_host}}sofia/softswitch/${destination_number}@yourdomainORipaddr:5070"/>
Теперь сделаем тестовый вызов и посмотрим трассировку через sngrep
И Leg-B:
По трассировке видно, что абонент А отправил SIP INVITE на публичный порт (адрес регистрации) — 5060. Далее, этот вызов пришел на Kamailio, который отправил вызов на media сервера (в нашем случае FreeSWITCH) с source port 5070 на destination port 5090 (настройка через dispatcher рассматривалась ранее)
SIP сигнализация через TCP + Proxy Protocol
В некоторых случаях необходимо обеспечить возможность совершать вызовы не только через UDP, но и через TCP протокол (например, балансировщик не поддерживает UDP). Есть несколько моментов, на которые необходимо обратить внимание
Настройка TCP портов в Kamailio
По аналогии с UDP необходимо настроить прослушивание портов для TCP
В конфигурационный файл, к другим listen директивам добавляем:
listen=tcp:LOCAL_IP:5060 advertise PUBLIC_IP:5060 name "public_tcp_socket"
listen=tcp:LOCAL_IP:5070 name "private_tcp_socket"
Также необходимо изменить параметры, которые идут после listen на следующие:
mhomed=1
tcp_accept_no_cl=yes
tcp_reuse_port=yes
tcp_connection_lifetime=3605
enable_tls=yes
По умолчанию, tcp_connection_lifetime равняется 120 секунд, т.е TCP сессия оборвется через 120 секунд. Некоторые SIP клиенты (софтфоны) умеют делать keepalive самостоятельно, чтобы продлевать время жизни TCP сессии. На это полагаться я бы не советовал, ввиду того, что абоненты могут подключаться с разных аппаратных и софтовых клиентов. Поэтому настройкой tcp_connection_lifetime принудительно задается время жизни сессии в один час.
Настройка tcp_reuse_port разрешает kamailio переиспользовать открытые TCP порты
Теперь, попробовав зарегистрироваться на сервере через софтфон, будет видна следующая ситуация:
Как видно, теперь у нас доступно 3 протокола для регистрации и возможности совершения звонков. Доступен UDP, TCP и TLS (который мы настраивали в статье Kamailio часть 10. Реализация WebRTC в Kamailio с рассмотрением примеров)
Proxy Protocol в Kamailio
Proxy Protocol применяется в тех случаях, когда SIP сервер находится за балансировщиком нагрузки (напр. AWS NLB, HAproxy, Hetzner Load Balancer…). Клиент фактически устанавливает TCP сессию не с SIP балансировщиком, а с балансировщиком нагрузки, который стоит перед ним. Балансировщик нагрузки создает TCP соединение с upstream (в нашем случае — Kamailio) и в качестве исходного IP адреса и/или порта указывает свои собственные, а не настоящего абонента. Для того, чтобы это исправить необходимо включить поддержу Proxy Protocol как на балансировщике, так и на SIP сервере. Proxy Protocol позволяет передать в заголовке PROXY реальный IP адрес клиента, а также используемые порты.
После того, как вы включили Proxy Protocol на вашем балансировщике, необходимо добавить параметр, который включает Proxy Protocol в Kamailio. Ко всем остальным TCP параметрам добавляется:
mhomed=1
tcp_accept_haproxy=yes
tcp_accept_no_cl=yes
tcp_reuse_port=yes
tcp_connection_lifetime=3605
enable_tls=yes
Параметр tcp_accept_haproxy позволяет обрабатывать SIP запросы с PROXY заголовками.
Посмотрим на SIP REGISTER, который пришел через балансировщик нагрузки:
2023/02/03 14:09:17.087555 10.10.8.2:52920 -> 10.*.*.**4:5060
REGISTER sip:ipcalls24.com SIP/2.0
Via: SIP/2.0/TCP 192.168.1.128:43751;branch=z9hG4bK-524287-1---3f660f74b108932e;rport;alias
Max-Forwards: 70
Contact: <sip:[email protected]:43751;rinstance=075ace6eb3d6bece;transport=TCP>
To: "1001"<sip:[email protected]>
From: "1001"<sip:[email protected]>;tag=bc29d013
Call-ID: Y9goKh1s_XWGFDuSYw87xA..
CSeq: 1 REGISTER
Expires: 600
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, SUBSCRIBE, UPDATE, INFO, MESSAGE
Supported: path, replaces, timer, norefersub
User-Agent: SessionTalk 6.0
Content-Length: 0
Видно, что изменился только исходный IP адрес (адрес балансировщика нагрузки), остаьная часть SIP REGISTER приходит без изменений (как было до появление балансировщика)
Настройка RTPengine с одним сетевым интерфейсом
После того, как была настроена корректная SIP сигнализация, также необходимо внести изменения в конфигурационный файл rtpengine (изначальная статья по установке, Kamailio часть 4. Обработка RTP потоков через sipwise RTPengine, взаимодействие SIP протокола с RTP), чтобы в SDP заголовках проставлялся корректный IP (приватный или публичный, в зависимости от плеча)
Внесем в конфигурационный файл rtpengine.conf (или любой другой, указанный в systemd демоне) изменения
[rtpengine]
table = 0
listen-ng = LOCAL_IP:2223
interface = internal/LOCAL_IP;external/LOCAL_IP!PUBLIC_IP
timeout = 60
silent-timeout = 3600
tos = 184
port-min = 10000
port-max = 40000
Обратив внимание на строку interface, мы видим изменения в правой части, в external. Восклицательный знак (!) обозначает тот же смысл, что и advertise. Т.е при отправке SIP сообщения с SDP во внешнюю сеть, будет изменен сам IP адрес на внешний
И убедимся, что в rtpengine_manage корректно проставлены флаги internal и external:
route[RELAY] {
...........................................................
if (has_body("application/sdp") && isflagset(tswitch)) {
rtpengine_manage("ICE=remove replace-origin UDP/RTP external internal");
} else {
if (pcre_match("$dP", "(?i)wss|ws")) {
rtpengine_manage("replace-origin ICE=force SDES=off UDP/TLS/RTP/SAVPF codec-mask=all codec-transcode=PCMA,PCMU internal external");
} else {
rtpengine_manage("ICE=remove replace-origin internal external");
}
}
...........................................................
Заключение
В этой статье мы рассмотрели, как работать в облачных решениях. Какие концепции существуют и как обходить ограничения по NAT. Также рассмотренна TCP сигнализация и параметры регулируемые со стороны Kamailio. В заключении, добавили настройку Proxy Protocol.
Если есть желание сделать пожертвование, то это можно сделать кликнув по ссылке или же нажав на кнопку. Спасибо за поддержку !)
5 ответов к “Kamailio часть 12. Работа в облаке через один сетевой интерфейс, SIP сигнализация через TCP”
Спасибо за замечательный цикл статей!))
Большое спасибо за статьи, очень понятно расписана тема.
Не дошел до сюда но вычитал на других ресурсах про advertise
Белый ip — прроброс 5060 и 10000-2000 на внутренний 192.168.1.33 это кама плюс диспетчер ретранслирует на астер в этой же сети 192.168.1.40. На астере транк с провайдером- прекрасно работает вся эта схема -.
Я так и не смог с камы зарегатся у провайдера , автор мог бы создать на задарме тестовый номер и все это показать —
и побольше схем бы — например 1 kamailio регается у провайдера ,2 kamailio регаються пользователи это для скрытия топологии а на астерах диалплан может так …..
так что пока так но продолжаем изучать и тестировать )))
У Задармы realm (etc.tario.ru) отличается от домена. Если правильно прописать, то всё работает.
Да уже разобрался !