PPTP+FreeRADIUS+MySQL搭建VPN认证和流量控制

Tuesday, April 12th, 2011 @ 4:07 pm

最近帮论坛上朋友建了个OpenVPN+PPTP的VPN服务器,记下来过程以备不时之需。

系统环境是CentOS 5.6 xen,所有过程中软件均从源码编译。

需要软件:

PopTop: http://poptop.sourceforge.net/

PPPd: http://ppp.samba.org/

FreeRADIUS: http://freeradius.org/

RADIUSClient: http://wiki.freeradius.org/Radiusclient

MySQL: http://www.mysql.com/

同时为了方便管理数据库,最好再装个php,使用phpmyadmin来管理。

编译过程很简单,pptpd、pppd和freeradius都是

./configure && make && make install

就可以了。

完成之后freeradius的启动脚本在redhat/里面,pptpd需要自己写一个,很简单:

#!/bin/sh
#
# Startup script for pptpd
#
# chkconfig: 345 40 70
# description: PPTP server
# processname: pptpd
# config: /etc/pptpd.conf

# Source function library.
. /etc/rc.d/init.d/functions
# See how we were called.
case "$1" in
start)
echo -n "Starting pptpd: "
if [ -f /var/lock/subsys/pptpd ] ; then
echo
exit 1
fi

/usr/local/sbin/pptpd -d
echo
touch /var/lock/subsys/pptpd
;;

stop)
echo -n "Shutting down pptpd: "
killproc pptpd
echo
rm -f /var/lock/subsys/pptpd
;;

status)
status pptpd
;;

restart)
$0 stop
$0 start
;;
*)

echo "Usage: $0 {start|stop|restart|status}"
exit 1
esac

exit 0

--------------------------------------------------------------------------------

然后修改一些FreeRADIUS的配置文件,位于/usr/local/etc/raddb/

sites-enabled/default

在所有的unix和files前面加上注释,并去掉所有sql前面的注释。

radiusd.conf

去掉include sql.conf前面的注释。

clients.conf
这个文件控制连接的客户端的地址以及secret code。
secret要记下来,测试和写配置文件的时候要用。默认是testing123

sql.conf
这个文件控制连接到sql的参数。
改成实际数据库的用户名和密码。

sql/mysql/dialup.conf
取消

sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}"

前面的注释,把下一行注释掉。
同时如果需要打开simultanoues-use(控制同时在线用户数)的话需要把simul_query_check取消注释。

--------------------------------------------------------------------------------

然后建立基本数据库:

/usr/local/mysql/bin/mysql -uroot -p
create database radius;
grant all privileges on radius.* to radius@localhost identified by "radiuspassword";
flush privileges;
exit;
/usr/local/mysql/bin/mysql -uradius -p radius < /usr/local/etc/raddb/sql/mysql/schema.sql

建立表格:

INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Auth-Type',':=','Local');
INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Service-Type',':=','Framed-User');
INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Address',':=','255.255.255.255');
INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Netmask',':=','255.255.255.0');
INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Acct-Interim-Interval',':=','600');
INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Max-Monthly-Traffic',':=','5368709120');
INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('user','Simultaneous-Use',':=','1');

以上前四行不用改动,acct-interim-interval是计算流量的间隔(600秒),意味着每隔10分钟记录当前流量。倒数第二行是每月最大流量,这里是5G(单位是字节)。最后一行是允许同时连接数目。

--------------------------------------------------------------------------------

输入测试用户信息:

INSERT INTO radcheck (username,attribute,op,VALUE) VALUES ('test','Cleartext-Password',':=','test');
INSERT INTO radusergroup (username,groupname) VALUES ('test','user');

用户名与密码必须以明文/NTLM Crypt形式保存,因为MS-CHAPv2不支持MD5保存的密码。

--------------------------------------------------------------------------------

由于上步中有非内置的attribute Max-Monthly-Traffic,所以需要在/usr/local/etc/raddb/dictionary里面定义:

ATTRIBUTE Max-Monthly-Traffic 3003 integer

--------------------------------------------------------------------------------

初步测试:

/etc/init.d/freeradius stop
radiusd -X &
radtest test test localhost 1649 testing123

如果结果中有Access-Accept就代表成功了,否则退回去检查设置。

测试成功的话添加在认证时检测流量的语句,打开/usr/local/etc/raddb/sites-enabled/default,找到authorize一节插入:

update request {
Group-Name := "%{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority}"
}
if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") {
reject
}

--------------------------------------------------------------------------------

设置radiusclient:

打开/usr/local/etc/radiusclient/radiusclient.conf,修改

authserver localhost:1812

acctserver localhost:1813

修改server:

最后加上localhost secret(就是FreeRadius的client.conf里面定义的secret)

修改dictionary:

最后加上

INCLUDE /usr/local/etc/radiusclient/dictionary.merit
INCLUDE /usr/local/etc/radiusclient/dictionary.microsoft

