最近从Ramhost上又订了一个Nano plan,用来搭建认证VPN的系统
环境:Ubuntu 9.10 x86, 128M RAM
Freeradius 2.1.0, RADIUS for OpenVPN 2.1beta9, OpenVPN 2.1, PostgreSQL 8.4.4
环境:Ubuntu 9.10 x86, 128M RAM
Freeradius 2.1.0, RADIUS for OpenVPN 2.1beta9, OpenVPN 2.1, PostgreSQL 8.4.4
OpenVPN是什么应该不用解释了。
FreeRADIUS是一个开源的RADIUS系统,目前是最为广泛使用的RADIUS,至于什么是RADIUS可以看这里:
FreeRADIUS是一个开源的RADIUS系统,目前是最为广泛使用的RADIUS,至于什么是RADIUS可以看这里:
1、安装组件
所需要的组件基本上都在Ubuntu的package source里面,用apt-get就可以装。
sudo apt-get install freeradius freeradius-postgresql postgresql openvpn build-essential libgcrypt11-dev
2、修改配置文件
Freeradius的配置文件位于/etc/freeradius
/etc/freeradius/clients.conf
这个文件控制连接的客户端的地址以及secret code。
地址不需要改变,因为我们是本地访问(openvpn到freeradius)。
secret要记下来,测试和写配置文件的时候要用。默认是testing123
/etc/freeradius/sql.conf
这个文件控制连接到sql的参数。
要改的地方:
database=”sql” 改成 database=”postgresql”
Connection info那里一般来说改密码就可以了。
/etc/freeradius/sql/postgresql/dialup.conf
取消sql_user_name = “%{%{Stripped-User-Name}:-%{%{User-Name}:-none}}”前面的注释,把下一行注释掉。
/etc/freeradius/sites-enabled/default
取消掉authorize、preacct和accounting段中sql前面的注释
注释掉所有的files和unix。
————————————————————-
Postgresql的配置文件做如下修改:
/etc/postgresql/8.4/main/postgresql.conf
找到listen_addresses,把引号里面的地址改成*
/etc/postgresql/8.4/main/pg_hba.conf
把local all all那里的ident改成md5
加入一行
host all all 0.0.0.0/0 md5
3、建立数据库
sudo -u postgres createuser radius --no-superuser --no-createdb --no-createrole -P
密码与sql.conf中connection info的密码一致。
sudo -u postgres createdb radius --owner=radius
然后
sudo cp /etc/freeradius/sql/postgresql/schema.sql ~/
psql -U radius radius < ~/schema.sql
然后连到sql上面,用psql或者pgadmin都可以。
psql里面输入如下命令:
insert into radgroupreply (groupname,attribute,op,value) values ('user','Auth-Type',':=','Local'); insert into radgroupreply (groupname,attribute,op,value) values ('user','Service-Type',':=','Dialout-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 radcheck (username,attribute,op,value) values ('test','Cleartext-Password',':=','test'); insert into radusergroup (username,groupname) values ('test','user');
最后\q退出。
4、初步测试
sudo /etc/init.d/freeradius stop sudo freeradius -X & radtest test test localhost 1649 testing123
如果出现类似如下信息:
Sending Access-Request of id 204 to 127.0.0.1 port 1812 User-Name = "test" User-Password = "test" NAS-IP-Address = 255.255.255.255 NAS-Port = 0 rad_recv: Access-Accept packet from host 127.0.0.1:1812, id=204, length=38 Service-Type = Framed-User Framed-IP-Address = 255.255.255.255 Framed-IP-Netmask = 255.255.255.0
即Access-Accept时,则说明freeradius和postgresql已经成功地连接起来了,否则要退回去检查配置。
5、配置OpenVPN
首先要把OpenVPN和Freeradius连接起来,这里是通过OpenVPN的插件Radiusplugin for OpenVPN。
wget http://www.nongnu.org/radiusplugin/radiusplugin_v2.1_beta9.tar.gz tar zxvf radiusplugin_v2.1_beta9.tar.gz cd radiusplugin/ make
应该会在当前目录下生成radiusplugin.so和radiusplugin.cnf,拷到/etc/openvpn。
修改/etc/openvpn/radiusplugin.cnf:
OpenVPNConfig=/etc/openvpn/openvpn.conf
sharedsecret= testing123
这里secret要与clients.conf中间的一致。
同时后面server段中的name要改成FreeRadius服务器的IP(本例中是本机localhost)
然后生成OpenVPN的key:
sudo su cp -R /usr/share/doc/openvpn/examples/easy-rsa /etc/openvpn cd /etc/openvpn/easy-rsa/2.0 . ./vars ./clean-all ./build-ca ./build-key-server server ./build-key client1 ./build-dh
然后把生成的ca.crt拖到客户端上,用winscp连到ssh就可以。
配置OpenVPN服务端:
sudo nano /etc/openvpn/openvpn.conf
dev tun proto tcp port xxxx ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt cert /etc/openvpn/easy-rsa/2.0/keys/server.crt key /etc/openvpn/easy-rsa/2.0/keys/server.key dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem user nobody group nogroup server 10.8.0.0 255.255.255.0 client-cert-not-required username-as-common-name plugin /etc/openvpn/radiusplugin.so /etc/openvpn/radiusplugin.cnf status /var/log/openvpn/status.log 1 log /var/log/openvpn/openvpn.log persist-key persist-tun push "redirect-gateway def1" push "dhcp-option DNS 8.8.8.8" push "dhcp-option DNS 208.67.222.222" auth RSA-SHA512 cipher AES-256-CBC comp-lzo
客户端:
client dev tun proto tcp remote your-server-address xxxx resolv-retry infinite nobind persist-key persist-tun script-security 2 auth RSA-SHA512 cipher AES-256-CBC ca ca.crt auth-user-pass verb 3 ns-cert-type server comp-lzo
再向/etc/rc.local中加入如下内容:
# add iptables rule for openvpn iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j SNAT --to-source your-server-ip-address # restart openvpn after 1 hour in case tun device got broken on reboot sleep 3600 /etc/init.d/openvpn stop sleep 10 /etc/init.d/openvpn start
加到exit 0前面。
重启等一个小时之后连接服务器应该会提示输入用户名密码,之后看到OpenVPN变绿就表示成功了。可以连到whatsmyip.org检查。
用户名密码可以通过pgadmin连到sql上面去修改,在radcheck里面。
本文参考了如下资料,在此表示感谢:
http://blog.chinaunix.net/u1/36506/showart_457803.html
https://forum.ramhost.us/bbs/viewtopic.php?id=4
http://wiki.freeradius.org/SQL_HOWTO
http://wiki.freeradius.org/Postgres_DDL_script
http://www.linuxsir.org/main/node/275
--------------------------------------------------------
FreeRADIUS+Postgresql+OpenVPN续:流量控制
实质上很简单,就是求和+if判断,枉自研究了半天的rlm_sql_counter
示例的是每月限制流量,针对用户组
1. 设定限制
radgroupreply组里面插入一行,命令如下:
insert into radgroupreply (groupname, attribute, op, value) values ('user','Max-Monthly-Traffic', ':=', '5368709120');
以上命令表示对用户组user限制流量为5G,单位是bytes
同时还要加入Acct-Interim-Interval,该参数是定义让OpenVPN plugin更新流量记录的间隔,必须是为300-3600秒之间的一个值
2. 判断命令
修改/etc/freeradius/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_trunc('day', acctstarttime) >= date_trunc ('month', current_date) AND date_trunc('day', acctstoptime) < = last_day(current_date);}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") { reject }
该行作用是用户连接时检查本月内上下行流量之和(1日-月末,acctinputoctet+acctoutputoctet),与限制相比较,如果相同或超过则拒绝认证。
中间使用了自定义函数last_day,所以需要在pgsql中定义。
3. 定义日期函数
CREATE OR REPLACE FUNCTION last_day(date) RETURNS date AS $$ SELECT (date_trunc('MONTH', $1) + INTERVAL '1 MONTH - 1 day')::date; $$ LANGUAGE 'sql' IMMUTABLE STRICT;
4. 定义Max-Monthly-Traffic
由于这不是Freeradius自带的属性,所以需要在dictionary中定义,否则freeradius不会去读这个属性
修改/etc/freeradius/dictionary
加入
Attribute Max-Monthly-Traffic 3003 integer
重启大功告成。试验的话把流量限制改成1,应该会被拒绝连接。
bug:如果用户一直不断开连接的话就无法拒绝认证了……FreeRADIUS不能踢人下线的。OpenVPN plugin的作者建议在openvpn.conf里加入reneg-sec xx让用户定时重新验证,同时在radiusplugin.cnf中使用useauthcontrolfile=true让用户在验证时不掉线。不过在实 验中useauthcontrolfile=true这条始终没成功过,不知道是什么原因.