一、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
转载时必须以链接形式注明原始出处及本声明。
评论区