安装OpenVPN
一下命令安装openvpn
sudo apt-get -y install openvpn libssl-dev openssl
安装完成后查看相应版本:
openvpn --version
查看版本的目的是后面下载相应的openvpn客户端文件的时候,最好下载相应的版本,否则可能会报错。
安装证书工具
sudo apt-get -y install easy-rsa
制作证书
sudo mkdir /etc/openvpn/easy-rsa/
#把/usr/share/easy-rsa/目录下的所有文件全部复制到/etc/openvpn/easy-rsa/下
sudo cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa/
sudo vi /etc/openvpn/easy-rsa/vars
# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="CN"
export KEY_PROVINCE="HB"
export KEY_CITY="wuhan"
export KEY_ORG="hansap"
export KEY_EMAIL="pengjunjie@hansap.com"
export KEY_OU="hansap"
# X509 Subject Field
export KEY_NAME="hansapextra"
实际上这里KEY_NAME是OpenVPN的名字,
然后使用source vars命令使其生效,如下:
source vars
#运行source vars的时候会有提示,需要使用clean all来清洗,执行clean-all命令会删除,当前目录下的keys文件夹。
./clean-all
制作CA证书
在easy-rsa目录下
./build-ca
输出的全部回车即可。这时在keys目录下面 /etc/openvpn/easy-rsa/keys/
可以查看到 ca.crt
和 ca.key
把该CA证书的ca.crt文件复制到openvpn的启动目录_etc_openvpn下,如下:
cp keys/ca.crt /etc/openvpn/
ll /etc/openvpn/
制作Server端证书
在easy-rsa目录下面执行
./build-key-server hansapextra
中间有个密码,可以保持为空
这个时候/etc/openvpn/easy-rsa/keys
会生成Server端证书 hansapextra.crt
,hansapextra.csr
,hansapextra.key
创建交换文件
在easy-rsa目录下执行
./build-dh
在目录/etc/openvpn/easy-rsa/keys
会生成 dh2048.pem
把vpnilanni.crt、vpnilanni.key、dh2048.pem复制到_etc_openvpn/目录下,如下:
cp keys/hansapextra.crt keys/hansapextra.key keys/dh2048.pem /etc/openvpn/
制作客户端证书
在目录easy-rsa下
./build-key extraclient
一直确认,后面输入密码可以为空
在目录/etc/openvpn/easy-rsa/keys
会生成extraclient.crt
,extraclient.csr
,extraclient.key
配置Server端
Server端的配置文件默认可以从openvpn的样例中拷贝
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
cd /etc/openvpn/
#拷贝过来后解压
gzip -d server.conf.gz
root@vpnserver:/etc/openvpn# grep -vE "^#|^;|^$" server.conf
port 1194
proto tcp
dev tun
ca ca.crt
cert hansapextra.crt
key hansapextra.key # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "route 192.168.11.0 255.255.255.0"
push "route 172.16.0.0 255.255.0.0"
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 3
做一点解释
- proto tcp 代表使用tcp的连接,tcp稳定一些。
- dev 使用tun模式。这样更使用与使用路由模式,而tap适合于使用将ip出去。
- server 10.8.0.0 255.255.255.0 这里可以随便配置一个子网,注意这里只能填写子网,这个子网是客户端分配的网段。
- push "route 192.168.11.0 255.255.255.0" 这里会推送两个路由,后面会讲这个路由怎么用
完成后可以启动
/etc/init.d/openvpn start
netstat -tunlp |grep 1194
#使用status也可以查看状态
/etc/init.d/openvpn start
配置Client 端
windows上配置
将client的ctr 和 key 文件,以及ca.crt文件拷贝到客户端,配置client.conf到客户端。
cp extraclient.crt extraclient.key ca.crt /home/firephoenix/
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /home/firephoenix/
配置修改
williamtekiMacBook-Pro:Downloads valentine$ grep -vE "^#|^;|^$" client.conf
client
dev tun
proto tcp
remote 61.183.247.97 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert extraclient.crt
key extraclient.key
ns-cert-type server
comp-lzo
verb 3
安装openvpn for windows客户端,我们可以从这个地址下载,如下:http://build.openvpn.net/downloads/releases/
建议和前面查询的版本相同的版本,如2.3.2版本。
将ca.crt
,client.conf
,extraclient.crt
,extraclient.key
四个文件放到一个文件夹中,然后再讲这个文件夹拷贝到c:\Program Files\OpenVPN\config\
文件夹下面。
启动OpenVPN的客户端之后就可以看到connect。
配置网络
固定:修改_etc_sysctl.conf,取消这一行的注释:
net.ipv4.ip_forward= 1
然后使之立即生效
sysctl -p
证书的管理
证书有效期管理
默认的OpenVPN配置,客户端证书有效期是10年。如何自定义客户端证书的时间呢?其实比较简单,编辑vars文件,找到export KEY_EXPIRE=3650这一行,把默认的3650,改为你想设置的天数即可。编辑后保存,运行一次vars,设置好环境变量,再用build-key生成客户端证书,即可。这样一来,客户端证书的有效期,就是你所设置的有效期了。
客户端证书的吊销
和PPTP VPN不一样,PPTP VPN直接删除客户端帐号,就可以了。在OpenVPN中,是通过revoke操作,吊销客户端证书,来实现禁止客户端连接OpenVPN的。
具体的方法如下:
#进入OpenVPN配置文件所在目录
#执行vars,初始化环境
. vars
#使用revoke-full命令,吊销客户端证书
./revoke-full clientName
#clientName是被吊销的客户端证书名称
命令执行后,我们能在keys目录中找到一个文件,名叫:crl.pem ,这个文件中包含了吊销证书的名单。然后,在服务端配置文件中,加入如下一行:
crl-verify crl.pem
最后一步,重启OpenVPN服务,即可
配置管理日志
默认情况下,openvpn server的配置会将日志写入_var_log/syslog 中,这种配置比较难管理,在openvpn中也添加了配置日志的部分。
# By default, log messages will go to the syslog (or
# on Windows, if running as a service, they will go to
# the "\Program Files\OpenVPN\log" directory).
# Use log or log-append to override this default.
# "log" will truncate the log file on OpenVPN startup,
# while "log-append" will append to it. Use one
# or the other (but not both).
;log openvpn.log
log-append openvpn.log
这样在_etc_openvpn/openvpn.log 下面就可以看到相应的登陆日志了。
配置mysql集成OpenVPN用户验证
安装数据库
root@vpnserver:~# apt-get install mysql-server libpam-mysql sasl2-bin
配置数据库
root@vpnserver:~# mysql -uroot -p
#建库
CREATE DATABASE `openvpn` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
mysql> use openvpn
mysql> GRANT ALL ON openvpn.* TO 'openvpn'@'localhost' IDENTIFIED BY '********';
mysql> 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;
Query OK, 0 rows affected (0.02 sec)
mysql> 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;
mysql> exit
修改openvpn配置
nano /etc/pam.d/openvpn
auth sufficient pam_mysql.so user=openvpn passwd=******** 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=******** 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。
编辑/etc/default/saslauthd
nano /etc/default/saslauthd
把START=no
改成START=yes
。
重新启动saslauthd。
/etc/init.d/saslauthd restart
先测试一下配置是否正确,先添加在mysql里面添加一个test用户,密码也是test。
mysql -uopenvpn -p
mysql>
USE openvpn;
INSERT INTO user(username, password) VALUES('test', ENCRYPT('test'));
exit
退出以后,运行
testsaslauthd -u test -p test -s openvpn
如果提示
0: OK "Success."
说明验证通过,如果验证没通过的话,检查一下_var_log/auth.log,看看是什么原因导致的错误。
配置pam验证模块
复制Openvpn的pam验证模块到Openvpn目录:
cp /usr/lib/openvpn/openvpn-plugin-auth-pam.so /etc/openvpn/
重新编辑server.conf
#增加这个配置
# user/password auth from mysql
plugin /etc/openvpn/openvpn-plugin-auth-pam.so openvpn
username-as-common-name
;client-to-client
# record in database,这两行主要做用户登陆记录和流量管控,我们这里不做流量管控,可以修改一下。
script-security 2
client-connect ./connect.sh
client-disconnect ./disconnect.sh
在disconnect里面在端口之后会记录相应的VPN流量。
流量记录
新建一个/etc/openvpn/connect.sh
文件。
nano /etc/openvpn/connect.sh
输入以下内容:
#!/bin/bash
DB='openvpn'
DBADMIN='openvpn'
DBPASSWD='password'
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
文件。
nano /etc/openvpn/disconnect.sh
输入以下内容:
#!/bin/bash
DB='openvpn'
DBADMIN='openvpn'
DBPASSWD='password'
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
其主要作用是:在用户连接时,在数据库log 表中新建一条记录,记录用户的IP 地址、端口号、连接时间等信息。在用户断开连接时,更新刚才添加的记录,记下用户的断开连接时间、发送数据量、接收数据量等。然后,对用户的流量进行判断,若超过配额,则将用户锁定(active=0)。
user 表中的quota_cycle 是用户的流量计算周期,quota_bytes 是用户每个周期内最多允许的流量。connect.sh 和disconnect.sh 脚本文件中调用了OpenVPN 的环境变量。OpenVPN 在执行脚本时,自动各种设置了环境变量,供脚本使用。
使用cron 每天对用户进行检查
以上操作在用户超过流量时自动将用户锁定。每天还应该执行一次检查,把已经恢复流量的用户解锁。可以通过cron实现此功能。
建立文件/etc/cron.daily/openvpn
nano /etc/cron.daily/openvpn
内容如下:
#!/bin/bash
DB='openvpn'
DBADMIN='openvpn'
DBPASSWD='password'
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
修改saslauthd 的缓存时间。
saslauthd 默认有一段较长的缓存时间,在用户通过认证后的一段时间里,可以再次通过认证而不需要重新查询数据库。这样不利于实现对超流量用户的立即锁定。saslauthd 启动时有一个-t 参数,可以设置其超时时间。
修改/etc/default/saslauthd
文件
nano /etc/default/saslauthd
saslauthd 启动时有一个-t 参数,可以设置其超时时间,最后一行的OPTIONS,添加-t 60。
OPTIONS="-c -m /var/run/saslauthd -t 60"
客户端的安装
Windows用户直接下载Windows Installer即可,安装按默认安装就可以了。
接下来在服务器上拷贝三个证书文件下来,分别是ca.crt,client1.key,client1.crt,放到C:\Program Files\OpenVPN\config\目录下,新建一个myvpn.ovpn文件,用记事本打开
client
dev tun
proto udp
remote 服务器ip 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client1.crt
key client1.key
#这里需要一定要增加,否则无法访问
auth-user-pass
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
ns-cert-type server
redirect-gateway
keepalive 20 60
comp-lzo
verb 3
mute 20
route-method exe
route-delay 2
非流量监控管理
在disconnect.sh 中去掉相应字段即可
#!/bin/bash
DB='openvpn'
DBADMIN='openvpn'
DBPASSWD='password'
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
将最下面的定期清理相应的超过流量的客户
tips: 这里面应该有个小bug,可以留到后面进行修改,在用户disconnect的时候,仅搜索了4个字段,用户的ip、端口、远程ip、用户名。但是可能出现跨天的情况,而update找到的是第一个,可能日志状态后续会混乱。这里后面还是应该加上相应的时间,至少需要保持更新用户几天之内的。
证书管理
用上面的方法,通过mysql连接的时候,依然需要客户端证书,才能进行登录。
所以针对安全考虑,可以分发不同的证书给不同的组织,然后针对某些组织,再分配相应的账号密码进行安全验证。
证书有效期
默认的OpenVPN配置,客户端证书有效期是10年。如何自定义客户端证书的时间呢?其实比较简单,编辑vars文件,找到export KEY_EXPIRE=3650这一行,把默认的3650,改为你想设置的天数即可。编辑后保存,运行一次vars,设置好环境变量,再用build-key生成客户端证书,即可。这样一来,客户端证书的有效期,就是你所设置的有效期了。
给客户的一些证书可以修改为30天过期,过期之后可以删除再重新生成新的证书
吊销证书
和PPTP VPN不一样,PPTP VPN直接删除客户端帐号,就可以了。在OpenVPN中,是通过revoke操作,吊销客户端证书,来实现禁止客户端连接OpenVPN的。
具体的方法如下:
#进入OpenVPN配置文件所在目录
#执行vars,初始化环境
. vars
#使用revoke-full命令,吊销客户端证书
./revoke-full clientName
#clientName是被吊销的客户端证书名称
命令执行后,我们能在keys目录中找到一个文件,名叫:crl.pem ,这个文件中包含了吊销证书的名单。然后,在服务端配置文件中,加入如下一行:
crl-verify /etc/openvpn/easy-rsa/keys/crl.pem
注意这里路径要对,要么是相对路径,否则openvpn server会起不起来
最后一步,重启OpenVPN服务,即可。
制作客户端说明文档
[[OpenVPN 客户端说明文档]]
制作一个给外部的客户端和用户名密码
生成客户端证书
cd /etc/openvpn/easy-rsa/
./build-key extraclient