openVPN-2-4-8—基于传统方式进行用户认证
# 1,环境说明
由于不同环境及软件版本命令使用略有差异,特别是 easy-rsa 的使用在 2.0 和 3.0 的差别有点大,所以在此先说明下安装环境及相关软件版本:
- 系统平台:
Centos7.4
- OpenVPN (opens new window) 版本:
2.4.8
- easy-rsa 版本:
3.0.6
尽管不同环境及软件版本命令使用略有所差异,但是整个搭建过程都是一致的:
安装相关软件—> 生成相关证书:CA 根证书、服务器证书—> 配置基于 MySQL 认证—> 配置 open VPN 服务端—> 添加防火墙规则:snat—> 启动 open VPN 服务端。
# 2,安装软件
- 安装 epel 源
yum -y install epel-release
- 安装核心软件
yum -y install openvpn easy-rsa iptables-services
# 3,制作证书
使用 easy-rsa 生成需要的证书及相关文件,在这个阶段会产生一些 key 和证书:
- CA 根证书
- OpenVPN 服务器 ssl 证书
- Diffie-Hellman 算法用到的 key
# 1,移动到统一管理目录
将 easy-rsa
脚本复制到 /etc/openvpn/
,该脚本主要用来方便地生成 CA 证书和各种 key
mkdir -p /etc/openvpn/easy-rsa/
# 这下边哪个目录都行,其实都是软链的关系
cp -a /usr/share/easy-rsa/3/* /etc/openvpn/easy-rsa/
2
3
# 2,配置环境变量
跳到 easy-rsa
目录并编辑 vars
文件,添加一些生成证书时用到的变量。
$ cd /etc/openvpn/easy-rsa
$ vim vars # 没这个文件的话新建,填写如下内容(变量值根据实际情况随便填写):
export KEY_COUNTRY="CN"
export KEY_PROVINCE="ZJ"
export KEY_CITY="Hangzhou"
export KEY_ORG="ERYAJF, Inc"
export KEY_EMAIL="Linuxlql@163.com"
export KEY_CN=vpn.eryajf.net
export KEY_NAME=vpnserver
export KEY_OU=OPS
$ source ./vars # 使变量生效
2
3
4
5
6
7
8
9
10
11
KEY_COUNTRY
:定义所在的国家KEY_PROVINCE
:定义所在的省份KEY_CITY
:定义所在的城市KEY_ORG
:定义所在的组织KEY_EMAIL
:定义邮箱地址KEY_CN
:自定义 VPN 域名KEY_NAME
:自定义 VPN 名称KEY_OU
:定义所在的单位
补充: 评论区有同学指出,添加配置的时候,还应该增加如下两条配置,否则重新签发会比较麻烦。
# 服务端证书有效期,默认是865天
export EASYRSA_CERT_EXPIRE 865
# CA证书有效期,默认是3650天
export EASYRSA_CA_EXPIRE 3650
2
3
4
未经验证,但你部署的时候可以加上。
# 3,生成 CA 根证书
初始化pki
目录,待会儿生成的证书都会放到这个目录下。
./easyrsa init-pki
Note: using Easy-RSA configuration from: ./vars
init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easy-rsa/pki
2
3
4
生成 CA 根证书, 输入 Common Name
,名字随便起。
./easyrsa build-ca nopass
Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating RSA private key, 2048 bit long modulus
............................................................................................................+++
...................+++
e is 65537 (0x10001)
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:eryajf-vpn
CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/easy-rsa/pki/ca.crt
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 4,生成服务端证书
第一个参数 server 为证书名称,可以随便起,比如 ./easyrsa build-server-full openvpn nopass
./easyrsa build-server-full server nopass
Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating a 2048 bit RSA private key
......................................................................................................................................................................................................................+++
..............................+++
writing new private key to '/etc/openvpn/easy-rsa/pki/private/server.key.bF3aSjbwlQ'
-----
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'server'
Certificate is to be certified until Jan 16 09:03:45 2023 GMT (1080 days)
Write out database with 1 new entries
Data Base Updated
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 5,生成 Diffie-Hellman 算法需要的密钥文件
创建 Diffie-Hellman,这可能得等一小会儿。
./easyrsa gen-dh
Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
..................................................................................................................................................................................................................................................................+...........................................................................................................+...........................+............................................................................................................................................................................................................+.................................+.................................................................................................................................................................................................+..........+..............................................................................................................................................+.........................................+.......+......+..................................................................+.....................................................................+..............................................................+..................................+........+..............................................................................................................+........................................+........................................................................................................................+................................................................................................................................................................................++*++*
DH parameters of size 2048 created at /etc/openvpn/easy-rsa/pki/dh.pem
2
3
4
5
6
7
# 6,生成 tls-auth key
这个 key 主要用于防止 DoS 和 TLS 攻击,这一步其实是可选的,但为了安全还是生成一下,该文件在后面配置 open VPN 时会用到。
openvpn --genkey --secret ta.key
# 7,移动到统一管理目录
将上面生成的相关证书文件整理到 /etc/openvpn/server/certs
(这一步完全是为了维护方便)
mkdir /etc/openvpn/server/certs && cd /etc/openvpn/server/certs
cp /etc/openvpn/easy-rsa/pki/dh.pem ./
cp /etc/openvpn/easy-rsa/pki/ca.crt ./
cp /etc/openvpn/easy-rsa/pki/issued/server.crt ./
cp /etc/openvpn/easy-rsa/pki/private/server.key ./
cp /etc/openvpn/easy-rsa/ta.key ./
2
3
4
5
6
# 8,创建 open VPN 日志目录
mkdir -p /var/log/openvpn/
chown openvpn:openvpn /var/log/openvpn
2
# 4,配置 OpenVPN
可以从 /usr/share/doc/openvpn-/sample/sample-config-files
复制一份 demo 到 /etc/openvpn/
(openvpn 版本号查看:yum info openvpn。)然后改改,或者从头开始创建一个新的配置文件。
我选择新建配置:
cd /etc/openvpn/
vim server.conf
2
填入如下内容(很多配置项不需要特别了解,重要的配置这里注释出来了,其他相关配置项想了解的话见 这里 (opens new window)):
# 监听的端口号
port 1194
# 服务端用的协议,udp 能快点,所以我选择 udp
proto udp
# 定义openvpn运行时使用哪一种模式,openvpn有两种运行模式一种是tap模式,一种是tun模式。
# tap模式也就是桥接模式,通过软件在系统中模拟出一个tap设备,该设备是一个二层设备,同时支持链路层协议。
# tun模式也就是路由模式,通过软件在系统中模拟出一个tun路由,tun是ip层的点对点协议。
dev tun
# 定义openvpn在使用tun路由模式时,分配给client端分配的IP地址段
server 10.8.0.0 255.255.255.0
# 这条命令可以重定向客户端的网关,在进行翻墙时会使用到
push "redirect-gateway def1 bypass-dhcp"
# 向客户端推送的路由信息,如下内容表示客户端连接之后与当前互通
push "route 10.0.0.0 255.255.0.0"
# 向客户端推送的DNS信息
push "dhcp-option DNS 223.5.5.5"
push "dhcp-option DNS 223.6.6.6"
push "dhcp-option DNS 114.114.114.114"
# 定义活动连接保时期限
keepalive 10 300
# 加密类型
cipher AES-256-CBC
# 启用允许数据压缩,客户端配置文件也需要有这项
comp-lzo
# 最多允许连接1000个客户端
max-clients 1000
# 通过keepalive检测超时后,重新启动VPN,不重新读取keys,保留第一次使用的keys
persist-key
# 通过keepalive检测超时后,重新启动VPN,一直保持tun或者tap设备是linkup的。否则网络连接,会先linkdown然后再linkup
persist-tun
# 指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
verb 4
# 重复日志记录限额
mute 20
# 禁用TSL重协商
reneg-sec 0
# 此选项开启只能使用udp协议。否则会报错error: --explicit-exit-notify can only be used with --proto udp
explicit-exit-notify 1
# 客户端1,服务端是0
key-direction 0
# 2.4版本之前使用 tls-auth,如果高于此版本,则用tls-crypt,我用的2.4.8使用了tls-auth,结果连通之后无法访问外网了
tls-crypt /etc/openvpn/server/certs/ta.key 0
# 记录客户端和虚拟ip地址之间的关系。在openvpn重启时,再次连接的客户端将依然被分配和断开之前的IP地址
ifconfig-pool-persist /etc/openvpn/ipp.txt
# 使用客户提供的UserName作为Common Name
username-as-common-name
# 基于mysql进行认证,如不需要可注释掉
plugin /etc/openvpn/openvpn-plugin-auth-pam.so openvpn
# CA 根证书路径
ca /etc/openvpn/server/certs/ca.crt
# open VPN 服务器证书路径
cert /etc/openvpn/server/certs/server.crt
# open VPN 服务器密钥路径
key /etc/openvpn/server/certs/server.key
# Diffie-Hellman 算法密钥文件路径
dh /etc/openvpn/server/certs/dh.pem
# 指定 log 文件位置
log /var/log/openvpn/server.log
log-append /var/log/openvpn/server.log
status /var/log/openvpn/status.log
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# 5,防火墙相关配置
# 1,防火墙
禁用 Centos7 默认的 firewalld,使用经典的 iptables 防火墙管理软件:
systemctl stop firewalld
systemctl mask firewalld
2
# 2,禁用 SELinux
马上关闭:setenforce 0
临时生效
永久关闭:sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
| 需要重启服务器生效
# 3,启用 iptables
systemctl enable iptables
systemctl start iptables
iptables -F # 清理所有防火墙规则
2
3
# 4,添加防火墙规则
将 openvpn 的网络流量转发到公网:snat 规则
# 如下网段记得与server.conf 当中定义的网段保持一致
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
iptables -L -t nat
iptables-save > /etc/sysconfig/iptables # iptables 规则持久化保存
2
3
4
# 5,Linux 服务器启用地址转发
echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
sysctl -p # 这一步一定得执行,否则不会立即生效。
2
# 6,安全组
如果是云服务器,还需要注意将当前服务器安全组的 1194 端口开放,而确实 udp 的协议。
# 6,启动 open VPN
systemctl start openvpn@server # 启动
systemctl enable openvpn@server # 开机自启动
systemctl status openvpn@server # 查看服务状态
2
3
启动之后,服务端会生成一个 tun0 的网卡:
$ ifconfig tun0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.8.0.1 netmask 255.255.255.255 destination 10.8.0.2
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 715 bytes 107530 (105.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 626 bytes 194611 (190.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2
3
4
5
6
7
8
现在,就已经配置好了 openVPN 的服务端接下来的事情就是分配不同的用户供给客户端进行使用了。
# 7,用户管理
openVPN 的部署并不是困难的,这只是前期一小部分工作而已,后期更多需要忙活的,则是用户的管理,用户管理有多种方式,可以用传统方式,也可以结合 mysql 来存储用户信息,也可以基于 LDAP 进行管理,接下来就对这些方案一一进行验证。
# 1,创建用户
接下来在服务端创建一个 open VPN 用户:其实创建用户的过程就是生成客户端 SSL 证书的过程,然后将其他相关的证书文件
、key
、.ovpn
文件(客户端配置文件)打包到一起供客户端使用。
由于创建一个用户的过程比较繁琐,所以在此将整个过程写成了一个脚本 ovpn_user.sh
,通过脚本方便创建用户。
首先创建一个客户端配置模板文件 sample.ovpn
,该文件在脚本中会用到,放到 /etc/openvpn/client/
目录。cat /etc/openvpn/client/sample.ovpn:
# 指定这是一个客户端,我们将从服务器获取某些配置文件指令
client
# 在大多数系统中,除非你部分禁用或者完全禁用了TUN/TAP接口的防火墙,否则VPN将不起作用
dev tun
# 指定连接的服务器是采用TCP还是UDP协议,这里需要使用与服务器端相同的设置
proto udp
# 指定服务器的主机名(或IP)以及端口号,如果有多个VPN服务器,为了实现负载均衡,你可以设置多个remote指令
remote my-server-1 21198
;remote my-server-2 21198
# 启用该指令,与服务器连接中断后将自动重新连接,这在网络不稳定的情况下(例如:笔记本电脑无线网络)非常有用
resolv-retry infinite
# 大多数客户端不需要绑定本机特定的端口号
nobind
# 持久化选项可以尽量避免访问在重启时由于用户权限降低而无法访问的某些资源
persist-key
persist-tun
remote-cert-tls server
# 启用允许数据压缩,服务端配置文件也需要有这项
comp-lzo
# 指定日志文件的记录详细级别,可选0-9,等级越高日志内容越详细
verb 3
auth-nocache
script-security 3
ca ca.crt
cert admin.crt
key admin.key
tls-crypt ta.key 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
下面为创建 open VPN 用户脚本cat /etc/openvpn/client/ovpn_user.sh:
# ! /bin/bash
set -e
OVPN_USER_KEYS_DIR=/etc/openvpn/client/keys
EASY_RSA_DIR=/etc/openvpn/easy-rsa/
PKI_DIR=$EASY_RSA_DIR/pki
for user in "$@"
do
if [ -d "$OVPN_USER_KEYS_DIR/$user" ]; then
rm -rf $OVPN_USER_KEYS_DIR/$user
rm -rf $PKI_DIR/reqs/$user.req
sed -i '/'"$user"'/d' $PKI_DIR/index.txt
fi
cd $EASY_RSA_DIR
# 生成客户端 ssl 证书文件
./easyrsa build-client-full $user nopass
# 整理下生成的文件
mkdir -p $OVPN_USER_KEYS_DIR/$user
cp $PKI_DIR/ca.crt $OVPN_USER_KEYS_DIR/$user/ # CA 根证书
cp $PKI_DIR/issued/$user.crt $OVPN_USER_KEYS_DIR/$user/ # 客户端证书
cp $PKI_DIR/private/$user.key $OVPN_USER_KEYS_DIR/$user/ # 客户端证书密钥
cp /etc/openvpn/client/sample.ovpn $OVPN_USER_KEYS_DIR/$user/$user.ovpn # 客户端配置文件
sed -i 's/admin/'"$user"'/g' $OVPN_USER_KEYS_DIR/$user/$user.ovpn
cp /etc/openvpn/server/certs/ta.key $OVPN_USER_KEYS_DIR/$user/ta.key # auth-tls 文件
cd $OVPN_USER_KEYS_DIR
zip -r $user.zip $user
done
exit 0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
执行上面脚本创建一个用户:sh ovpn_user.sh testuser1
$ sh ovpn_user.sh testuser1
Note: using Easy-RSA configuration from: ./vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Generating a 2048 bit RSA private key
.......+++
....................................+++
writing new private key to '/etc/openvpn/easy-rsa/pki/private/testuser1.key.wwfcLvbunb'
-----
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'testuser1'
Certificate is to be certified until Jan 16 09:36:22 2023 GMT (1080 days)
Write out database with 1 new entries
Data Base Updated
adding: testuser1/ (stored 0%)
adding: testuser1/testuser1.ovpn (deflated 30%)
adding: testuser1/ca.crt (deflated 26%)
adding: testuser1/testuser1.key (deflated 23%)
adding: testuser1/testuser1.crt (deflated 46%)
adding: testuser1/ta.key (deflated 40%)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
会在 /etc/openvpn/client/keys
目录下生成以用户名命名的 zip 打包文件,将该压缩包下载到本地解压,然后将里面的 .ovpn
文件拖拽到 Tunnelblick 客户端软件即可使用。
压缩包里面文件有如下,示例:
.
├── ca.crt
├── username.crt
├── username.key
├── username.ovpn
└── ta.key
2
3
4
5
6
# 2,客户端是 Linux
这个时候,可以拿上刚刚生成的压缩包,传到客户端主机,然后进行如下配置。
当客户端是 Linux 的时候,先在主机上安装一下客户端。
yum -y install epel-release
yum -y install openvpn
2
然后把配置拷贝到主机。
$ pwd
/etc/openvpn
$ ls /etc/openvpn
ca.crt ta.key testuser1.crt testuser1.key testuser1.ovpn
2
3
4
现在简单重命名下:
mv testuser1.ovpn client.conf
然后启动客户端:
systemctl restart openvpn@client
然后能够看到本机多了一个 tun0 的网卡:
$ ifconfig tun0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.8.0.6 netmask 255.255.255.255 destination 10.8.0.5
inet6 fe80::4783:6d65:a65c:2ae5 prefixlen 64 scopeid 0x20<link>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 100 (UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3 bytes 144 (144.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2
3
4
5
6
7
8
9
服务器正是借助于这个网卡实现与服务器同网段内的内网通信的。
# 3,客户端是 Mac。
要连接到 open VPN 服务端首先得需要一个客户端软件,在 Mac 下推荐使用 Tunnelblick (opens new window),下载地址:https://tunnelblick.net/。Tunnelblick 是一个开源、免费的 Mac 版 open VPN 客户端软件。
下载之后进行安装,安装方式非常简单,直接将上边生成的压缩包下载到本地,然后进行解压,解压完成之后,双击 testuser1.ovpn
即可自动安装到 Tunnelblick 客户端当中,添加之后的配置可以在界面中查看,如下:
也可以直接在终端查看:
$ ls /Library/Application\ Support/Tunnelblick/Shared/testuser1.tblk/Contents/Resources/
ca.crt config.ovpn ta.key testuser1.crt testuser1.key
2
然后直接点击连接,如果配置没有问题,那么就会看到认证成功。这个时候可以 ping 一下内网,以及百度等,如果都没有问题,则说明配置正常。
# 4,删除一个 OpenVPN 用户
上面我们知道了如何添加一个用户,那么如果公司员工离职了或者其他原因,想删除对应用户 OpenVPN 的使用权,该如何操作呢?其实很简单,OpenVPN 的客户端和服务端的认证主要通过 SSL 证书进行双向认证,所以只要吊销对应用户的 SSL 证书即可。
编辑 OpenVPN 服务端配置 server.conf 添加如下配置:
crl-verify /etc/openvpn/easy-rsa/3/pki/crl.pem
1吊销用户证书,假设要吊销的用户名为 username
cd /etc/openvpn/easy-rsa/3/ ./easyrsa revoke username ./easyrsa gen-crl
1
2
3重启 OpenVPN 服务端使其生效
systemctl start openvpn@server
1
为了方便,也将上面步骤整理成了一个脚本,可以一键删除用户:
del_ovpn_user.sh:
# ! /bin/bash
set -e
OVPN_USER_KEYS_DIR=/etc/openvpn/client/keys
EASY_RSA_VERSION=3
EASY_RSA_DIR=/etc/openvpn/easy-rsa/
for user in "$@"
do
cd $EASY_RSA_DIR/$EASY_RSA_VERSION
echo -e 'yes\n' | ./easyrsa revoke $user
./easyrsa gen-crl
# 吊销掉证书后清理客户端相关文件
if [ -d "$OVPN_USER_KEYS_DIR/$user" ]; then
rm -rf $OVPN_USER_KEYS_DIR/${user}*
fi
systemctl restart openvpn@server
done
exit 0
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 8,遇到的问题
# 问题 1
open VPN 客户端可以正常连接到服务端,但是无法上网,ping 任何地址都不通,只有服务端公网 ip 可以 ping 通。
问题原因及解决方法:主要原因是服务的地址转发功能没打开,其实我前面配置
了 echo net.ipv4.ip_forward = 1 >> /etc/sysctl.conf
,但是没有执行 sysctl -p
使其
立即生效,所以才导致出现问题。因此一定要记得两条命令都要执行。
# 问题 2
open VPN 可以正常使用,但是看客户端日志却有如下错误:
2020-02-02 17:05:59 AEAD Decrypt error: bad packet ID (may be a replay): [ #6361 ] -- see the man page entry for --no-replay and --replay-window for more info or silence this warning with --mute-replay-warnings
2020-02-02 17:05:59 AEAD Decrypt error: bad packet ID (may be a replay): [ #6508 ] -- see the man page entry for --no-replay and --replay-window for more info or silence this warning with --mute-replay-warnings
2
问题原因及解决方法: 其实这个问题一般在 open VPN 是 UDP 服务的情况下出现,主要原因是 UDP 数据包重复发送导致,在 Wi-Fi 网络下经常出现,这并不影响使用,但是我们可以选择禁止掉该错误:根据错误提示可知使用 –mute-replay-warnings 参数可以消除该警告,我们使用的 open VPN 是 GUI 的,所以修改客户端 .ovpn 配置文件,末尾添加:mute-replay-warnings 即可解决。
该问题在这里有讨论: https://sourceforge.net/p/openvpn/mailman/message/10655695/
# 相关文档
关于 open VPN 客户端和服务端配置文件配置项说明:很全面,可以随时查看不懂的配置项 https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://openvpn.net/ | OpenVPN 官网 https://www.fandenggui.com/post/centos7-install-openvpn.html | Centos7 安装 OpenVPN https://www.howtoing.com/how-to-install-openvpn-on-centos-7 | Centos7 安装 OpenVPN
https://www.xiaohui.com/dev/server/20070904-revoke-openvpn-client.htm | 吊销客户端证书 https://scott.stevensononthe.net/2015/02/how-to-addremove-additional-users-to-openvpn/ | 吊销客户端证书 https://tunnelblick.net/cConnectedBut.html | open VPN 一些常见问题 https://tunnelblick.net/ipinfo | 本地公网 ip 查看