mariadb+freeradius踢用户下线及非正常掉线用户清理【更新】

    整套Radius环境基于mariadb+freeradius+daloradius,daloradius本身有踢用户下线功能,但是只能逐个用户踢下线。本文结合网上其他网友的方法,提供一段可执行的python代码,用以定时批量将已停断的用户主动踢下线。
    程序的原理是查找所有当前在线的但是却被daloradius放入daloRADIUS-Disabled-Users用户组(daloradius是用这种方法禁用、停断用户的)的用户以及在线信息(用户的Acct-Session-Id等信息),用这些信息向Bras/NAS发送DM信息,完成将用户踢下线的功能。这里有个前提是需要说明,因为我们这套系统要和其他系统对接,通过其他系统完成用户业务的开通和停断,其他系统停断用户只是将用户放入daloRADIUS-Disabled-Users用户组,没有给我们提供诸如用户有效时间等其他的信息,我们只能依靠用户是不是在daloRADIUS-Disabled-Users用户组来判断用户是否已经被停断业务。
    服务器上要安装python3以及python的mariadb、pyrad包,并且由于使用了mariadb包,需要连接数据库,还要确保部署此程序的linux服务器已经安装了mariadb或者MariaDB Connector/C 3.1.5以上版本,低于此版本安装mariadb包会报错。
    不会安装MariaDB Connector/C的朋友可以参考以下shell命令:

mkdir -p /tmp/mdbccbin
cd /tmp/mdbccbin

curl -O https://downloads.mariadb.com/Connectors/c/connector-c-3.1.10/mariadb-connector-c-3.1.10-ubuntu-bionic-amd64.tar.gz

echo "1b5b513f44967efadf5eae5e34952cd61f94655575d45b5a9182ea1b91d1d1fa  mariadb-connector-c-3.1.10-ubuntu-bionic-amd64.tar.gz" | sha256sum -c

# get root
sudo su

tar xvf mariadb-connector-c-3.1.10-ubuntu-bionic-amd64.tar.gz --directory /usr --strip-components 1

echo "/usr/lib/mariadb/" > /etc/ld.so.conf.d/mariadb.conf
ldconfig

# back to regular user
exit

python3 -m pip install --user mariadb

    对安全性要求高的朋友可以在数据库中创建一个view,然后只允许一个权限较低的用户访问此view。

CREATE OR REPLACE VIEW view_kick_user
AS
SELECT radacct.Username, 
radacct.FramedIPAddress,
radacct.NASIPAddress, 
radacct.AcctSessionId, 
nas.secret, 
nas.shortname 
FROM radacct 
LEFT JOIN nas ON (nas.nasname = radacct.NASIPAddress) 
LEFT JOIN radusergroup ON (radacct.Username = radusergroup.username) 
WHERE (radacct.AcctStopTime IS NULL OR radacct.AcctStopTime = '0000-00-00 00:00:00') 
AND (radacct.Username LIKE '%') 
AND (radusergroup.groupname = 'daloRADIUS-Disabled-Users') 
ORDER BY radacctid asc;

    对安全性要求不高的朋友可以将后面python程序内的select查询语句改成下面的语句:

SELECT radacct.Username, 
radacct.FramedIPAddress,
radacct.NASIPAddress, 
radacct.AcctSessionId, 
nas.secret, 
nas.shortname 
FROM radacct 
LEFT JOIN nas ON (nas.nasname = radacct.NASIPAddress) 
LEFT JOIN radusergroup ON (radacct.Username = radusergroup.username) 
WHERE (radacct.AcctStopTime IS NULL OR radacct.AcctStopTime = '0000-00-00 00:00:00') 
AND (radacct.Username LIKE '%') 
AND (radusergroup.groupname = 'daloRADIUS-Disabled-Users') 
ORDER BY radacctid asc 

代码如下:

#!/usr/bin/python
from __future__ import print_function
from pyrad.client import Client
from pyrad import dictionary
from pyrad import packet
import mariadb
import datetime
import sys

logfile = open("freeradius_kick_user.log", "a")
try:
    conn = mariadb.connect(
    user='数据库用户名',
    password='数据库密码',
    host='数据库服务器地址',
    port=3306,
    database='数据库名'
    )
except mariadb.Error as e:
    print(f"Error connecting to MariaDB Platform: {e}")
    sys.exit(1)

cur = conn.cursor()
cur.execute("SELECT Username,FramedIPAddress,NASIPAddress,AcctSessionId,secret,shortname FROM view_kick_user;")#这里是查询View的语句,可以改成上面直接查询表的语句。
for item in cur:
    ATTRIBUTES = {
        "Acct-Session-Id": item[3],
        "User-Name": item[0],
        "Framed-IP-Address": item[1]
    }
    logfile.write(str(datetime.datetime.now())+" "+str(item)+"!\n")
    print("Program is running......:")
    # create coa client
    client = Client(server=item[2], secret=item[4].encode(), dict=dictionary.Dictionary("dictionary"))
    # set coa timeout
    client.timeout = 5
    # create coa request packet
    attributes = {k.replace("-", "_"): ATTRIBUTES[k] for k in ATTRIBUTES}
    # create disconnect request
    request = client.CreateCoAPacket(code=packet.DisconnectRequest, **attributes)
    # send request
    result = client.SendPacket(request)
    if result.code==packet.DisconnectACK:
        resultstr = " Disconnect ACK "
    elif result.code==packet.DisconnectNAK:
        resultstr = " Disconnect NAK "
    else:
        resultstr = " Unknow "
    logfile.write(str(datetime.datetime.now())+" "+str(result)+"\n")
    logfile.write(str(datetime.datetime.now())+resultstr+" Code:"+str(result.code)+"!\n")
logfile.write(str(datetime.datetime.now())+" end of result\n")
conn.close()
logfile.close()

    此程序因为pyrad的原因,只能在linux环境下运行,windows下运行会出现AttributeError: module ‘select’ has no attribute 'poll’的错误提示。程序里涉及的字典档可以到github上pyrad项目的示例文件夹中下载,并与本程序放在同一级目录中。
    本程序执行后,在程序同级目录下会生成一个freeradius_kick_user.log日志文件用以查看执行结果及排错。
linux下定时执行程序的方法请大家自行百度吧。

    关于非正常掉线用户的数据清理问题,可以用以下语句查找这种用户:
    【2020年12月1日更正】:需要将在线时间再减去acctsessiontime,再与1800秒比较,1800秒可以根据需要设置,记录用户会话时间间隔由用户或者用户组的Acct-Interim-Interval属性决定,默认可能是300秒,我自己设置为600秒,这样的话1800秒意味着NAS半个小时3次没有上报记账信息即为非正常离线。

select radacctid,acctstarttime, acctstoptime, username from radacct where acctstoptime is null and timestampdiff(second, acctstarttime, current_timestamp)-acctsessiontime>1800

    将用户为空的下线时间修改为当前时间的语句如下:

update radacct set acctstoptime = current_timestamp where acctstoptime is null and timestampdiff(second, acctstarttime, current_timestamp)-acctsessiontime>1800

    另外,cron里每半个小时执行一次脚本的设置如下:

*/30 * * * * python3 clear_abnormal_user.py >> /tmp/freeradius_clear_abnormal_user.log 2>&1

    而不是:

30 * * * * python3 clear_abnormal_user.py >> /tmp/freeradius_clear_abnormal_user.log 2>&1

    上面的语句意思是每个小时每逢半点执行一次,比如:6点半、7点半、8点半,以此类推。
参考文章:
1.PostgreSQL下的FreeRadius 清除非正常掉线用户
2.Error pip install mariadb on ubuntu server

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值