Freeradius Xlat: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 8 промежуточных версий этого же участника)
Строка 1: Строка 1:
  +
[[Категория:Linux]]
  +
[[Категория:FreeRadius]]
 
=FreeRadius Xlat=
 
=FreeRadius Xlat=
 
FreeRadius предоставляет интересные возможности для опереривания с данными.
 
FreeRadius предоставляет интересные возможности для опереривания с данными.
Строка 28: Строка 30:
 
</PRE>
 
</PRE>
 
Обратить внимание, что для cisco передается Cisco-AVPair, для VPN на базе Linux я использую атрибуты PPPD-Upstream-Speed-Limit / PPPD-Downstream-Speed-Limit со значением скорости в килобитах (а не в битах как для Cisco) в секунду. Т.к. радиус не знает этих атрибутов, то их следует вписать в словарь.
 
Обратить внимание, что для cisco передается Cisco-AVPair, для VPN на базе Linux я использую атрибуты PPPD-Upstream-Speed-Limit / PPPD-Downstream-Speed-Limit со значением скорости в килобитах (а не в битах как для Cisco) в секунду. Т.к. радиус не знает этих атрибутов, то их следует вписать в словарь.
  +
  +
  +
Но, как можно заметить, авторизация пользователя все равно требует наличия записей в таблице radcheck - хоть и одинаковых для всех. <BR>
  +
Хотелось бы избежать ненужного дублирования информации, однако мне не удалось заставить работать конструкции вида '%{sql: SELECT ... }' для check атрибутов если проверка идет из файла users.
  +
<BR> конструкция вида
  +
<PRE>
  +
DEFAULT Framed-Protocol == PPP, Password := "%{sql:SELECT pwd FROM mtraf WHERE domain='%{User-Name}'}"
  +
...
  +
</PRE>
  +
у меня не заработала.
  +
  +
<BR>Обходным решением является использование групп. Я создал "группу по-умолчанию", для которой один раз в таблице radgroupcheck указал атрибуты для проверки. (группа называется PPTP)
  +
<PRE>
  +
select * from radgroupcheck;
  +
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+
  +
| id | groupname | attribute | op | value |
  +
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+
  +
| 1 | PPTP | Auth-Type | := | `%{sql:SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'REJECT','MS-CHAP') FROM mtraf WHERE domain='%{User-Name}'}` |
  +
| 2 | PPTP | Password | := | `%{sql:SELECT pwd FROM mtraf WHERE domain='%{User-Name}'}` |
  +
| 3 | PPTP | Pool-Name | := | Test-Pool |
  +
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+
  +
</PRE>
  +
и изменил запросы провеки групп, что бы для пользователя который не входит ни в одну группу использовались атрибуты группы "по-умолчанию"
  +
в файле sql.conf:
  +
<PRE>
  +
default_group = "PPTP"
  +
</PRE>
  +
  +
<PRE>
  +
  +
authorize_group_check_query = " SELECT \
  +
${groupcheck_table}.id, \
  +
${groupcheck_table}.GroupName, \
  +
${groupcheck_table}.Attribute, \
  +
${groupcheck_table}.Value,radgroupcheck.op \
  +
FROM \
  +
${groupcheck_table} \
  +
LEFT JOIN ${usergroup_table}\
  +
USING (GroupName) \
  +
WHERE \
  +
${groupcheck_table}.GroupName = '${default_group}' OR \
  +
${usergroup_table}.Username = '%{SQL-User-Name}' \
  +
ORDER BY \
  +
${groupcheck_table}.id"
  +
  +
  +
  +
authorize_group_reply_query = " SELECT \
  +
${groupreply_table}.id, \
  +
${groupreply_table}.GroupName, \
  +
${groupreply_table}.Attribute, \
  +
${groupreply_table}.Value,radgroupcheck.op \
  +
FROM \
  +
${groupreply_table} \
  +
LEFT JOIN ${usergroup_table}\
  +
USING (GroupName) \
  +
WHERE \
  +
${groupreply_table}.GroupName = '${default_group}' OR \
  +
${usergroup_table}.Username = '%{SQL-User-Name}' \
  +
ORDER BY \
  +
${groupreply_table}.id"
  +
  +
  +
group_membership_query = "SELECT IFNULL((SELECT GroupName FROM radusergroup WHERE UserName='%{SQL-User-Name}'),'${default_group}')"
  +
  +
</PRE>
  +
  +
Для того что бы перекрыть адрес из пула, можно использовать атрибут Framed-IP-Address (и, вероятно, любые другие) из таблицы radreply.
  +
