Произошел очередной инцидент с исходящим VoIP-трафиком в Колумбию, Гандурас и прочую Зимбабву с аккаунта одного из клиентов. Система мониторинга своевременно оповестила нас о происходящем. Аккаунт был заблокирован до выяснения обстоятельств.В процессе разборов было выяснено, что в этот раз пароли были достаточно криптостойкими, логины более 8 символов да и попыток подбора вообще не было — злоумышленники просто авторизовались с пакистанских адресов и стали понемногу сливать трафик. Клиент попросил реализовать возможность авторизации только с его IP адресов.
В данном случае авторизация проходит на OpenSER.
Решением стало использование функции allow_uri модуля permissions.
Функция работает следующим образом:
при поступлении запроса на авторизацию создается пара в форме (From URI и псевдопеременная) и
- авторизация разрешается, если пара соответствует хотя бы одной записи в файле allow;
- авторизация запрещается, если пара соответствует хотя бы одной записи в файле deny;
- авторизация разрешается (действие по умолчанию).
И все было бы совсем просто, если бы клиент не находился за NAT’ом…
Для решения проблемы авторизации из-за NAT`а на OpenSER проанализируем при помощи функции nat_uac_test запрос на регистрацию пришел из-за NAT или нет. Если клиент находится за NAT’ом, то вызываем функцию fix_nated_register для добавления к полю Contact атрибута «received», содержащего реальный IP, при ответе 200 OK и сохранения в локальной БД OpenSER’a.
Файлы с правилами allow и deny, с именем my-register, ищутся в директории с конфигом OpenSER с соответствующими расширениями.
В моем случае это будут:
/usr/local/etc/openser/my-register.allow
«^sip:00412345678» : «^192\.168\.137\.250$»
/usr/local/etc/openser/my-register.deny
«^sip:00412345678» : ALL
Немного изменяем конфиг самого OpenSER, загружаем модуль:
loadmodule «permissions.so»
…skiped…
а так же для метода REGISTER:
if(nat_uac_test("19")){
xlog("L_INFO", "NATed REGISTER [$fU@$si]\n");
fix_nated_register();
}
if (allow_uri("my-register","$si")){
if(!www_authorize("sip.mydomain.com", "subscriber")){
xlog("L_NOTICE", "Register authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
www_challenge("sip.mydomain.com", "0");
exit;
}
}else{
xlog("L_NOTICE", "Register denied by config - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
sl_send_reply("403", "Register authentication failed");
exit;
}
…skiped…
и для метода INVITE:
if(nat_uac_test("19")){
xlog("L_INFO", "NATed REGISTER [$fU@$si]\n");
fix_nated_register();
}
if (allow_uri("my-register","$si")){
if(!proxy_authorize("sip.mydomain.com", "subscriber")){
xlog("L_NOTICE", "Proxy authentication failed - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
proxy_challenge("sip.mydomain.com", "0");
exit;
}
}else{
xlog("L_NOTICE", "Proxy denied by config - M=$rm RURI=$ru F=$fu T=$tu IP=$si ID=$ci\n");
sl_send_reply("403", "Proxy authentication failed");
exit;
}
Рестартим OpenSER для применения изменений и пользуемся расширившимся функционалом.
Ниже приведены возможные варианты дебага:
Debug при методе REGISTER и нахождении IP в списке разрешенных:
NATed REGISTER [00412345678@192.168.137.250]
May 5 21:14:19 [16176] DBG:permissions:allow_uri: looking for From: sip:00412345678@sip.mydomain.com;transport=UDP URI: 192.168.137.250
May 5 21:14:19 [16176] DBG:permissions:allow_uri: allow rule found => URI is allowed
May 5 21:14:19 [16176] DBG:core:parse_headers: flags=4000
May 5 21:14:19 [16176] DBG:auth:pre_auth: credentials with given realm not found
Register authentication failed - M=REGISTER RURI=sip:sip.mydomain.com;transport=UDP F=sip:00412345678@sip.mydomain.com;transport=UDP T=sip:00412345678@sip.mydomain.com;transport=UDP IP=192.168.137.250 ID=MDhjYjQwOTZjMzFjNGNmMDcwNzI1NTU0ODA1Zjg1MTU.
Debug при методе REGISTER и нахождении IP в списке запрещенных:
NATed REGISTER [00412345678@192.168.137.250]
May 5 21:10:54 [13758] DBG:permissions:allow_uri: looking for From: sip:00412345678@sip.mydomain.com;transport=UDP URI: 192.168.137.250
May 5 21:10:54 [13758] DBG:permissions:allow_uri: deny rule found => URI is denied
Register denied by config - M=REGISTER RURI=sip:sip.mydomain.com;transport=UDP F=sip:00412345678@sip.mydomain.com;transport=UDP T=sip:00412345678@sip.mydomain.com;transport=UDP IP=192.168.137.250 ID=NDA2Y2NlMGFjNzZjN2YwZDJjYjllYzUxNDJlYmEzYjA.
Debug при методе INVITE и нахождении IP в списке разрешенных:
NATed REGISTER [00412345678@192.168.137.250]
May 5 20:19:20 [13299] DBG:permissions:allow_uri: looking for From: sip:00412345678@sip.mydomain.com;transport=UDP URI: 192.168.137.250
May 5 20:19:20 [13299] DBG:permissions:allow_uri: allow rule found => URI is allowed
May 5 20:19:20 [13299] DBG:core:parse_headers: flags=10000
May 5 20:19:20 [13299] DBG:auth:pre_auth: credentials with given realm not found
Proxy authentication failed - M=INVITE RURI=sip:8499XXXXXXX@sip.mydomain.com;transport=UDP F=sip:00412345678@sip.mydomain.com;transport=UDP T=sip:8499XXXXXXX@sip.mydomain.com;transport=UDP IP=192.168.137.250 ID=NTkxNDhiMTlmOWNiOWY1MjM2Nzk0YTY3ODgxNzYzMjU.
Debug при методе INVITE и нахождении IP в списке запрещенных:
NATed REGISTER [00412345678@192.168.137.250]
May 5 20:26:04 [13758] DBG:permissions:allow_uri: looking for From: sip:00412345678@sip.mydomain.com;transport=UDP URI: 192.168.137.250
May 5 20:26:04 [13758] DBG:permissions:allow_uri: deny rule found => URI is denied
Proxy denied by config - M=INVITE RURI=sip:8499XXXXXXX@sip.mydomain.com;transport=UDP F=sip:00412345678@sip.mydomain.com;transport=UDP T=sip:8499XXXXXXX@sip.mydomain.com;transport=UDP IP=192.168.137.250 ID=MDk0YTQ1ODMzZjE0ODAxZDMwMGYxZjU1YmIyOTc4ZWY.
Полезные ресурсы по теме:
- http://www.opensips.org/Resources/DocsCoreVar14
- http://www.opensips.org/html/docs/modules/1.4.x/permissions.html
- http://voip.rus.net/tiki-index.php?page=SER+module+permissions
- http://www.opensips.org/html/docs/modules/1.4.x/nathelper.html
З.Ы. При копировании статьи ссылка на источник ОБЯЗАТЕЛЬНА ! Пожалуйста, уважайте чужой труд.
Автор: Панфилов Алексей (lehis (at) subnets.ru)