Write by lyc at 2022-5-6
[AWS入门]AWS客户端VPN终端节点,OpenVPN easy-rsa管理证书

什么是 PKI?

5分钟让你知道什么是PKI

1.安装 easy-rsa

easy-rsa GitHub 获取最新的安装包。

1
2
3
4
5
6
yum update -y
yum install -y openvpn
cd /usr/local/src/
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
tar xvf EasyRSA-3.0.8.tgz -C /usr/local
ln -s /usr/local/EasyRSA-3.0.8 /etc/openvpn/easy-rsa

初始化一个新的 PKI 环境

1
2
3
4
5
6
7
8
9
10
11
cd /etc/openvpn/easy-rsa
cat > /etc/openvpn/easy-rsa/vars <<EOF
set_var EASYRSA_REQ_COUNTRY "CN"
set_var EASYRSA_REQ_PROVINCE "FuJian"
set_var EASYRSA_REQ_CITY "FuZhou"
set_var EASYRSA_REQ_ORG "lyc7456"
set_var EASYRSA_REQ_EMAIL "lyc7456@qq.com"
set_var EASYRSA_REQ_OU "IT"
set_var EASYRSA_CERT_EXPIRE 3650
EOF
./easyrsa init-pki

2.自签 CA 证书

生成一个私有的CA根证书,nopass 表示证书不需要密码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ ./easyrsa build-ca nopass

Note: using Easy-RSA configuration from: /usr/local/EasyRSA-3.0.8/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.
-----
# 定义一个 CA证书名称
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:lyc7456.com

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

查看 CA 证书:

1
2
3
4
5
6
$ ls -l pki/ca* pki/private/ca*
-rw------- 1 root root 1172 May 6 16:30 pki/ca.crt
-rw------- 1 root root 1675 May 6 16:30 pki/private/ca.key

# 效验CA证书:可以查看到 CA有效期(10年)、加密算法、
$ openssl x509 -in pki/ca.crt -text -noout

3.创建吊销列表文件

1
2
3
4
5
6
7
8
$ ./easyrsa gen-crl

Note: using Easy-RSA configuration from: /usr/local/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017
Using configuration from /etc/openvpn/easy-rsa/pki/easy-rsa-20171.iKnbjV/tmp.UYdnfv

An updated CRL has been created.
CRL file: /etc/openvpn/easy-rsa/pki/crl.pem

查看吊销列表文件 crl.pem 内容

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
28
29
30
31
32
33
34
35
36
37
# 吊销列表文件位置
$ ls -l pki/crl.pem
-rw------- 1 root root 633 May 6 17:23 pki/crl.pem

# 查看内容
$ openssl crl -noout -text -in pki/crl.pem
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: /CN=gao7.com
Last Update: Jun 28 08:20:58 2022 GMT # 吊销列表最后更新时间
Next Update: Dec 25 08:20:58 2022 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:E3:1B:5A:04:77:64:E0:82:27:79:32:3E:48:EE:47:DD:BA:6F:76:46
DirName:/CN=gao7.com
serial:CF:A3:6A:2E:62:4B:7E:12

Revoked Certificates:
Serial Number: 038159B5A92F37BC2D7BE4CD161DD211 # 被吊销的证书1
Revocation Date: May 24 03:41:03 2022 GMT # 吊销时间
Serial Number: 078400FDCD7E8440A1BDC1AABA7353B0
Revocation Date: May 10 10:46:21 2022 GMT
Serial Number: 11232066B7F71B037486781DBFAD0E14
Revocation Date: Jun 28 08:20:58 2022 GMT
Serial Number: 5E51256BF2591A01B0EEC807DDD04453
Revocation Date: May 10 10:25:52 2022 GMT
Serial Number: E3FEB2069969A4CA5AC48CCC317D9C3B
Revocation Date: May 24 03:36:19 2022 GMT
Signature Algorithm: sha256WithRSAEncryption
b2:68:ed:c6:93:b9:7d:c4:e7:2d:7a:fe:56:a9:13:b5:60:17:
8f:28:69:34:1a:8a:c8:4e:4e:1e:8e:d6:63:8d:70:5f:a1:e3:
77:e1:05:54:90:cc:ab:ae:6f:f1:bf:9d:5c:25:ed:5d:83:a6:
c0:cd:42:5a:bd:bc:fd:20:a4:bb:e7:86:6f:56:ec:22:86:57:
50:a0:4e:d9:53:62:39:f2:f6:a4:09:d4:f0:99:4b:89:49:96:
26:d3:a7:99:b4:f3:6f:54:10:37:ec:67:79:f8:51:0c:15:ce:
92:c1:08:2e

