第十四节:Daloradius限制上网流量

本节内容主要通过在Daloradius下配置Freeradius,可以按月限制用户的流量,Freeradius本身没有内置限制用户每个月最大流量的功能。网上有很多类似的文章,但是都是针对freeradius版本2的文档。由于版本3在很多地方与2有细微差别,直接用版本2的设置方法是行不通的。

这里总结整理了freeradius3的环境下每月流量限制功能的设置方法

1、增加radius自定义属性

编辑字典文件:

vi /etc/raddb/dictionary

在最下方增加两行自定义属性

ATTRIBUTE Max-Monthly-Traffic  3003 integer
ATTRIBUTE Monthly-Traffic-Limit    3004    integer

2、配置计数器SQL

1)新建月流量的计数器sql语句,下面的文件没有需要新增

vi /etc/raddb/mods-config/sql/counter/mysql/monthlytrafficcounter.conf

内容如下

query = "SELECT SUM(acctinputoctets + acctoutputoctets) DIV 1048576 FROM radacct WHERE UserName='%{${key}}' AND UNIX_TIMESTAMP(AcctStartTime) > '%%b'"

重要说明:在radius 中的结果是以B来统计的,上面的语句中查询结果除以 1048576 将单位转换为MB,如果此处不 除以 1048576 ,最大只能限制2G,因为 int 最大为 2G

1KB=1024B;

1MB=1024KB=1024×1024B=1048576B

2)在sqlcounter模块中增加新的计数器

编辑sqlcounter文件

vi /etc/raddb/mods-available/sqlcounter

在最下面一行追加以下内容,注意,如果本文件中有其他内容,请注视掉

sqlcounter monthlytrafficcounter {
        sql_module_instance = sql
        #dialect = ${modules.sql.dialect}
        dialect = "mysql"
        counter_name = Monthly-Traffic
        check_name = Max-Monthly-Traffic
        reply_name = Monthly-Traffic-Limit
        key = User-Name
        reset = monthly
        $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf
}

启用sqlcounter模块

cd /etc/raddb/mods-enabled
ln -s ../mods-available/sqlcounter sqlcounter

3、将monthlytrafficcounter模块添加到用户认证过程中

编辑以下文件

vi /etc/raddb/sites-enabled/default

在authorize部分中的sql后面,添加monthlytrafficcounter,例如:

authorize {
    ...
    sql
    # check monthly usage limit
    monthlytrafficcounter
    ...
}

注意:monthlytrafficcounter 一定要放在sql的下方,否则不生效,在很多教程中没有说明这一点

4、重启radiusd

1)重启服务(或者先用radiusd -X模式进行调试)

systemctl restart radiusd

2)故障排除,某些时候radiusd重启后,会出现以下错误

/etc/freeradius/mods-enabled/sqlcounter[43]: Reference 
"${modules.sql.dialect}" not found

错误分析:这个错误的原因是在sqlcounter里面调用了sql模块里面的dialect变量。如果模块的启动顺序出现了启动sqlcounter时,sql还没有被加载的情况,就会导致这个变量获取不到。
解决思路一:是在/etc/raddb/radiusd.conf中的instantiate部分指定模块的启动顺序;

解决思路二:简单粗暴的方式,直接在sqlcounter中将所有的dialect都指定为’mysql’。例如:

sqlcounter dailycounter {
    sql_module_instance = sql
    #dialect = ${modules.sql.dialect}
    dialect = "mysql"
    counter_name = Daily-Session-Time
    check_name = Max-Daily-Session
    reply_name = Session-Timeout
    
    key = User-Name
    reset = daily
    $INCLUDE ${modconfdir}/sql/counter/${dialect}/${.:instance}.conf
}

5、对目标用户或者组设置限量属性

例如:增加mygroup组,对这个组限制每个月最大流量为1GB(1024MB)此处的单位已经转换为MB了。如果用户已经超过这个使用量,认证将失败。

在radius数据库的check表以及reply表中,分别添加以下两条记录(也可以使用第三方的radius操作界面进行操作,例如daloradius系统)

# 在数据库中限制用户组的最大流量为1GB(本例中的用户组名为mygroup)
mysql> INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('mygroup','Max-Monthly-Traffic',':=','1024');
    
# 流量统计时间的间隔(60秒)
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('mygroup','Acct-Interim-Interval',':=','60');

如果用户使用量已经超过限制,radius认证会失败。使用radtest调试,可以看到返回的信息

返回的错误信息样例:

Sending Access-Request Id 219 from 0.0.0.0:40100 to 127.0.0.1:1812
    User-Name = 'myusername'
    User-Password = 'mypassword'
    NAS-IP-Address = 172.16.241.135
    NAS-Port = 0
    Message-Authenticator = 0x00
Received Access-Reject Id 219 from 127.0.0.1:1812 to 127.0.0.1:40100 length 70
    Reply-Message = 'Your maximum monthly usage time has been reached'
(0) -: Expected Access-Accept got Access-Reject

6、【可选】为daloRadius系统添加dictionary辅助定义

使用daloRadius管理界面管理为用户或组添加属性时,选择Vendor的下拉框可以很方便的选择属性。对于自定义的属性,也可以使用SQL语句添加到dictionary表里使其出现在下拉列表里

INSERT INTO dictionary (Type, Attribute,Vendor, RecommendedOP,RecommendedTable,RecommendedHelper,RecommendedTooltip) VALUES ('integer','Max-Monthly-Traffic','dictionary.freeradius.vpntraffic', ':=', 'check', 'The traffic of user per month', '1024=1G');

INSERT INTO dictionary (Type, Attribute,Vendor, RecommendedOP,RecommendedTable,RecommendedHelper,RecommendedTooltip) VALUES ('integer','Monthly-Traffic-Limit','dictionary.freeradius.vpntraffic', ':=', 'reply', 'The traffic of user per month', '1024=1G');