Выкладываю рецепт динамики с freeradius, суть его примерно как в предпоследнем посте от ув. Arti на этой странице: viewtopic.php?t=6980&postdays=0&postorder=asc&start=15
1. Пулы прописываются на NAS'ах. Выдаются IP-адреса из пулов - когда от радиуса не приходит аттрибут Framed-IP-Address.
2. У нас статические ипы выдаются из отдельного диапазона, поэтому если в билинге привязан 93.157.x.x - выдаётся Framed-IP-address, иначе - Framed-Pool.
Код: Выделить всё
authorize_reply_query = "SELECT '','%{SQL-User-Name}','Framed-IP-Address',inet_ntoa( ip_groups.ip & 0xffffffff ) AS ip,'=' \
FROM UTM5.ip_groups WHERE uname ='%{SQL-User-Name}' AND is_deleted = '0' \
AND inet_ntoa( ip_groups.ip & 0xffffffff ) LIKE '93.157.%' \
UNION SELECT '', '%{SQL-User-Name}', 'Framed-Pool', 'mainpool', '=' FROM ip_groups \
WHERE uname ='%{SQL-User-Name}' AND inet_ntoa( ip_groups.ip & 0xffffffff ) NOT LIKE '93.157.%' \
UNION select '', '%{SQL-User-Name}', 'Mikrotik-Rate-Limit', radius_data.value, '=' \
FROM radius_data \
WHERE radius_data.owner_id=( select sl.service_id FROM ip_groups ig, iptraffic_service_links isl, service_links sl \
where ig.uname='%{SQL-User-Name}' and ig.is_deleted=0 and ig.ip_group_id=isl.ip_group_id \
and isl.is_deleted=0 and isl.id=sl.id and sl.is_deleted=0) \
AND radius_data.vendor=14988"
3. Чтобы при этом считался трафик по netflow, необходимо выданный IP привязывать к аккаунту пользователя. Для этого я подключил rlm_perl с использованием единственной функции - accounting.
Можно, в принципе, использовать и rlm_exec, но перл загружается при старте радиуса, а exec - каждый раз при вызове, что гораздо более ресурсоёмко.
/etc/raddb/radiusd.conf:
Код: Выделить всё
modules {
perl {
module = /etc/raddb/rad.pl
}
..........
}
/etc/raddb/sites-enabled/default:
Код: Выделить всё
accounting {
detail
sql
perl
}
/etc/raddb/rad.pl -- это прилагаемый к поставке фрирадиуса example.pl с переделанной ф-ией accounting.
rad.pl:
Код: Выделить всё
use strict;
use DBI;
my $DBH = DBI->connect("DBI:mysql:database=UTM5;host=localhost", "xxx", "xxx");
$DBH->{mysql_auto_reconnect}=1;
my $sth = "";
my $URFA_CALL = "/netup/utm5/bin/utm5_urfaclient ";
.....................
# Function to handle accounting
sub accounting {
# Тут проверяется, не из диапазона ли реальных внешников выдан IP
if($RAD_REQUEST{'Acct-Status-Type'} eq 'Start' && not($RAD_REQUEST{'Framed-IP-Address'} =~ m/93.157.(xxx|yyy|zzz|zxc|cxz).[0-9]+/i) )
{
my $fip = $RAD_REQUEST{'Framed-IP-Address'};
my $uname = $RAD_REQUEST{'SQL-User-Name'};
my $sessid = $RAD_REQUEST{'Acct-Session-Id'};
# 1. Find ip-goup with this (dynamic) ip AND! empty login (just ensure it's dynamic) AND remove it
$sth = $DBH->prepare("SELECT ip_group_id FROM `ip_groups` where `ip`=inet_aton('$fip') AND uname='' AND is_deleted=0");
$sth->execute;
if($sth->rows)
{
while(my $ref = $sth->fetchrow_arrayref)
{
my $ipg_id = $$ref[0];
`$URFA_CALL -a iphome_delete_from_ipgroup -ip_group_id $ipg_id -ip_address "$fip"`;
}
}
# 2. Find connected user info AND add this ip to hem:
$sth = $DBH->prepare("SELECT service_links.id as slink_id, service_links.service_id as service_id,
users.id as uid, accounts.id as aid, periodic_service_links.discount_period_id AS did
FROM ip_groups
INNER JOIN iptraffic_service_links isl ON isl.ip_group_id=ip_groups.ip_group_id
INNER JOIN service_links ON service_links.id=isl.id
INNER JOIN periodic_service_links ON periodic_service_links.id=service_links.id
INNER JOIN accounts ON accounts.id=service_links.account_id
INNER JOIN users ON users.basic_account=accounts.id
WHERE ip_groups.uname='$uname' AND ip_groups.is_deleted=0
AND isl.is_deleted=0
AND accounts.is_deleted=0
AND users.is_deleted=0");
$sth->execute;
while(my $ref = $sth->fetchrow_arrayref)
{
my $slink_id = $$ref[0];
my $service_id = $$ref[1];
my $uid = $$ref[2];
my $aid = $$ref[3];
my $did = $$ref[4];
`$URFA_CALL -a iphome_add_ip -user_id $uid -account_id $aid -slink_id $slink_id -service_id $service_id -ip_address "$fip" -discount_period_id $did`;
}
}
return RLM_MODULE_OK;
}
/netup//utm5/xml/iphome_delete_from_ipgroup.xml
Код: Выделить всё
<?xml version="1.0"?>
<urfa>
<parameter name="ip_group_id"/>
<parameter name="ip_address"/>
<call function="rpcf_delete_from_ipgroup_by_ipgroup"/>
</urfa>
Код: Выделить всё
<?xml version="1.0"?>
<urfa>
<parameter name="user_id"/>
<parameter name="account_id"/>
<parameter name="slink_id"/>
<parameter name="service_id"/>
<parameter name="service_type" value="3"/>
<parameter name="discount_period_id"/>
<parameter name="ip_address"/>
<parameter name="ip_not_vpn" value="0"/>
<parameter name="mask" value="255.255.255.255"/>
<parameter name="return_type" value="integer_return"/>
<call function="rpcf_add_service_to_user"/>
</urfa>
Если кому нужно - пользуйтесь, если у кого есть советы по шлифовке - буду весьма рад =)
P.S. При таком способе не нужно заморачиваться с коммутируемым доступом, сиречь переделывать все тарифы и (в моём случае больше 10к) всех юзеров.
Ещё один плюс - реально делать динамику не глобально, а, например, на отдельном VPN-сервере с отдельным радиусом, и обкатывать хоть до посинения без, опять же, изменения тарифов/услуг в билинге.