После добавления записи:
  +
<PRE>
  +
select * from radreply;
  +
+----+----------+-------------------+----+--------------+
  +
| id | username | attribute | op | value |
  +
+----+----------+-------------------+----+--------------+
  +
| 27 | tan | Framed-IP-Address | := | XX.XX.128.11 |
  +
+----+----------+-------------------+----+--------------+
  +
</PRE>
  +
абонент получает, соответвенно, статический ip. Если в таблице radreply никаких записей для username=tan то будет выда адрес из пула.
  +
  +
==Еще идеи и их реализация==
  +
<PRE>
  +
  +
  +
  +
DROP PROCEDURE GetPool;
  +
delimiter //
  +
CREATE PROCEDURE GetPool(in SQLUserName varchar(64), OnetBorder INTEGER(11) )
  +
begin
  +
DECLARE CurrentId INTEGER(11);
  +
DECLARE CurrentId_Onet INTEGER(11);
  +
DECLARE CurrentId_AB INTEGER(11);
  +
  +
SELECT id INTO CurrentId_Onet FROM mtraf WHERE domain=SQLUserName;
  +
SELECT id INTO CurrentId_AB FROM mtraf WHERE domain=SUBSTRING(SQLUserName,3);
  +
  +
SELECT IFNULL(CurrentID_Onet,CurrentId_AB) INTO CurrentId;
  +
  +
if CurrentId < OnetBorder then
  +
SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'NOPAY-Pool','Pool0') FROM mtraf WHERE domain=SUBSTRING(SQLUserName,3);
  +
  +
else
  +
SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'NOPAY-Pool','Pool0') FROM mtraf WHERE domain=SQLUserName;
  +
end if;
  +
end;
  +
//
  +
delimiter ;
  +
</PRE>

Текущая версия на 11:35, 24 июня 2010

FreeRadius Xlat

FreeRadius предоставляет интересные возможности для опереривания с данными. В моем случае мне не хотелось для каждого абонента делать дублирование данных из биллинга ( в моем случае таблица mtraf) в radcheck и radreply. Проверка Auth-Type - на основании данных из биллинга.

select * from radcheck;
+----+----------+------------------+----+---------------------------------------------------------------------------------------------------------------+
| id | username | attribute        | op | value                                                                                                         |
+----+----------+------------------+----+---------------------------------------------------------------------------------------------------------------+
|  4 | tan      | Simultaneous-Use | := | 1                                                                                                             |
|  7 | tan      | Password         | := | `%{sql:SELECT pwd FROM mtraf WHERE domain='%{User-Name}'}`                                                    |
| 11 | tan      | Auth-Type        | := | `%{sql:SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'REJECT','MS-CHAP') from mtraf  where domain='%{User-Name}'}` |
+----+----------+------------------+----+---------------------------------------------------------------------------------------------------------------+