4.创建服务器证书

由于我们 init-pki 初始化时,设置了 set_var EASYRSA_CERT_EXPIRE 3650,所以这里服务器证书的有效时间为 10年,而有效期默认的只有 825 days。这个时间不能大于 CA 证书的有效时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ./easyrsa build-server-full server nopass

Note: using Easy-RSA configuration from: /usr/local/EasyRSA-3.0.8/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/easy-rsa-20203.iO9a0j/tmp.PjYPZd'
-----
Using configuration from /etc/openvpn/easy-rsa/pki/easy-rsa-20203.iO9a0j/tmp.gwy54A
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 May 3 09:30:40 2032 GMT (3650 days) # 有效期10年

Write out database with 1 new entries
Data Base Updated

查看证书

1
2
3
4
5
6
7
# 服务器证书位置
$ ls -l pki/issued/server.crt pki/private/server.key
-rw------- 1 root root 4547 May 6 17:30 pki/issued/server.crt
-rw------- 1 root root 1708 May 6 17:30 pki/private/server.key

# 效验证书
$ openssl x509 -noout -text -in pki/issued/server.crt

5.创建算法密钥文件

创建算法密钥文件 dh.pem,主要是用于 pki 证书 key 时效性验证。

1
2
3
4
5
6
7
8
9
# 创建 Diffie-Hellman 算法密钥文件,默认dh文件创建长度为2048
$ ./easyrsa gen-dh

DH parameters of size 2048 created at /etc/openvpn/easy-rsa/pki/dh.pem


# 查看 dh.pem 算法密钥文件
$ ls -l pki/dh.pem
-rw------- 1 root root 424 May 6 17:32 pki/dh.pem

6.创建 TA Key

创建 tls 认证密钥 tls-auth Key ,主要用来防止 DDos 和 TLS 攻击。

1
2
cd /etc/openvpn/easy-rsa/pki
openvpn --genkey --secret ta.key

整理服务器端证书

把所有服务器端需要的证书拷贝到 openvpn vpn 服务端目录保存

