В этой статье будет рассмотрено, как взаимодействовать с SIP операторами/провайдерами в качестве клиента через UAC модуль в Kamailio
Теория взаимодействия Kamailio с оператором связи
Для начала кратко вспомним 1 часть (SIP регистрация в Kamailio), где максимально подробно рассматривалась сама регистрация в SIP протоколе.
Kamailio в роли сервера — UAS (User Agent Server)
Здесь, мой компьютер с установленным SIP клиентом (или WebRTC клиентом). Т.е отправляется запрос SIP REGISTER с моего компьютера в сторону Kamailio и далее выполняется обработка этого REGISTER согласно алгоритму:
Как происходит взаимодействие нашего локального абонента (который регистрируется на нашем SIP сервере) я думаю понятно, но как будет происходить взаимодействие, если мы будем выступать в роли клиента (будем локальным абонентом для вышестоящего оператора/провайдера связи)?
Kamailio в роли UAC (User Agent Client)
Мы, как клиент оператора, должны зарегистрироваться для возможности приема входящих вызовов и возможности совершения исходящих.
Уточню, что возможность приема входящих и совершения исходящих зависят от настройки вашего оператора. Например, у некоторых операторах не обязательно выполнять регистрацию, чтобы оператор отправлял входящие вызовы (которые поступают на ваш арендованный внешний SIP номер) в сторону Kamailio. Также может быть и не обязательна регистрация для совершения исходящих вызовов.
В нашем случае, мы условимся, что оператору требуется предварительная регистрация номера для дальнейшей маршрутизации.
Алгоритм работы ничем не отличается от алгоритма регистрации нашего локального абонента на Kamailio, только при взаимодействии с оператором, мы становимся локальным абонентом, а оператор сервером регистрации.
Обычно, если это какой-то местный провайдер связи, то вам передадут документ с данными вашего арендованного внешнего SIP номера. В этом электронном или физическом документе будут указаны логин (обычно это арендованный номер или его часть, но может быть и другой), пароль, адрес регистрации (в виде dns или IP адреса) и домен (realm).
От нас требуется ввести корректно все предоставленные данные и отправить запрос на регистрацию к провайдеру.
Практическая реализация SIP регистрации у оператора связи с Kamailio UAC
Чтобы Kamailio смог выступать в роли клиента, существует модуль UAC. Загрузим модуль, для этого к другим модулям в конфигурационном файле добавим (но обязательно после загрузки модулей uac, rr):
loadmodule "uac.so"
После чего к остальным modparam добавим:
modparam("uac", "reg_db_url", DBURL)
modparam("uac", "reg_contact_addr", "***.***.***.***:5060")
Первый параметр отвечает за подключение к БД, это также очень подробно рассматривалось в первой части (подключение БД в Kamailio).
Второй параметр более интересный, он опять же очень подробно рассматривался во второй части (Прохождение NAT в Kamailio) . Но кратко напомню, что при регистрации оператор запоминает наш AoR (Address of Record), т.е заголовок Contact из SIP REGISTER сообщения. Поэтому, если в заголовке Contact будет указан некорректный IP адрес, то звонки работать не будут (хотя мы и зарегистрируем номер, но регистрация будет некорректной). Поэтому параметром reg_contact_addr мы указываем наш публичный (или белый) IP адрес, который мы будем отправлять в заголовке Contact.
Давайте посмотрим трассировку SIP REGISTER с Kamailio в сторону оператора связи
И само тело SIP сообщения:
2022/03/12 19:58:39.654610 ***.***.***.***:5060 -> ***.***.***.***:5060
REGISTER sip:******* SIP/2.0
Via: SIP/2.0/UDP ***.***.***.***;branch=z9hG4bK05a8.62653513000000000000000000000000.0
To: <sip:9*****5@***.****.***.**>
From: <sip:9*****5@***.****.***.**>;tag=910ad4f878ce5fa73fee402a3fafb4f9-a0c6f323
CSeq: 10 REGISTER
Call-ID: [email protected]
Max-Forwards: 70
Content-Length: 0
User-Agent: kamailio (5.5.3 (x86_64/linux))
Contact: <sip:number@yourpublicip:5060>
Expires: 60
Т.е reg_contact_addr из параметра модуля отвечает за то, что мы отправляет в заголовке Contact и нам необходимо корректно отправить IP адрес в сторону оператора.
Для ответа на 401 или 407 ответы с требованием авторизации от оператора, нам необходимо добавить failure_route для корректной обработки таких ответов.
В самый низ kamailio.cfg добавляем строки вида:
failure_route[TRUNKAUTH] {
if (t_is_canceled()) {
exit;
}
if(t_check_status("401|407")) {
$avp(auser) = "ЛОГИН_ИЛИ_НОМЕР_ОТ_ПРОВАЙДЕРА";
$avp(apass) = "ПАРОЛЬ_ОТ_ПРОВАЙДЕРА";
$avp(arealm) = "ДОМЕН_ОТ_ПРОВАЙДЕРА";
$rd = "ДОМЕН_ОТ_ПРОВАЙДЕРА";
if (uac_auth()) {
t_relay();
}
exit;
}
}
И в route[RELAY] сошлемся на failure_route добавив:
route[RELAY] {
if (has_body("application/sdp") && isflagset(tswitch)) {
rtpengine_manage("replace-origin external internal");
} else {
rtpengine_manage("replace-origin internal external");
}
t_on_failure("TRUNKAUTH");
t_on_reply("REPLY");
if (isflagset(fswitch)) {
t_relay();
}
if (isflagset(tswitch)) {
if (is_method("INVITE")) {
ds_select_dst("1", "4");
}
t_relay();
}
}
Далее, нам необходимо указать непосредственно данные для регистрации, который сообщил вам ваш провайдер. Для этого мы будем использовать БД (которую ранее подключили через параметр reg_db_url)
По умолчанию используется таблица uacreg, но это можно изменить через параметр:
modparam("uac", "reg_db_table", "uacreg")
Но мы будем использовать таблицу по умолчанию — uacreg.
Сама структура таблицы uacreg следующая:
Table "public.uacreg"
Column | Type | Collation | Nullable | Default
---------------+------------------------+-----------+----------+------------------------------------
id | integer | | not null | nextval('uacreg_id_seq'::regclass)
l_uuid | character varying(64) | | not null | ''::character varying
l_username | character varying(64) | | not null | ''::character varying
l_domain | character varying(64) | | not null | ''::character varying
r_username | character varying(64) | | not null | ''::character varying
r_domain | character varying(64) | | not null | ''::character varying
realm | character varying(64) | | not null | ''::character varying
auth_username | character varying(64) | | not null | ''::character varying
auth_password | character varying(64) | | not null | ''::character varying
auth_ha1 | character varying(128) | | not null | ''::character varying
auth_proxy | character varying(255) | | not null | ''::character varying
expires | integer | | not null | 0
flags | integer | | not null | 0
reg_delay | integer | | not null | 0
contact_addr | character varying(255) | | not null | ''::character varying
socket | character varying(128) | | not null | ''::character varying
Разберем подробно каждый столбец и за что он отвечает (сверху вниз):
- id — уникальный идентификатор записи, автоматически увеличивается при INSERT (autoincrement), заполнять не требуется
- l_uuid — локальный идентификатор пользователя. Не может быть нулем (not null), необходимо заполнить (обычно, я указываю внешний номер, но вы можете указать любое другое значение)
- l_username — локальный логин пользователя, не может быть нулем,необходимо заполнить. Можно указать произвольный логин
- l_domain — локальный домен (realm). В случае, если у вас только один домен (например одна организация), то необходимо указать этот домен. Если настроена мультидоменность (multi tenant), то необходимо указать домен к которому будет привязан этот номер.
- r_username — указывается логин, который сообщил вам оператор/провайдер для вашего номера.
- r_domain — указывается домен (realm), который сообщил вам оператор связи. Может быть как IP адресом, так и DNS записью
- realm — указывается такое же значение, как и в r_domain
- auth_username — логин для авторизации. Почти всегда указываем такое же значение, как для r_username
- auth_password — пароль для авторизации, также сообщает оператор
- auth_ha1 — пароль в зашифрованном виде, заполнять не обязательно, достаточно заполненного столбца auth_password. В этой статье использоваться не будет.
- auth_proxy — непосредственно сам адрес регистрации, может быть как IP, так и DNS имя. Сообщает также оператор.
- expires — время истекания регистрации (в секундах). Т.е сколько номер будет зарегистрирован у оператора.
- flags — состояние регистрации. По умолчанию ставим значение 0.
- reg_delay — задержка перед отправкой запроса регистрации. Не будет использоваться.
- contact_addr — адрес, который будет в заголовке Contact, в сообщении REGISTER. В нашем случае не заполняется, т.к мы переопределили глобально IP адрес через параметр reg_contact_addr
- socket — сокет, который будет использоваться для отправки в сторону провайдера. При наличии нескольких IP адресов, можно указать IP, который будет использоваться для этого номера.
Заполним указанные столбцы, согласно регистрационным данным провайдера. Я это сделаю через SQL запрос (но можно также добавить и через kamcmd uac.reg_add).
Для этого подключаемся к БД, с которой взаимодействует Kamailio (к БД, которая указана в параметре reg_db_url) и выполняем SQL запрос:
INSERT INTO uacreg (l_uuid, l_username, l_domain, r_username, r_domain, realm, auth_username, auth_password, auth_proxy, expires, flags, reg_delay, socket) VALUES ("111111111", "111111111", "operator1", "111111111", "operator1", "operator1", "111111111", "supersecretpwd", "sip:1.2.3.4:5060", 60, 0, 0, 0)
Там, где выделено, необходимо подставить значения, которые передал вам оператор.
После того, как значения добавлены в базу данных, нам необходимо, чтобы Kamailio взял эти значения из БД. Есть два варианта:
- Перезагрузить демон через systemctl
- Через kamcmd
Второй вариант предпочтительней, для этого выполним команду (уже в bash консоли):
kamcmd uac.reg_refresh l_uuid
Вместо l_uuid необходимо подставить значение, которое было указано в БД, в столбце l_uuid, т.е как пример:
kamcmd uac.reg_refresh 111111111
После чего посмотрим статус регистрации с помощью команды:
kamcmd uac.reg_dump
В выводе мы увидим:
И нас интересует значение flags в выводе команды. Существуют следующие флаги:
- Значение 1 — регистрация выключена
- Значение 2 — регистрация в процессе
- Значение 4 — регистрация успешна
- Значение 8 — регистрация в процессе авторизации
- Значение 16 — данные загружены из БД, регистрация инициализированна
В нашем случае, в flags указано значение 20, что означает, что регистрация прошла успешно. Это значение включает в себя два флага, флаг 16 (данные загруженны из БД, выполняется инциализация) и флаг 4 (регистрация успешна).
Заключение
В этой статье мы рассмотрели модуль UAC и как выполнять регистрацию у оператора связи. В следующей статье мы настроим входящие вызовы со стороны оператора к нам, настроим dialplan (со стороны FreeSWITCH) и примем первый входящий вызов.
Если есть желание сделать пожертвование, то это можно сделать кликнув по ссылке или же нажав на кнопку. Спасибо за поддержку !)
26 ответов к “Kamailio часть 11. UAC модуль. Регистрация SIP номера у оператора через Kamailio, Kamailio в роли клиента”
oadmodule «pv.so»
loadmodule «ctl.so»
loadmodule «jsonrpcs.so»
loadmodule «tm.so»
loadmodule «textops.so»
loadmodule «sl.so»
loadmodule «usrloc.so»
loadmodule «registrar.so»
loadmodule «auth.so»
loadmodule «db_postgres.so»
loadmodule «auth_db.so»
loadmodule «siputils.so»
loadmodule «nathelper.so»
loadmodule «uac.so»
С включенным модулем не запускается :/etc/kamailio# systemctl restart kamailio
Job for kamailio.service failed because the control process exited with error code.
See «systemctl status kamailio.service» and «journalctl -xe» for details.
Сам модуль присутствует
find / -name uac.so -print
/usr/lib/x86_64-linux-gnu/kamailio/modules/uac.so
Доброго дня!
Что в выводе команды kamailio -c ?
И прописаны ли параметры reg_db_url, reg_contact_addr?
Вставил все из вашей статьи из нат хелпер
и добавил
#!define DBURL «postgres://kamailio:[email protected]:5432/kamailio»
loadmodule «pv.so»
loadmodule «ctl.so»
loadmodule «jsonrpcs.so»
loadmodule «tm.so»
loadmodule «textops.so»
loadmodule «sl.so»
loadmodule «usrloc.so»
loadmodule «registrar.so»
loadmodule «auth.so»
loadmodule «db_postgres.so»
loadmodule «auth_db.so»
loadmodule «siputils.so»
loadmodule «nathelper.so»
loadmodule «uac.so»
#############[Подключение к БД]###########
modparam(«auth_db», «db_url», DBURL); # указываем URL для подключения, берем его из ранее созданной директивы DBURL
modparam(«uac», «reg_db_url», DBURL)
#тут мой внешний адрес
modparam(«uac», «reg_contact_addr», «0.0.0.200:5060»)
modparam(«uac», «reg_db_table», «uacreg»)
request_route {
if (is_method(«INVITE») || is_method(«REGISTER»)) {
route(NAT);
}
if (is_method(«REGISTER»)) {
route(AUTH);
}
}
route[AUTH] {
if (!auth_check(«$fd», «subscriber», «1»)) {
force_rport();
auth_challenge(«$fd», «1»);
exit;
}
force_rport();
if (is_method(«REGISTER»)) {
save(«location»);
exit;
} else {
return;
}
}
route[NAT] {
if (nat_uac_test(«19»)) {
if (is_method(«REGISTER»)) {
set_contact_alias();
} else {
if(is_first_hop()) {
set_contact_alias();
}
}
}
return;
}
##########################
systemctl restart kamailio
Job for kamailio.service failed because the control process exited with error code.
See «systemctl status kamailio.service» and «journalctl -xe» for details.
root@debiandc:~# kamailio -c
0(1692146) WARNING: [core/socket_info.c:1480]: fix_hostname(): could not rev. resolve 10.30.7.100
0(1692146) WARNING: [core/socket_info.c:1480]: fix_hostname(): could not rev. resolve 10.30.7.100
Listening on
udp: 127.0.0.1:5060
udp: 10.30.7.100:5060
tcp: 127.0.0.1:5060
tcp: 10.30.7.100:5060
Aliases:
tcp: localhost:5060
udp: localhost:5060
config file ok, exiting…
Проигнорировал
Ваше сообщение сорян
Чтобы Kamailio смог выступать в роли клиента, существует модуль UAC. Загрузим модуль, для этого к другим модулям в конфигурационном файле добавим (но обязательно после загрузки модулей uac, rr):
Не заработает у вас uac ребята если вы не сделаете так
Найдите строку:
modparam («rr», «append_fromtag», 0)
и замените его на:
modparam («rr», «append_fromtag», 1)
У меня почему-то сервер присылает ответ 401, а повторной реоистрации камаилио не отправляет, и регистрация умирает на статусе 401. Что идет не так?
Не могу понять, почему на ответ с внешнего сервера 401 Kamailio не отправляет ответ с аутентификационными данными, флаги остаются в значении 16 или 17, через промежуток времени, когда регистрация истекает. Проблема в настройках провайдера или что-то должно быть допрописано в kamailio?
На всякий случай уточню, что сервер супер-минимальный и на момент написания комментария нет media сервера (типо FreeSwitch), только Кама.
Флаг 17 означает, что регистрация выключена. Флаг 16 — регистрация инициализирована. Есть ли трассировка?
Выглядит вот так: https://ibb.co/JjSxnFx
Проверил логи камаилио, вижу ответ 408 от сервера регистрации, погуглил его, нашел следующее:
SIP/2.0 408 Request Timeout — время обработки запроса истекло: Абонента не удалось найти за отведенное время
SIP/2.0 408 Login timed out — за отведенное время не получен ответ от сервера на запрос авторизации
Если я правильно понимаю, то вследствие неотправки данных логин/пароль регистрация просто уходит на таймаут.
Свою проблему разрешил. Оставлю подсказки тем, кто наткнется на мои грабли. У билайна realm отличается от r_domain, найти корректный realm можно через sngrep в ответе билайна 401, auth_username должен состоять из r_username + @ip.beeline.ru. В остальном подвохов нет.
Автору большое спасибо за статью, попробую связать kamailio с freeswitch по вашим статьям.
Эхх, как жаль что следующая часть так и не вышла.
У меня нерешаямая проблема именно во входящих вызовах, звонок соединяется корректно, а вот звука нет, RTP трафик вообще в sngrep не виден(
Добрый день!
Статья скоро выйдет.
Какая проблема со звуком? rtpengine модуль настроен корректно? Локальные вызовы проходят?
Локальные вызовы проходят, исходящие тоже, проблема исключительно во входящих, связанных с модулем UAC.
Вместо rtpengine использую rtpproxy, но настройки такие же, как в 4м шаге; в SDP везде IP публичные. При этом в sngrep вообще не видно RTP потоков ни при исходящих, ни при входящих вызовах (возможно, особенности PSTN);
Сетевой интерфейс за NAT? И открыты ли UDP порты (10000-40000 в зависимости от настройки rtpengine/rtpproxy)?
Симметрчиный NAT (облако Yandex), все порты открыты. Решил свою проблему.
1)Установил RTPEngine (это не помогло)
2)Перевел телефоны на протокол TCP
3)???
4)PROFIT (появился звук)
Автору спасибо, материально также поддержу.
А яндекс клауд умеет в UDP? Kamailio стоит за каким-либо балансировщиком (+ есть ли ACL) или же напрямую NAT’тится в виртуалку?
Вроде как умеет, т.к. паралелльно на втором облаке стоит Asterisk и у него проблем с UDP не возникает.
По сетевым настройкам мне очень сложно сказать, но скорее всего натится напрямую в виртуалку (у каждой виртуалки свой выделенный статический айпишник).
В tcpdump видны UDP датаграммы? Если нет — то не доходит до сетевого интерфейса и может быть iptables/ufw/firewalld.
У вас наверно условие белый ip на kamailio ?
А как быть тем кто за натом ?
Отсылает register в ответ 401 и все
скрин kamailio
https://drive.google.com/file/d/1o_lRj5rAUkxP6Epf92-dO597ilokIQhN/view?usp=share_link
Asterisk
https://drive.google.com/file/d/1_R0hK9tItu5KQOKyqG7CjMAXAGbqJlzq/view?usp=share_link
Asterisk при этом сам подставляет все адреса внешние и норм регается ПОМОГИТЕ если есть время
Да и как быть если кама на 10.20.7.103 исходящий белый ip у нее 109.109.109.20 , а абоненты регаются по доменному имени maydns.sytes.net и по тунелю в каму на 10.20.7.103
Добрый день. Для работы за NAT’ом нужно донастроить конфиг.файл по статье
https://blog.ipcalls24.com/kamailio-behind-nat-in-cloud/
Обновил статью, добавил failure_route, почему-то в финальную версию забыл добавить.
Если не заработает, напишите в tg, постараюсь помочь @maxqwe11
Kamailio register -> 401
https://ibb.co/xq2M0S5
Астериск из той же сети
https://ibb.co/DRHcVKt
Спасибо автору за дополнение !
Я решил дебажить
вставлял такой код
route[RELAY] {
xlog(» — voshli v RELAY —\n»);
if (has_body(«application/sdp»)) {
rtpengine_manage(«replace-session-connection replace-origin ICE=remove direction=internal direction=external»);
}
xlog(» —PERED FAILURE—\n»);
t_on_failure(«TRUNKAUTH»);
xlog(» — posle TRANKAUTH —\n»);
t_on_reply(«REPLY»);
if (isflagset(fswitch)) {
t_relay();
}
С помощью команды
tail -f /var/log/syslog | grep kamailio
И вижу что в RELAY я попадаю тока после набора номера
May 15 12:14:34 : — request_route —
May 15 12:14:34 : — prigaem v REQINIT —
May 15 12:14:34 : — vozvrat iz REQINIT —
May 15 12:14:34 : — voshli v RELAY —
May 15 12:14:34 : —PERED FAILURE—
May 15 12:14:34 : — posle TRANKAUTH —
Таким образом сервер kamilio не смог заставить отвечает на 401 (чтобы обработать ответ и отправить повторный запрос REGISTER с заголовком Authorization) он как будто ее игнорирует —
Вообще ситуация такая : вчитываясь в log видел такую ошибку
kama-vb /usr/sbin/kamailio[40928]: ERROR: {2 10 REGISTER [email protected]} uac [uac_reg.c:946]: uac_reg_tm_callback(): realms do not match. requested realm: [sip.zadarma.com]
А регистрироваться пытался на sip.novofon.com
Вот правильная регистрация
1,»972008″,»972008″,»vash-dns-kamailio»,»972008″,»sip.zadarma.com»,»sip.zadarma.com»,»972008″,»vashparol»,»»,»sip:sip.zadarma.com:5060″,60,0,0,»0″
https://ibb.co/kMpF156
modparam(«uac», «reg_db_url», DBURL)
modparam(«uac», «reg_db_table», «uacreg»)
modparam(«uac», «reg_timer_interval»,20)
modparam(«uac», «reg_retry_interval»,120)
modparam(«uac», «reg_contact_addr», «vash-dns-kamailio:5060»)
#!ifdef WITH_BLOCK401407
# block call redirect based on 401, 407 replies.
if (t_check_status(«401|407»)) {
if (uac_auth()) {
route(RELAY);
} else {
xlog(«L_INFO», «UAC_AUTH(): credentials not found»);
}
}
}
│REGISTER sip:sip.zadarma.com SIP/2.0
10.20.7.103:5060 185.45.152.174:5060│Via: SIP/2.0/UDP vash-dns-kamailio:5060;branch=z9hG4bK6059.cefd21c7000000000000000000000000.0
──────────┬───────── ──────────┬─────────│To:
09:40:27.985631 │ REGISTER │ │From: ;tag=4b3747ba0727a9c595cdfc7769407429-de98f323
+0.066412 │ ──────────────────────────> │ │CSeq: 11 REGISTER
09:40:28.052043 │ 401 Unauthorized │ │Call-ID: [email protected]
+0.000687 │ │ │User-Agent: kamailio (5.4.4 (x86_64/linux))
09:40:28.126043 │ 200 OK │ │Contact:
│ <────────────────────────── │ │Expires: 60
│ │ │Authorization: Digest username="972008", realm="sip.zadarma.com", nonce="ZGSUKGRkkvwx0JIe5JL1h1N7qRsc1tlP", uri="sip:sip.zadarma.com", qop=auth
│ │ │nc=00000001, cnonce="2140972592", response="0bc3cf64fcc3f9f16060fc4b4201be97", algorithm=MD5
https://ibb.co/R67vdp2
Жаль что нет форматирования )))
Все таки стоит смотреть логи и разбираться в них !
А можете подсказать по модулю carrierroute — а то получается так зарегались мы у оператора связи, а трафик отправить на него тоже бы нужно
Подскажите, а можно ли каким-то образом при регистрации на удаленном сервере в поле Contact передавать параметр «q»? Например, Contact: ;q=0.5
Нужно для реализации serial forking когда провайдер поддерживает множественные регистрации на одном аккаунте.