PPTP+FreeRADIUS+MySQL搭建VPN认证和流量控制
最近帮论坛上朋友建了个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.254');
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
ATTRIBUTE User-Group 3004 string
初步测试:
/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 {
User-Group:= "%{sql:SELECT groupname FROM radusergroup WHERE username='%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}' ORDER BY priority}"
}
if ('%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) FROM radacct WHERE username='%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}' 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='%{User-Group}' 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