如果没有dicitionary.microsoft的话看这里:http://wiki.freeradius.org/PopTop

--------------------------------------------------------------------------------

一切正常后设置pptp:

把源码包里面的options.pptpd和pptpd.conf拷到/etc/

修改options.pptpd:

取消ms-dns前面的注释,后面的ip改为8.8.8.8

加入一行noaccomp,以提供对iOS 4.3+的支持(否则连上就断)。

最后加上插件:

plugin /usr/local/lib/pppd/2.4.5/radius.so
plugin /usr/local/lib/pppd/2.4.5/radattr.so
radius-config-file /usr/local/etc/radiusclient/radiusclient.conf

修改pptpd.conf:

ppp路径改为/usr/local/sbin/pppd

option路径为/etc/options.pptpd

注释掉logwtmp避免619错误

最后的localip根据需要设置

示例:localip 192.168.100.1

remoteip 192.168.100.100-150

重 要的一点:一定要注释掉delegate,之前没有注释结果连接的时候log显示LCP terminated by peer跟着一堆乱码直接掉线,客户端则显示720,注释掉就好了。(虽然个人认为不应该注释,因为delegate的作用是让radius来处理ip分 配)

启动服务测试下是否能连接,多用radiusd -X看输出信息。

--------------------------------------------------------------------------------

最后是相应的iptables设置:/etc/sysconfig/iptables

nat里面加入:

-A POSTROUTING -s 192.168.100.0/255.255.255.0 -o eth0 -j MASQUERADE

filter里面加入:

-A INPUT -i lo -j ACCEPT
-A INPUT -i ! lo -d 127.0.0.0/8 -j REJECT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -j ACCEPT
-A INPUT -p gre -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 1723 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A INPUT -j REJECT
-A FORWARD -i ppp+ -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j TCPMSS --set-mss 1356

设置mss以防止过大的包被丢弃,从而造成无法载入。

大功告成!

本文参考:

http://wiki.freeradius.org/PopTop

http://freeradius.1045715.n5.nabble.com/group-variable-td2776238.html

http://hi.baidu.com/ox188/blog/item/4ae1373f33d90fe455e723a4.html

http://www.accountingenhancements.com/filetree/pptp-HOWTO-linux-2.6.9.txt

http://discussions.apple.com/thread.jspa?threadID=2778039&start=60&tstart=0

Tags: , , ,
Posted in VPN, 折腾 | 22 Comments »

22 Responses to “PPTP+FreeRADIUS+MySQL搭建VPN认证和流量控制”

  1. SivaCoHan says:

    看了此文,收益匪浅!今天又看了半天的文档。
    就为了解决用户不正常掉线,会在radacct留下一个acc*stop的字段为NULL的情况。而freeradius判读是否多用户在线,就是查询一个用户名在这个表中有几个NULL。在这种情况下,如果设置只允许单用户登录,那么这个帐号将无法登录,不知道,这个问题应该怎么解决,求教。

    • tony says:

      不正常掉线数据库里面会有Lost-Carrier,应该不会影响记录的,除非你的Freeradius/Mysql/Radiusplugin没有正常运行。

      • SivaCoHan says:

        plugin /usr/local/lib/pppd/2.4.5/radattr.so
        radius-config-file /usr/local/etc/radiusclient/radiusclient.conf
        我配置的时候一直没加这两个,可以正常运行。而且,在看到您这篇博文之前,一直没有人提到这两个文件。我觉得,最后一个radius的配置文件其实不加也行,因为radius主要实现的是认证,ppp就提供一个链接。ppp不需要知道radius都干了什么。

  2. SivaCoHan says:

    plugin /usr/local/lib/pppd/2.4.5/radattr.so
    radius-config-file /usr/local/etc/radiusclient/radiusclient.conf
    这两个插件是干什么的阿?我是通过yum安装的freeradius2。在这个插件里,我只添加了radius.so。

  3. SivaCoHan says:

    大哥,我已经给你加友情链接了……虽然我的pr值只有2……还希望你别嫌弃给我也加个友链吧

  4. SivaCoHan says:

    update request {
    Group-Name := "%{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority}"
    }

    if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') = "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") {
    reject
    }
    这个query我尝试了……不知道为什么确不能对流量已经超限的用户reject。接着研究吧……

  5. SivaCoHan says:

    奇怪,为什么我看不到回复呢?

  6. snow says:

    流量检测的语句有问题,多了一个空格 < = last_day(now());}" ,应该是<= last_day(now());}"

  7. 老谢 says:

    请教一下,为什么我编译完,在/usr/local/etc/raddb/里面没有任何文件呢?

  8. [...] 在PPTP VPN服务器上配置FreeRADIUS+DaloRADIUS实现用户跟踪管理 PPTP+FreeRADIUS+MySQL搭建VPN认证和流量控制 ARA (ASN RADIUS admin) – FreeRADIUS [...]

Leave a Reply