使用pyrad解决pptp错误(挂死)账号退出有关问题(笔记)
个人笔记,水平较低,方法不是很深入,写这个之前,我看了两篇牛人翻译的关于radius的RFC文档,翻译的蛮好的,大家有兴趣可以看下,绝对能长知识
http://blog.csdn.net/twingao/article/details/927037
http://blog.csdn.net/twingao/article/details/1024207
问题环境为:用户个人PC(pptp client) --》 pptp server = radius client --》radius server
有时候由于用户的PC突然断电或者断网会引起VPN的异常断开,此时若keep alive机制不够完善的话,会导致VPN服务器不知道客户端已经异常,就算pptp自身的保活机制将连接断开,但pptp server作为radius client却不会向radius server发送计费结束请求,导致radius server那边某个异常账号一直保持在线状态,等用户再次登录时就会出现用户名密码错误的提示。
解决方法是使用pyrad中的一个python脚本向发送计费结束的请求
下列是环境部署步骤:
1、安装python2.6.6
tar zxvf Python-2.6.6.tgz
cd Python-2.6.6
./configure --prefix=/usr/local/python-2.6
make && make install
python -V查看版本是否为2.6.6
装完python后可能会导致yum不能使用,修改一下yum文件即可
将第一行的!#/usr/bin/python
改成 !#/usr/bin/python2.4
这样就可以了
2、下载pyrad
解压后,里面有个README文件,里面有使用python脚本向radius发送认证的使用方法,以及安装方法
安装方法是
这时候大部分会报错
解决方法如下
tar zxvf setuptools-0.6c8.tar.gz
cd setuptools-0.6c8
python setup.py build
python setup.py install
这样就可以解决了
然后再次执行python setup.py install就可以了
3、修改文件
其实pyrad应该是可以作为radius client使用的,支持的都是标准的radius协议,但是我没有配置过,所以不介绍具体的配置方法了,等以后有机会使用了再补上来吧
我用到的是pyrad2.0/example中的acct.py文件,这个文件经过修改后如下
import random, socket, sys import pyrad.packet from pyrad.client import Client from pyrad.dictionary import Dictionary def SendPacket(srv, req): try: srv.SendPacket(req) except pyrad.client.Timeout: print "RADIUS server does not reply" sys.exit(1) except socket.error, error: print "Network error: " + error[1] sys.exit(1) srv=Client(server="192.168.1.1", secret="TestKey", dict=Dictionary("dictionary")) req=srv.CreateAcctPacket(User_Name="vpn") print "Sending accounting stop packet" req["Acct-Status-Type"]="Stop" req["Acct-Input-Octets"] = random.randrange(2**10, 2**30) req["Acct-Output-Octets"] = random.randrange(2**10, 2**30) req["Acct-Session-Time"] = random.randrange(120, 3600) req["Acct-Terminate-Cause"] = random.choice(["User-Request", "Idle-Timeout"]) SendPacket(srv, req)
python目前我还不是很熟,但是简单介绍一下这个文件的各行代码
import pyrad.packet
from pyrad.client import Client
from pyrad.dictionary import Dictionary
这个是各种导入咯 - -、
try:
srv.SendPacket(req)
except pyrad.client.Timeout:
print "RADIUS server does not reply"
sys.exit(1)
except socket.error, error:
print "Network error: " + error[1]
sys.exit(1)
定义异常处理 - -、
secret="TestKey",
dict=Dictionary("dictionary"))
req=srv.CreateAcctPacket(User_Name="vpn")
调用Client方法,定义radius server的ip是192.168.1.1,验证的secret key是TestKey,调用的属性文件是当前目录下的dictionary文件,需要处理的异常账号的用户名是vpn
req["Acct-Status-Type"]="Stop"
req["Acct-Input-Octets"] = random.randrange(2**10, 2**30)
req["Acct-Output-Octets"] = random.randrange(2**10, 2**30)
req["Acct-Session-Time"] = random.randrange(120, 3600)
req["Acct-Terminate-Cause"] = random.choice(["User-Request", "Idle-Timeout"])
SendPacket(srv, req)
这里是用到radius的计费属性了,计费状态是停止计费“stop”
从计费开始到计费结束发送了多少数据,接收了多少数据"Acct-Input-Octets""Acct-Output-Octets",3G上网卡里面买流量应该是这么算的,这里是随机给一个
从计费开始到计费结束连接了多长时间"Acct-Session-Time",3G上网卡包时间应该是这么算的,这里是随机给一个
结束计费的原因"Acct-Terminate-Cause",这里是随机给一个
先安装一遍
需要注意的是,radius默认的计费的端口是1813,但是有些地方用到的是1646,所以需要更改一下pyrad-2.0/build/lib/pyrad/client.py,将这一行改一下
改成你需要的端口就可以,更改完成后,务必需要重新安装一下,执行
就可以了,要不然更改不会生效
然后回到example目录,修改dictionary文件,把文件一开始的include全部注释掉
#$INCLUDE dictionary.acc
#$INCLUDE dictionary.ascend
#$INCLUDE dictionary.bay
#$INCLUDE dictionary.cisco
#$INCLUDE dictionary.livingston
#$INCLUDE dictionary.microsoft
#$INCLUDE dictionary.quintum
#$INCLUDE dictionary.redback
#$INCLUDE dictionary.shasta
#$INCLUDE dictionary.shiva
#$INCLUDE dictionary.tunnel
#$INCLUDE dictionary.usr
#$INCLUDE dictionary.versanet
#$INCLUDE dictionary.erx
#$INCLUDE dictionary.freeradius
#$INCLUDE dictionary.alcatel
为什么要注视掉,因为这些文件都没有,不注视掉会报错,悲催啊
然后开始向radius server发送计费结束请求了,执行
即可,如果你抓包的话,可以看到如下数据
16:08:04.678476 IP 192.168.1.1.sa-msg-port > 192.168.2.2.60993: RADIUS, Accounting Response (5), id: 0xc1 length: 20
这说明已经成功了,然后使用异常的账号就可以正常登陆了
今天干的事情就这么多了,先记录一下,后期有的话就更新上去
2011-10-10更新
上面的代码中是通过修改User_Name来指定要注销的用户,若通过命令行参数输入用户名则更加的方便
比如在shell终端执行:
其中vpn是需要注销的用户名
解决方法:
把这行改成
req=srv.CreateAcctPacket(User_Name=sys.argv[1])
注意sys.argv[0]永远都表示是你执行的文件名,所以你需要的参数是1