1
2
3
4
5
6
7
8
mkdir -p /etc/openvpn/server/certs
cd /etc/openvpn/server/certs/
cp /etc/openvpn/easy-rsa/pki/{dh.pem,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/pki/ta.key ./
chown -R openvpn.openvpn /etc/openvpn/server/certs
chmod -R 0600 /etc/openvpn/server/certs

7.创建客户端证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cd /etc/openvpn/easy-rsa
./easyrsa build-client-full user001 nopass

Note: using Easy-RSA configuration from: /usr/local/EasyRSA-3.0.8/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/easy-rsa-20327.8ZOZXa/tmp.3nt3pw'
-----
Using configuration from /etc/openvpn/easy-rsa/pki/easy-rsa-20327.8ZOZXa/tmp.61tIhQ
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'user001'
Certificate is to be certified until May 3 09:36:34 2032 GMT (3650 days) # 有效期10年

Write out database with 1 new entries
Data Base Updated

查看证书

1
2
3
4
5
6
7
# 证书位置
$ ls -l pki/issued/user001* pki/private/user001*
-rw------- 1 root root 4437 May 6 16:54 pki/issued/user001.crt
-rw------- 1 root root 1704 May 6 16:54 pki/private/user001.key

# 校验证书
openssl x509 -noout -text -in pki/issued/user001.crt

整理客户端证书

把所有客户端需要的证书拷贝到 openvpn vpn 客户端目录保存

1
2
3
4
5
6
mkdir -p /etc/openvpn/client/certs
cd /etc/openvpn/client/certs/
cp /etc/openvpn/easy-rsa/pki/issued/user001.crt ./
cp /etc/openvpn/easy-rsa/pki/private/user001.key ./
chown -R openvpn.openvpn /etc/openvpn/client/certs
chmod -R 0600 /etc/openvpn/client/certs

把客户端证书 xxx.crt 和密钥文件 xxx.key 下发给客户端使用。

8.使用脚本来创建客户端服务器模式的客户端证书与客户端配置文件(可选)

先创建一个供脚本调用的客户端证书模板文件,变量 ${OPENVPN_SERVER_HOSTS} 替换成 openvepn 服务端的域名或IP地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ vim /etc/openvpn/client/agent_template.ovpn
client
proto udp
dev tun
nobind
remote ${OPENVPN_SERVER_HOSTS} 1194
ca ca.crt
cert user.crt
key user.key
tls-auth ta.key 1
remote-cert-tls server
persist-tun
persist-key
comp-lzo
verb 3
mute-replay-warnings

创建脚本 create_user.sh

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ vim /etc/openvpn/client/create_user.sh
#!/usr/bin/env bash
# Author: jackzang
# mail: jackzang@aishangwei.net
# Date: 2020/2/9

# 如果脚本执行报错,则停止
set -e

# 配置目录
USER_KEYS_DIR=/etc/openvpn/client/certs
EASY_RSA_VER=3
EASY_RSA_DIR=/etc/openvpn/easy-rsa
PKI_DIR=${EASY_RSA_DIR}/${EASY_RSA_VER}/pki

# 安装 zip
rpm -qa|grep ^zip || yum -y install zip

# 循环创建多个用户
for user in "$@"
do
# 如果用户已存在,跳出本次循环
if [ -d ${USER_KEYS_DIR}/${user} ]; then
echo "[Warning] $user already exists!"
break
fi
# 创建用户
cd ${EASY_RSA_DIR}/${EASY_RSA_VER}
./easyrsa build-client-full ${user} nopass
mkdir -p ${USER_KEYS_DIR}/${user}
cp ${PKI_DIR}/ca.crt ${USER_KEYS_DIR}/${user}
cp ${PKI_DIR}/issued/${user}.crt ${USER_KEYS_DIR}/${user}
cp ${PKI_DIR}/private/${user}.key ${USER_KEYS_DIR}/${user}
cp /etc/openvpn/client/agent_template.ovpn ${USER_KEYS_DIR}/${user}/${user}.ovpn
sed -i "s/user/"${user}"/g" ${USER_KEYS_DIR}/${user}/${user}.ovpn
cp /etc/openvpn/server/certs/ta.key ${USER_KEYS_DIR}/${user}/ta.key
# 打包用户文件
cd ${USER_KEYS_DIR}
zip -r ${user}.zip ${user}
done
exit 0

脚本授权

1
chmod +x /etc/openvpn/client/create_user.sh

创建客户端证书

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
$ /etc/openvpn/client/create_user.sh user001
zip-3.0-11.el7.x86_64

Note: using Easy-RSA configuration from: /usr/share/easy-rsa/3.0.8/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/3/pki/easy-rsa-22118.7RWFvd/tmp.uKvcV1'
-----
Using configuration from /etc/openvpn/easy-rsa/3/pki/easy-rsa-22118.7RWFvd/tmp.oFIaSm
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'user001'
Certificate is to be certified until Jul 25 06:05:57 2024 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

adding: user001/ (stored 0%)
adding: user001/ca.crt (deflated 27%)
adding: user001/user001.crt (deflated 45%)
adding: user001/user001.key (deflated 23%)
adding: user001/user001.ovpn (deflated 30%)
adding: user001/ta.key (deflated 40%)

查看客户端证书

1
2
3
4
5
6
7
8
9
10
$ cd /etc/openvpn/client
$ tree keys/
keys/
├── user001
│   ├── ca.crt
│   ├── ta.key
│   ├── user001.crt
│   ├── user001.key
│   └── user001.ovpn
└── user001.zip # 下载客户端证书

最终得到 openvpn 的客户端证书压缩包 user001.zip,下载下来发给申请 vpn 权限的员工。

9.吊销客户端证书

当员工离职时,需要删除该员工的 vpn 权限,那么就需要吊销客户端证书。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 吊销客户端证书
$ cd /etc/openvpn/easy-rsa
$ ./easyrsa revoke user001

Note: using Easy-RSA configuration from: /usr/local/EasyRSA-3.0.8/vars
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017


Please confirm you wish to revoke the certificate with the following subject:

subject=
commonName = user001


Type the word 'yes' to continue, or any other input to abort.
Continue with revocation: yes # 输入 yes
Using configuration from /etc/openvpn/easy-rsa/pki/easy-rsa-20412.oWky4r/tmp.QdaEcP
Revoking Certificate DE193FB7B09E369896440B91E0C80313.
Data Base Updated

IMPORTANT!!!

Revocation was successful. You must run gen-crl and upload a CRL to your
infrastructure in order to prevent the revoked cert from being accepted.

重新生成吊销列表。

1
$ ./easyrsa gen-crl

openvpn 服务器端配置文件,需要配置引用吊销列表。

1
2
3
$ vim /etc/openvpn/server/server.conf
.... # 省略其他
crl-verify /etc/openvpn/easy-rsa/3/pki/crl.pem

openvpn 客户端就无法连接上了。

查看一下新生成的吊销列表。

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
28
29
30
31
32
33
34
$ openssl crl -noout -text -in  pki/crl.pem
Certificate Revocation List (CRL):
Version 2 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: /CN=gao7.com
Last Update: May 10 10:46:21 2022 GMT
Next Update: Nov 6 10:46:21 2022 GMT
CRL extensions:
X509v3 Authority Key Identifier:
keyid:E3:1B:5A:04:77:64:E0:82:27:79:32:3E:48:EE:47:DD:BA:6F:76:46
DirName:/CN=gao7.com
serial:CF:A3:6A:2E:62:4B:7E:12

Revoked Certificates:
Serial Number: 078400FDCD7E8440A1BDC1AABA7353B0 # user001
Revocation Date: May 10 10:46:21 2022 GMT
Serial Number: 5E51256BF2591A01B0EEC807DDD04453 # user002
Revocation Date: May 10 10:25:52 2022 GMT
Signature Algorithm: sha256WithRSAEncryption
0d:84:1f:e3:0c:62:1a:04:6f:51:b4:25:00:a1:f9:7e:5e:fb:
ab:e8:dd:d2:d8:2a:20:76:da:2e:c0:c8:0d:46:dd:7c:13:e9:
27:7e:60:64:71:0d:38:a3:ae:21:70:31:48:57:08:cc:88:e5:
92:12:ea:55:a3:7a:e2:50:ac:d8:8b:c5:7f:c4:76:a2:b9:41:
e3:86:36:ad:e9:e9:b2:6d:a4:8e:3a:01:32:b2:56:f5:a5:d3:
ff:3d:4f:61:a2:48:14:ca:32:73:9b:99:00:93:45:e7:c5:d4:
d5:6d:c8:7d:4d:6a:ee:b4:c9:a3:23:6d:ff:21:fb:38:92:42:
c9:ce:2c:a8:ef:e4:35:17:e0:ce:4b:87:eb:e4:28:b9:8e:bf:
41:fe:47:fa:d0:13:0c:6a:a9:7d:99:77:25:aa:b6:b9:2d:cc:
d8:96:c8:65:4c:46:aa:0b:89:85:c2:0c:01:17:25:00:dd:19:
e5:89:f8:dd:e3:28:b3:19:c9:ca:3e:b9:ce:ba:aa:80:5d:32:
a8:a4:5b:42:fa:13:79:f6:7c:72:98:65:be:b4:a5:1f:d0:84:
64:4c:76:b7:3d:1f:d6:bb:ce:90:35:ff:c7:c3:dd:4e:60:47:
e3:b2:80:9c:7f:ba:46:03:b1:0f:6d:47:88:89:af:10:d6:d1:
d4:26:7e:95

10.更新客户端证书

证书有效期(EASYRSA CERT EXPIRE)默认为825天,通过调节参数 set_var EASYRSA_CERT_EXPIRE 825 来修改预设值。

更新证书有效期,需要在证书过期前 30 天内才能进行更新操作,否则将会报错如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
./easyrsa renew client1.domain.tld
Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017


Please confirm you wish to renew the certificate with the following subject:

subject=
commonName = client1.domain.tld


Type the word 'yes' to continue, or any other input to abort.
Continue with renew: <输入yes>

Easy-RSA error:

Certificate expires in more than 30 days.
Renewal not allowed.

通过配置参数来改变这个时间

1
2
$ vi vars
set_var EASYRSA_CERT_RENEW 1000

再次执行

1
./easyrsa renew ${commonName}