openvpn进阶笔记

单服务器多个独立VPN区域配置脚本更新

准备服务器

准备conf文件

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
42
43
44
45
46
47
48
49
50
51
52
53
54
su --
vpn_region_name="pub_server"
vpn_region_name_short="pub"
vpn_root_path="/etc/openvpn/${vpn_region_name}"
vpn_conf="/etc/openvpn/${vpn_region_name}.conf"
vpn_addr="1.2.3.4"
vpn_port=12345
vpn_proto="udp"
vpn_ip_mask="10.9.10.0 255.255.255.0"

echo "port ${vpn_port}" > ${vpn_conf}
echo "proto ${vpn_proto}" >> ${vpn_conf}
echo "dev tun" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "ca ${vpn_root_path}/easy-rsa/pki/ca.crt" >> ${vpn_conf}
echo "cert ${vpn_root_path}/easy-rsa/pki/issued/server.crt" >> ${vpn_conf}
echo "key ${vpn_root_path}/easy-rsa/pki/private/server.key # keep secret" >> ${vpn_conf}
echo "dh ${vpn_root_path}/easy-rsa/pki/dh.pem" >> ${vpn_conf}
echo "crl-verify ${vpn_root_path}/easy-rsa/pki/crl.pem" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "topology subnet" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "# client-config-dir ${vpn_root_path}/ccd" >> ${vpn_conf}
echo "# ifconfig-pool-persist ${vpn_root_path}/ipp.txt" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "server ${vpn_ip_mask} # internal tun connection IP" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "#push "route 172.16.0.0 255.255.255.0 10.9.8.4 1"" >> ${vpn_conf}
echo "#push "route 172.16.32.0 255.255.254.0"" >> ${vpn_conf}
echo "#route 172.16.32.0 255.255.254.0" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "user nobody" >> ${vpn_conf}
echo "group nogroup" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "keepalive 10 120" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "tls-auth ${vpn_root_path}/static.key 0" >> ${vpn_conf}
echo "auth-nocache" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "cipher AES-256-CBC" >> ${vpn_conf}
echo "data-ciphers AES-256-CBC" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "persist-key" >> ${vpn_conf}
echo "persist-tun" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "status /var/log/openvpn/openvpn-${vpn_region_name_short}-status.log" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "verb 3 # verbose mode" >> ${vpn_conf}
echo "" >> ${vpn_conf}
echo "client-to-client" >> ${vpn_conf}
echo "explicit-exit-notify 1" >> ${vpn_conf}
echo "" >> ${vpn_conf}

chmod 700 ${vpn_conf}

准备CA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 接上文脚本

touch ${vpn_conf}
chmod 700 ${vpn_conf}
mkdir -p ${vpn_root_path}

cd ${vpn_root_path}
openvpn --genkey secret static.key
make-cadir ${vpn_root_path}/easy-rsa # 创建ca证书分发文件夹
cd ${vpn_root_path}/easy-rsa

./easyrsa init-pki # 初始化
./easyrsa build-ca # 构建ca证书,请牢记密码,后续签发客户端证书需要CA pass phrase
./easyrsa build-server-full server nopass # 构建服务器证书,nopass为无密码,如需要PEM pass密码请剔除nopass参数,后续启动服务都需要输入此密码
./easyrsa gen-dh
./easyrsa gen-crl

systemctl enable openvpn@$(pwd | cut -d'/' -f4) --now
systemctl status openvpn@$(pwd | cut -d'/' -f4)

准备客户端分发