(обратить внимание на обратные кавычки, в которые взят запрос)
Аналогично, для передачи лимитов по скорости (но вместо того что бы указать для каждого %{User-Name} можно указать значения по умолчани.

#
DEFAULT Framed-Protocol == PPP
        Framed-Protocol = PPP,
        Service-Type = Framed-User,
        Cisco-AVPair += "%{sql:SELECT CONCAT('lcp:interface-config=rate-limit input ',ul_in*1024, ' ', ROUND(ul_in*1000/8), ' ', ROUND(ul_in*1000/8), ' conform-action transmit exceed-action drop') from mtraf where domain='%{User-Name}'}",
        Cisco-AVPair += "%{sql:SELECT CONCAT('lcp:interface-config=rate-limit output ',ul_in*1024, ' ', ROUND(ul_out*1000/8), ' ', ROUND(ul_out*1000/8), ' conform-action transmit exceed-action drop') from mtraf where domain='%{User-Name}'}",
        PPPD-Upstream-Speed-Limit  :=  "%{sql:SELECT ul_in  from mtraf where domain='%{User-Name}'} ",
        PPPD-Downstream-Speed-Limit := "%{sql:SELECT ul_out from mtraf where domain='%{User-Name}'} "

Обратить внимание, что для cisco передается Cisco-AVPair, для VPN на базе Linux я использую атрибуты PPPD-Upstream-Speed-Limit / PPPD-Downstream-Speed-Limit со значением скорости в килобитах (а не в битах как для Cisco) в секунду. Т.к. радиус не знает этих атрибутов, то их следует вписать в словарь.


Но, как можно заметить, авторизация пользователя все равно требует наличия записей в таблице radcheck - хоть и одинаковых для всех.
Хотелось бы избежать ненужного дублирования информации, однако мне не удалось заставить работать конструкции вида '%{sql: SELECT ... }' для check атрибутов если проверка идет из файла users.
конструкция вида

DEFAULT Framed-Protocol == PPP, Password := "%{sql:SELECT pwd FROM mtraf WHERE domain='%{User-Name}'}"
...

у меня не заработала.


Обходным решением является использование групп. Я создал "группу по-умолчанию", для которой один раз в таблице radgroupcheck указал атрибуты для проверки. (группа называется PPTP)

select * from radgroupcheck;
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+
| id | groupname | attribute | op | value                                                                                                        |
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+
|  1 | PPTP      | Auth-Type | := | `%{sql:SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'REJECT','MS-CHAP') FROM mtraf WHERE domain='%{User-Name}'}` |
|  2 | PPTP      | Password  | := | `%{sql:SELECT pwd FROM mtraf WHERE domain='%{User-Name}'}`                                                   |
|  3 | PPTP      | Pool-Name | := | Test-Pool                                                                                                    |
+----+-----------+-----------+----+--------------------------------------------------------------------------------------------------------------+

и изменил запросы провеки групп, что бы для пользователя который не входит ни в одну группу использовались атрибуты группы "по-умолчанию" в файле sql.conf:

default_group =  "PPTP"

authorize_group_check_query = " SELECT \
    ${groupcheck_table}.id, \
    ${groupcheck_table}.GroupName, \
    ${groupcheck_table}.Attribute, \
    ${groupcheck_table}.Value,radgroupcheck.op \
    FROM \
    ${groupcheck_table} \
    LEFT JOIN  ${usergroup_table}\
    USING (GroupName) \
    WHERE \
    ${groupcheck_table}.GroupName = '${default_group}' OR \
    ${usergroup_table}.Username = '%{SQL-User-Name}'  \
    ORDER BY \
    ${groupcheck_table}.id"



authorize_group_reply_query = " SELECT \
    ${groupreply_table}.id, \
    ${groupreply_table}.GroupName, \
    ${groupreply_table}.Attribute, \
    ${groupreply_table}.Value,radgroupcheck.op \
    FROM \
    ${groupreply_table} \
    LEFT JOIN  ${usergroup_table}\
    USING (GroupName) \
    WHERE \
    ${groupreply_table}.GroupName = '${default_group}' OR \
    ${usergroup_table}.Username = '%{SQL-User-Name}'  \
    ORDER BY \
    ${groupreply_table}.id"


group_membership_query = "SELECT IFNULL((SELECT GroupName FROM  radusergroup  WHERE UserName='%{SQL-User-Name}'),'${default_group}')"

Для того что бы перекрыть адрес из пула, можно использовать атрибут Framed-IP-Address (и, вероятно, любые другие) из таблицы radreply. После добавления записи:

select * from radreply;
+----+----------+-------------------+----+--------------+
| id | username | attribute         | op | value        |
+----+----------+-------------------+----+--------------+
| 27 | tan      | Framed-IP-Address | := | XX.XX.128.11 |
+----+----------+-------------------+----+--------------+

абонент получает, соответвенно, статический ip. Если в таблице radreply никаких записей для username=tan то будет выда адрес из пула.

Еще идеи и их реализация




DROP PROCEDURE GetPool;
delimiter //
CREATE PROCEDURE GetPool(in SQLUserName varchar(64), OnetBorder INTEGER(11) )
begin
    DECLARE CurrentId           INTEGER(11);
    DECLARE CurrentId_Onet      INTEGER(11);
    DECLARE CurrentId_AB        INTEGER(11);

    SELECT id INTO CurrentId_Onet       FROM mtraf WHERE domain=SQLUserName;
    SELECT id INTO CurrentId_AB         FROM mtraf WHERE domain=SUBSTRING(SQLUserName,3);

    SELECT IFNULL(CurrentID_Onet,CurrentId_AB) INTO CurrentId;

    if CurrentId < OnetBorder then
         SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'NOPAY-Pool','Pool0') FROM mtraf WHERE domain=SUBSTRING(SQLUserName,3);

    else
         SELECT IF (0n_a<0 OR (debt=0 AND 0n_a=0),'NOPAY-Pool','Pool0') FROM mtraf WHERE domain=SQLUserName;
    end if;
end;
//
delimiter ;