使用pyrad解决pptp错误(挂死)账号退出有关问题(笔记)

使用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

 

写道
yum install gcc gcc-c++ autoconf automake
 
写道
wget http://www.python.org/ftp/python/2.6.6/Python-2.6.6.tgz
tar zxvf Python-2.6.6.tgz
cd Python-2.6.6
./configure --prefix=/usr/local/python-2.6
make && make install
 
写道
ln -sf /usr/local/python2.6/bin/python2.6 /usr/bin/python

 python -V查看版本是否为2.6.6

 

装完python后可能会导致yum不能使用,修改一下yum文件即可

写道
vim /usr/bin/yum

将第一行的!#/usr/bin/python
改成 !#/usr/bin/python2.4

 这样就可以了

 

2、下载pyrad

 

写道
wget http://pypi.python.org/packages/source/p/pyrad/pyrad-2.0.tar.gz#md5=e95f2cef1a191c1c891779dff8fb0255

 解压后,里面有个README文件,里面有使用python脚本向radius发送认证的使用方法,以及安装方法

 

安装方法是

写道
python setup.py install

 这时候大部分会报错

写道
ImportError: No module named setuptools

 解决方法如下

写道
wget http://pypi.python.org/packages/source/s/setuptools/setuptools-0.6c8.tar.gz#md5=0e9bbe1466f3ee29588cc09d3211a010
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 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")

调用Client方法,定义radius server的ip是192.168.1.1,验证的secret key是TestKey,调用的属性文件是当前目录下的dictionary文件,需要处理的异常账号的用户名是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)

 这里是用到radius的计费属性了,计费状态是停止计费“stop”

从计费开始到计费结束发送了多少数据,接收了多少数据"Acct-Input-Octets""Acct-Output-Octets",3G上网卡里面买流量应该是这么算的,这里是随机给一个

从计费开始到计费结束连接了多长时间"Acct-Session-Time",3G上网卡包时间应该是这么算的,这里是随机给一个

结束计费的原因"Acct-Terminate-Cause",这里是随机给一个

 

先安装一遍

写道
python setup.py install
 

 

需要注意的是,radius默认的计费的端口是1813,但是有些地方用到的是1646,所以需要更改一下pyrad-2.0/build/lib/pyrad/client.py,将这一行改一下

写道
def __init__(self, server, authport=1645, acctport=1646,

 改成你需要的端口就可以,更改完成后,务必需要重新安装一下,执行

写道
python setup.py install

 就可以了,要不然更改不会生效

 

然后回到example目录,修改dictionary文件,把文件一开始的include全部注释掉

写道
#$INCLUDE dictionary.compat # compability issues
#$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发送计费结束请求了,执行

写道
python acct.py

 即可,如果你抓包的话,可以看到如下数据

写道
16:08:04.674935 IP 192.168.2.2.60993 > 192.168.1.1.sa-msg-port: RADIUS, Accounting Request (4), id: 0xc1 length: 57
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终端执行:

写道
python acct.py vpn

 其中vpn是需要注销的用户名

 

解决方法:

写道
req=srv.CreateAcctPacket(User_Name="vpn")

把这行改成

req=srv.CreateAcctPacket(User_Name=sys.argv[1])

 注意sys.argv[0]永远都表示是你执行的文件名,所以你需要的参数是1