侧边栏壁纸
博主头像
★街角晚灯★博主等级

博观而约取 厚积而薄发

  • 累计撰写 438 篇文章
  • 累计创建 181 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

基于用户名/密码认证和流量控制的OpenVPN系统配置--转

WinJay
2016-08-26 / 0 评论 / 0 点赞 / 129 阅读 / 10553 字 / 正在检测是否收录...
温馨提示:
文章发布较早,内容可能过时,阅读注意甄别。。。。

title: 基于用户名/密码认证和流量控制的OpenVPN系统配置 date: '2016-08-26 13:03:28+08:00'

一、OpenVPN的基本安装与配置

以Debian 5.0系统为例。主要包括OpenVPN服务器程序的安装和证书的生成。

1、下载安装OpenVPN

apt-get install openvpn
2、生成证书

复制生成证书的脚本:

cp -R /usr/share/doc/openvpn/examples/easy-rsa/ /etc/openvpn/
修改证书的变量:

cd /etc/openvpn/easy-rsa/2.0/
nano vars
编辑该文件,将最后几行的变量改成自己的,例如

export KEY_COUNTRY=”CN”
export KEY_PROVINCE=”BJ”
export KEY_CITY=”Beijing”
export KEY_ORG=”XX”
export KEY_EMAIL=”xxx@xxx.com”
保存退出后,运行脚本设置变量,并清理:

source ./vars
./clean-all
之后就可以生成公钥和私钥证书了,一路回车默认值或yes即可:

./build-ca
./build-key-server server
./build-key client1
./build-dh
实际上,对于用户名/密码认证机制来说,client1可以省略掉。

二、基于MySQL的用户名/密码认证实现

1、安装MySQL Server

apt-get install mysql-server
已安装的可以略过。

2、建立数据库

以管理员身份登录MySQL:

mysql -uroot -p
运行以下SQL命令:

— 创建数据库
CREATE DATABASE openvpn;

— 切换数据库
USE openvpn;

— 创建用户,用户名openvpn,密码openvpn(可自行设定)
GRANT ALL ON openvpn.* TO ‘openvpn’@’localhost’ IDENTIFIED BY ‘openvpn’;

