Freeradius Xlat

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску

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 \
    ${usergreply_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}')"