准备模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 接上文脚本,准备示例文件
example_ovpn="${vpn_root_path}/example.ovpn"
echo "client" > ${example_ovpn}
echo "dev tun" >> ${example_ovpn}
echo "proto ${vpn_proto}" >> ${example_ovpn}
echo "remote ${vpn_addr} ${vpn_port}" >> ${example_ovpn}
echo "resolv-retry infinite" >> ${example_ovpn}
echo "nobind" >> ${example_ovpn}
echo "persist-key" >> ${example_ovpn}
echo "persist-tun" >> ${example_ovpn}
echo "remote-cert-tls server" >> ${example_ovpn}
echo "auth-nocache" >> ${example_ovpn}
echo "cipher AES-256-CBC" >> ${example_ovpn}
echo "data-ciphers AES-256-CBC" >> ${example_ovpn}
echo "mute-replay-warnings" >> ${example_ovpn}
echo "verb 3" >> ${example_ovpn}
chmod 700 ${example_ovpn}

准备自动生成脚本

新建客户端脚本

1
2
3
touch ./genclient.sh
chmod +x ./genclient.sh
chmod 700 ./genclient.sh

同目录下准备文件genclient.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
42
43
44
45
46
47
48
49
#!/bin/bash

vpn_region_name=$(dirname "$(realpath "$0")" | cut -d'/' -f4)
vpn_root_path="/etc/openvpn/${vpn_region_name}"

if [ $# -eq 0 ]; then
cat ${vpn_root_path}/easy-rsa/pki/index.txt | cut -f6
echo "请输入以上客户端以外的名字"
exit 1
else
echo "添加客户端: $1"
fi


ovpn_out="${vpn_root_path}/publish/${1}.ovpn"
mkdir -p $(dirname ${ovpn_out})

echo "预计生成路径:${ovpn_out}"
echo "请输入用户密码"

cd "${vpn_root_path}/easy-rsa/"

./easyrsa build-client-full ${1}

cat ${vpn_root_path}/example.ovpn > ${ovpn_out}

echo '<tls-auth>' >> ${ovpn_out}
cat $(cat ${vpn_root_path}.conf | grep "^tls-auth" | sed 's/ \+/ /g' | cut -d' ' -f2) >> ${ovpn_out}
echo '</tls-auth>' >> ${ovpn_out}

echo 'key-direction 1' >> ${ovpn_out}

echo '<ca>' >> ${ovpn_out}
cat $(cat ${vpn_root_path}.conf | grep "^ca" | sed 's/ \+/ /g' | cut -d ' ' -f2) >> ${ovpn_out}
echo '</ca>' >> ${ovpn_out}

echo '<cert>' >> ${ovpn_out}
cat ${vpn_root_path}/easy-rsa/pki/issued/${1}.crt >> ${ovpn_out}
echo '</cert>' >> ${ovpn_out}

echo '<key>' >> ${ovpn_out}
cat ${vpn_root_path}/easy-rsa/pki/private/${1}.key >> ${ovpn_out}
echo '</key>' >> ${ovpn_out}

chmod 744 ${ovpn_out} # 方便SCP下载 不安全,下载后确保删除
echo "生成路径:${ovpn_out}"
echo "> 下载后一定删除!"
echo "> 下载后一定删除!"
echo "> 下载后一定删除!"

注销客户端脚本

1
2
3
touch ./rmclient.sh
chmod +x ./rmclient.sh
chmod 700 ./rmclient.sh

为后续方便也可以同目录准备一个rmclient.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

vpn_region_name=$(dirname "$(realpath "$0")" | cut -d'/' -f4)
vpn_root_path="/etc/openvpn/${vpn_region_name}"

cd ${vpn_root_path}/easy-rsa

if [ $# -eq 0 ]; then
cat ${vpn_root_path}/easy-rsa/pki/index.txt | grep $'^[^R]' | cut -f6
echo "请输入需要撤销证书的客户端名"
exit 1
else
echo "撤销证书的客户端: $1"
fi
./easyrsa revoke $1
./easyrsa gen-crl

# 不要这么做 ## find ./ -type f -iname "${1}*" -print0 | xargs -0 -I {} rm -I -v {}
# 不要这么做 ## sed "/^R.*\/CN=${1}\$/d" ./pki/index.txt -i

systemctl restart openvpn@${vpn_region_name}
systemctl status openvpn@${vpn_region_name}