Freeradius3 限制每个月最大流量

Freeradius没有内置限制用户每个月最大流量的功能,只能自己定制。网上有很多类似的文章,但是都是针对freeradius版本2的文档。由于版本3在很多地方与2有细微差别,直接用版本2的设置方法是行不通的。

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

一、增加radius自定义属性

编辑字典文件:

vi /etc/raddb/dictionary

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

#ATTRIBUTE	My-Local-String		3000	string
#ATTRIBUTE	My-Local-IPAddr		3001	ipaddr
#ATTRIBUTE	My-Local-Integer	    3002	integer
ATTRIBUTE	Max-Monthly-Traffic  3003	integer
ATTRIBUTE	Monthly-Traffic-Limit    3004    integer

二、配置计数器SQL

  1. 新建月流量的计数器sql语句

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

    内容如下:

    query = "SELECT SUM(acctinputoctets + acctoutputoctets) FROM radacct WHERE UserName='%{%k}' AND UNIX_TIMESTAMP(AcctStartTime) > '%b'"
    
  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
    }
    
  3. 启用sqlcounter模块

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

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

  1. 编辑以下文件

    vi /etc/raddb/sites-enabled/default
    
  2. authorize部分中,将添加monthlytrafficcounter,例如:

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

四、重启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
    }
    

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

例如对mygroup这个组限制每个月最大流量为1M(1048576字节)。如果用户已经超过这个使用量,认证将失败。

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

    # 在数据库中限制用户组的最大流量为1M(本例中的用户组名为mygroup)
    mysql> INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('mygroup','Max-Monthly-Traffic',':=','1048576');
    
    # 流量统计时间的间隔(60秒)
    mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('mygroup','Acct-Interim-Interval',':=','60');
    
    
  2. 如果用户使用量已经超过限制,radius认证会失败。使用radtest调试,可以看到返回的信息。

    radtest myusername mypassword localhost 0 testing123
    

    返回的错误信息样例:

    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
    

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

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


INSERT INTO `dictionary` (`Type`, `Attribute`, `Vendor`, `RecommendedOP`, `RecommendedTable`, `RecommendedHelper`, `RecommendedTooltip`) VALUES ('integer','Max-Monthly-Traffic','MySpec', ':=', 'check', 'volumebytes', 'max monthly traffic');

INSERT INTO `dictionary` (`Type`, `Attribute`, `Vendor`, `RecommendedOP`, `RecommendedTable`, `RecommendedHelper`, `RecommendedTooltip`) VALUES ('integer','Monthly-Traffic-Limit','MySpec', ':=', 'reply', 'volumebytes', 'monthly traffic limit');

Share Comments
comments powered by Disqus