— 创建用户数据表
CREATE TABLE IF NOT EXISTS user (
username char(32) COLLATE utf8_unicode_ci NOT NULL,
password char(128) COLLATE utf8_unicode_ci DEFAULT NULL,
active int(10) NOT NULL DEFAULT ‘1’,
creation timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
name varchar(32) COLLATE utf8_unicode_ci NOT NULL,
email char(128) COLLATE utf8_unicode_ci DEFAULT NULL,
note text COLLATE utf8_unicode_ci,
quota\_cycle int(10) NOT NULL DEFAULT ’30’,
quota\_bytes bigint(20) NOT NULL DEFAULT ‘10737418240’,
enabled int(10) NOT NULL DEFAULT ‘1’,
PRIMARY KEY (username),
KEY idx\_active (active),
KEY idx\_enabled (enabled)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

— 创建日志数据表
CREATE TABLE IF NOT EXISTS log (
username varchar(32) COLLATE utf8_unicode_ci NOT NULL,
start\_time timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
end\_time timestamp NOT NULL DEFAULT ‘0000-00-00 00:00:00’,
trusted\_ip varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
trusted\_port int(10) DEFAULT NULL,
protocol varchar(16) COLLATE utf8_unicode_ci DEFAULT NULL,
remote\_ip varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
remote\_netmask varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL,
bytes\_received bigint(20) DEFAULT ‘0’,
bytes\_sent bigint(20) DEFAULT ‘0’,
status int(10) NOT NULL DEFAULT ‘1’,
KEY idx\_username (username),
KEY idx\_start\_time (start\_time),
KEY idx\_end\_time (end\_time)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
3、安装pam_mysql模块

apt-get install libpam-mysql
4、配置OpenVPN的PAM

nano /etc/pam.d/openvpn
输入以下内容:

auth sufficient pam_mysql.so user=openvpn passwd=openvpn host=localhost db=openvpn table=user usercolumn=username passwdcolumn=password where=active=1 sqllog=0 crypt=1

account required pam_mysql.so user=openvpn passwd=openvpn host=localhost db=openvpn table=user usercolumn=username passwdcolumn=password where=active=1 sqllog=0 crypt=1
其中数据库、用户名、密码按照自己的实际情况设置。
crypt表示密码在数据库中加密存储的方式,含义如下:

0 (or “plain”):不加密,明文存储。不推荐使用。
1 (or “Y”):使用crypt(3)函数,相当于MySQL中的ENCRYPT()函数。
2 (or “mysql”):使用MySQL的PASSWORD()函数。PAM可能与MySQL的函数不同,不推荐使用。
3 (or “md5″):使用MD5。
4 (or “sha1″):使用SHA1。
MD5我试用过有些问题。最后我使用的是1。
之后重启saslauthd:

/etc/init.d/saslauthd restart
如果出现以下提示:

To enable saslauthd, edit /etc/default/saslauthd and set START=yes (warning).
说明saslauthd未配置成自动启动,则需修改/etc/default/saslauthd文件,将START=no改为START=yes,再重启服务即可。

5、测试saslauthd是否配置成功

登入MySQL数据库:

mysql -uopenvpn -p
执行以下命令:

USE openvpn;
INSERT INTO user(username, password) VALUES(‘test’, ENCRYPT(‘123456′));
退出后,运行以下命令:

testsaslauthd -u test -p 123456 -s openvpn
如果显示

0: OK “Success.”
则说明配置成功。否则,请根据/var/log/auth.log日志查找原因。

6、复制OpenVPN PAM认证模块

cp /usr/lib/openvpn/openvpn-auth-pam.so /etc/openvpn/
7、编写OpenVPN配置文件。

OpenVPN服务启动时,会扫描/etc/openvpn目录中的.conf文件,对于每个文件,启动一个daemon。本系统要实现UDP、TCP登录的同时支持,我的做法是写两份配置文件,即启动两个daemon,分别负责UDP和TCP协议。

nano /etc/openvpn/
输入以下内容

dev tun
proto udp
port 1194

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

keepalive 20 120
persist-key
persist-tun

# user/pass auth from mysql
plugin ./openvpn-auth-pam.so openvpn
client-cert-not-required
username-as-common-name

client-to-client

push “redirect-gateway def1”
push “dhcp-option DNS 8.8.8.8”
push “dhcp-option DNS 8.8.4.4”

comp-lzo

max-clients 15

status status/udp.log
log-append /var/log/openvpn/udp.log
verb 3
mute 5
其中,# user/pass auth from mysql下面的几行是该认证设置的关键所在。
同理,如果想支持TCP,建立一个openvpn-tcp.conf文件,内容跟上面相同,仅仅把

proto udp
server 10.8.0.0 255.255.255.0
status status/udp.log
log-append /var/log/openvpn/udp.log
改为

proto tcp
server 10.10.0.0 255.255.255.0
status status/tcp.log
log-append /var/log/openvpn/tcp.log
即可。
同时,为日志和状态文件建立目录:

mkdir /etc/openvpn/status
mkdir /var/log/openvpn
重启OpenVPN服务:

/etc/init.d/openvpn restart
8、设置iptables

nano /etc/rc.local
在exit 0之前添加以下几行:

# iptables for OpenVPN
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o venet0 -j SNAT –to xxx.xxx.xxx.xxx
iptables -t nat -A POSTROUTING -s 10.10.0.0/24 -o venet0 -j SNAT –to xxx.xxx.xxx.xxx
其中xxx.xxx.xxx.xxx是你的服务器的IP地址。
然后让其生效:

/etc/rc.local
至此,一个用户名/密码认证的OpenVPN系统就配置完成了。客户端下载使用/etc/openvpn/easy-rsa/2.0/keys/ca.crt作为证书文件,用用户名、密码认证,即可连接。一个典型的客户端配置文件如下:

client
dev tun
proto udp
remote xxx.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
auth-user-pass
comp-lzo
verb 3
其中xxx.com替换为服务器的域名或IP地址。
用刚才建立的test/123456用户连接一下试试吧!

9、“PAM unable to dlopen(/lib/security/pam_mysql.so): /lib/security/pam_mysql.so: undefined symbol: pam_get_item”错误的解决办法

我在Debian 5中,遇到了如上的错误(/var/log/auth.log),导致OpenVPN提示认证失败。解决方法如下:

echo “/lib/libpam.so.0” >> /etc/ld.so.preload
/etc/init.d/saslauthd restart
/etc/init.d/openvpn restart
三、流量控制的实现

总体思路:利用OpenVPN程序在连接、断开时的脚本钩子,将用户的使用信息记录到数据库。根据数据库中的日志,判断用户是否超过流量配额,如果超过,则将用户锁定。

1、连接、断开时的脚本

建立文件/etc/openvpn/connect.sh,内容如下:

#!/bin/bash

DB=’openvpn’
DBADMIN=’openvpn’
DBPASSWD=’openvpn’

mysql -u$DBADMIN -p$DBPASSWD -e “INSERT INTO log(username,start_time,trusted_ip,trusted_port,protocol,remote_ip,remote_netmask,status) VALUES(‘$common_name’,now(),’$trusted_ip’,$trusted_port,’$proto_1′,’$ifconfig_pool_remote_ip’,’$route_netmask_1′,1)” $DB
建立文件/etc/openvpn/disconnect.sh,内容如下:

#!/bin/bash

DB=’openvpn’
DBADMIN=’openvpn’
DBPASSWD=’openvpn’

mysql -u$DBADMIN -p$DBPASSWD -e “UPDATE log SET end_time=now(),bytes_received=$bytes_received,bytes_sent=$bytes_sent,status=0 WHERE trusted_ip=’$trusted_ip’ AND trusted_port=$trusted_port AND remote_ip=’$ifconfig_pool_remote_ip’ AND username=’$common_name’ AND status=1” $DB

mysql -u$DBADMIN -p$DBPASSWD -e “UPDATE user SET active=0 WHERE user.username IN (SELECT username FROM (SELECT log.username AS username, quota_bytes FROM user, log WHERE log.username=’$common_name’ AND log.username=user.username AND log.status=0 AND TO_DAYS(NOW())-TO_DAYS(start_time)< =quota_cycle GROUP BY log.username HAVING SUM(bytes_received)+SUM(bytes_sent)>=quota_bytes) AS u);” $DB
将文件改为可执行属性:

chmod +x /etc/openvpn/connect.sh
chmod +x /etc/openvpn/disconnect.sh
修改OpenVPN配置文件openvpn-udp.conf、openvpn-tcp.conf,添加以下几行:

# record in database
script-security 2
client-connect ./connect.sh
client-disconnect ./disconnect.sh
其主要作用是:在用户连接时,在数据库log表中新建一条记录,记录用户的IP地址、端口号、连接时间等信息。在用户断开连接时,更新刚才添加的记录,记下用户的断开连接时间、发送数据量、接收数据量等。然后,对用户的流量进行判断,若超过配额,则将用户锁定(active=0)。
user表中的quota_cycle是用户的流量计算周期,quota_bytes是用户每个周期内最多允许的流量。
connect.sh和disconnect.sh脚本文件中调用了OpenVPN的环境变量。OpenVPN在执行脚本时,自动各种设置了环境变量,供脚本使用。具体的环境变量可以查看这里。

2、使用cron每天对用户进行检查

以上操作在用户超过流量时自动将用户锁定。每天还应该执行一次检查,把已经恢复流量的用户解锁。可以通过cron实现此功能。
建立文件/etc/cron.daily/openvpn,内容如下:

#!/bin/bash

DB=’openvpn’
DBADMIN=’openvpn’
DBPASSWD=’openvpn’

mysql -u$DBADMIN -p$DBPASSWD -e “UPDATE user SET active=1” $DB

mysql -u$DBADMIN -p$DBPASSWD -e “UPDATE user SET active=0 WHERE user.username IN (SELECT username FROM (SELECT log.username AS username, quota_bytes FROM user, log WHERE log.username=user.username AND log.status=0 AND TO_DAYS(NOW())-TO_DAYS(start_time)< =quota_cycle GROUP BY log.username HAVING SUM(bytes_received)+SUM(bytes_sent)>=quota_bytes) AS u);” $DB

mysql -u$DBADMIN -p$DBPASSWD -e “UPDATE user SET active=0 WHERE enabled=0″ $DB
其思路是:先默认将所有用户解锁,然后将超过流量的用户锁定。同时,管理员可以通过user表中的enabled字段手工禁用用户。
然后给文件可执行权限:

chmod +x /etc/cron.daily/openvpn
3、修改saslauthd的缓存时间

saslauthd默认有一段较长的缓存时间,在用户通过认证后的一段时间里,可以再次通过认证而不需要重新查询数据库。这样不利于实现对超流量用户的立即锁定。
saslauthd启动时有一个-t参数,可以设置其超时时间。修改/etc/default/saslauthd文件,将

OPTIONS=”…”
一行,引号最后添上-t 60,可将缓存时间设置为60秒。当然,也可直接将其设置为0,即不缓存。
重启saslauthd服务和OpenVPN,使设置生效:

/etc/init.d/saslauthd restart
/etc/init.d/openvpn restart

版权属于: 伪技术の宅
原文地址: http://blog.liujason.com/1698.html
转载时必须以链接形式注明原始出处及本声明。

0

评论区