Рубрики
Kamailio

Kamailio часть 11. UAC модуль. Регистрация SIP номера у оператора через Kamailio, Kamailio в роли клиента

В этой статье будет рассмотрено, как взаимодействовать с SIP операторами/провайдерами в качестве клиента через UAC модуль в Kamailio

Теория взаимодействия Kamailio с оператором связи

Для начала кратко вспомним 1 часть (SIP регистрация в Kamailio), где максимально подробно рассматривалась сама регистрация в SIP протоколе.

Kamailio в роли сервера — UAS (User Agent Server)

Kamailio REGISTER trace UAC UAS

Здесь, мой компьютер с установленным 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

Разберем подробно каждый столбец и за что он отвечает (сверху вниз):

  1. id — уникальный идентификатор записи, автоматически увеличивается при INSERT (autoincrement), заполнять не требуется
  2. l_uuid — локальный идентификатор пользователя. Не может быть нулем (not null), необходимо заполнить (обычно, я указываю внешний номер, но вы можете указать любое другое значение)
  3. l_username — локальный логин пользователя, не может быть нулем,необходимо заполнить. Можно указать произвольный логин
  4. l_domain — локальный домен (realm). В случае, если у вас только один домен (например одна организация), то необходимо указать этот домен. Если настроена мультидоменность (multi tenant), то необходимо указать домен к которому будет привязан этот номер.
  5. r_username — указывается логин, который сообщил вам оператор/провайдер для вашего номера.
  6. r_domain — указывается домен (realm), который сообщил вам оператор связи. Может быть как IP адресом, так и DNS записью
  7. realm — указывается такое же значение, как и в r_domain
  8. auth_username — логин для авторизации. Почти всегда указываем такое же значение, как для r_username
  9. auth_password — пароль для авторизации, также сообщает оператор
  10. auth_ha1 — пароль в зашифрованном виде, заполнять не обязательно, достаточно заполненного столбца auth_password. В этой статье использоваться не будет.
  11. auth_proxy — непосредственно сам адрес регистрации, может быть как IP, так и DNS имя. Сообщает также оператор.
  12. expires — время истекания регистрации (в секундах). Т.е сколько номер будет зарегистрирован у оператора.
  13. flags — состояние регистрации. По умолчанию ставим значение 0.
  14. reg_delay — задержка перед отправкой запроса регистрации. Не будет использоваться.
  15. contact_addr — адрес, который будет в заголовке Contact, в сообщении REGISTER. В нашем случае не заполняется, т.к мы переопределили глобально IP адрес через параметр reg_contact_addr
  16. 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 взял эти значения из БД. Есть два варианта:

  1. Перезагрузить демон через systemctl
  2. Через kamcmd

Второй вариант предпочтительней, для этого выполним команду (уже в bash консоли):

kamcmd uac.reg_refresh l_uuid

Вместо l_uuid необходимо подставить значение, которое было указано в БД, в столбце l_uuid, т.е как пример:

kamcmd uac.reg_refresh 111111111

После чего посмотрим статус регистрации с помощью команды:

kamcmd uac.reg_dump

В выводе мы увидим:

И нас интересует значение flags в выводе команды. Существуют следующие флаги:

  1. Значение 1 — регистрация выключена
  2. Значение 2 — регистрация в процессе
  3. Значение 4 — регистрация успешна
  4. Значение 8 — регистрация в процессе авторизации
  5. Значение 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

Вставил все из вашей статьи из нат хелпер
и добавил

#!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 — регистрация инициализирована. Есть ли трассировка?

Проверил логи камаилио, вижу ответ 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 (облако 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

Спасибо автору за дополнение !
Я решил дебажить
вставлял такой код

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 когда провайдер поддерживает множественные регистрации на одном аккаунте.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *