具有两层CA层次结构的OpenVPN

最近,我碰巧遇到了在debian上为OpenVPN创建两级证书颁发机构的任务。很多时候,我有机会向一个认证机构提出OpenVPN,并完全理解两个CA在理论上应该是怎样的,但是在实践中,我遇到了一个事实,就是我不知道在什么地方签名。 Google并没有提供适合Linux的答案(或者我没有用Google搜索),于是我开始弄清楚。下面提供了我在创建和配置过程中编写的手册。



我想马上指出,在这里我比在OpenVPN上更加注重设置CA。



在开始之前,我将告诉所有可以在示例中使用它的人。



我的任务是为一家大公司创建一个系统,使得只有一个人签署了OpenVPN服务器证书,有很多VPN服务器,每个部门都安装了几台VPN服务器。每次来/离开公司的员工负担非常重(更不用说临时员工)时,还会有更多的员工(客户)和控制(颁发/吊销)证书。每个部门的员工均受部门负责人的监督,部门负责人分别为新员工/旧员工颁发或撤销证书。



对于需要什么证书和数字密钥,已经说了很多,我不再重复其他作者,但总之,然后:



  • 为了验证可靠性(发生“两次握手”),客户端和服务器确保他们是谁,他们是否可以彼此信任并建立连接;
  • 加密/解密;
  • “中间人(MITM)”例外,以确保没有人拦截消息/流量;
  • 创建加密密码,从而提高安全性,并使攻击者更难访问主机。


多级CA层次结构的工作原理是,顶级CA(RootCA)会在足够长的时间内为自己签署证书(但这纯粹是个人的事情),CA层次结构中每个下一个较低级别或服务都使用上级CA签署其证书(通常官僚制),条件是较低级别的证书的有效期不得超过较高级别证书的有效期的一半。







创建CA时,将创建两个文件:ca.crt-公钥和ca.key-私钥。

私钥必须受到保护,并且不得与第三方共享。



当我们需要创建从属/签名CA时,我们在其上创建一个私钥以及从RootCA进行签名的请求。



您问世界各地的计算机和用户如何知道他们可以信任服务或站点?很简单(从理论上讲),将CA的公钥(RootCA)放在用户的计算机上,并且这些计算机信任此CA颁发的所有证书。在实践中,这当然更加困难并且不便宜。但是在您自己的公司中,这很容易做到。



为了实现,我们需要三台服务器。在本教程中,我们将使用debian9。我们将根据服务器的应用程序命名服务器:OpenVPN,SubCA,RootCA。



所有操作均在用户而非root用户下执行。



为此,您的用户必须位于sudo组中。



如果服务器上未安装sudo,请以root用户身份登录:



# su - root
# apt-get install sudo -y
# usermod -aG sudo username
# exit


我们在所有服务器上安装了必要的实用程序(实用程序可能因信念而不同,wget,ufw,vim是强制性的,因为在这里我已使用这些实用程序给出了命令):



# sudo apt-get update
# sudo apt-get upgrade
# sudo apt-get install wget curl net-tools ufw vim -y
# cd ~
# wget -P ~/ https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.4/EasyRSA-3.0.4.tgz
# tar xvf EasyRSA-3.0.4.tgz


在OpenVPN服务器上安装openvpn:



# sudo apt-get install openvpn -y


转到RootCA服务器。在这里我们需要创建一个文件,easyrsa将从该文件中获取变量的值:



# mv ~/EasyRSA-3.0.4 ~/easyrsa/
# cd ~/easyrsa/
# cp vars.example vars
# vim vars


找到该块,删除#并替换我们的值。为了在签署证书时不输入我们的数据,我们将在此处编写它们:



#set_var EASYRSA_REQ_COUNTRY	"US"
#set_var EASYRSA_REQ_PROVINCE	"California"
#set_var EASYRSA_REQ_CITY	"San Francisco"
#set_var EASYRSA_REQ_ORG	"Copyleft Certificate Co"
#set_var EASYRSA_REQ_EMAIL	"me@example.net"
#set_var EASYRSA_REQ_OU		"My Organizational Unit"


接下来,找到以下设置,删除#并编辑其值。这些指令负责证书的生存期(第一个用于CA证书的生存期,第二个用于正在签名的证书的生存期):



#set_var EASYRSA_CA_EXPIRE	3650         #-->  3650
#set_var EASYRSA_CERT_EXPIRE	3650         #-->  1825


进一步:



# ./easyrsa init-pki


运行下一个命令将要求输入CN。您可以保留默认值,但最好输入一个主机名标识名称(RootCA)。值“ nopass”表示您无需创建密码:



# ./easyrsa build-ca nopass


转到SubCA服务器,并按照类似的步骤进行较小的更改:



# mv ~/EasyRSA-3.0.4 ~/easyrsa/
# cd ~/easyrsa/
# cp vars.example vars
# vim vars


找到该块,删除#并替换我们的值:



#set_var EASYRSA_REQ_COUNTRY	"US"
#set_var EASYRSA_REQ_PROVINCE	"California"
#set_var EASYRSA_REQ_CITY	"San Francisco"
#set_var EASYRSA_REQ_ORG	"Copyleft Certificate Co"
#set_var EASYRSA_REQ_EMAIL	"me@example.net"
#set_var EASYRSA_REQ_OU		"My Organizational Unit"


接下来,我们找到以下设置,删除#并编辑其值:



#set_var EASYRSA_CA_EXPIRE	3650         #-->  1825
#set_var EASYRSA_CERT_EXPIRE	3650         #-->  365


进一步:



# ./easyrsa init-pki


运行下一个命令将要求输入CN。您可以保留默认值,但最好输入主机标识符名称(SubCA)。值“ subca”表示我们正在创建一个从属CA,并且需要创建一个证书签名请求:



# ./easyrsa build-ca subca nopass


接下来,我们找到文件〜/ easyrsa / pki / reqs / ca.req(这是非常重要的请求),并将其传输到RootCA服务器(可以使用两种方法:WinSCP和scp):



# scp ~/easyrsa/pki/reqs/ca.req user@ip_RootCA:/tmp


转到RootCA服务器并签署请求。在签署请求之前,我们必须将其导入工作目录。为下级CA的证书签名,我们使用“ ca”属性和证书名称(您可以将其称为ca,但为了避免混淆,我们将其称为我们对其进行签名的服务器的名称,当我们将其传输到服务器时,将对其重命名):



# cd ~/easyrsa/
# ./easyrsa import-req /tmp/ca.req SubCA
# ./easyrsa sign-req ca SubCA


将要求确认,您必须输入“是”。

我们返回SubCA签名的证书。



# scp ~/easyrsa/pki/issued/SubCA.crt user@ip_SubCA:/tmp


转到SubCA服务器并将证书移动到easyrsa工作目录:



# mv /tmp/SubCA.crt ~/easyrsa/pki/ca.crt


至此,我们已经有一个根CA和一个已签名的根辅助CA。

现在,让我们进入OpenVPN服务器。进行设置时,将重复前面的一些步骤。转到OpenVPN服务器。



# cd ~/easyrsa/
# ./easyrsa init-pki


现在,让我们开始创建用于签名的证书。我们将创建一个Diffie-Hellman密钥(dh.pem / dh2048.pem / dh1024.pem)以用于密钥交换,并创建一个HMAC签名(ta.key)以增强TLS完整性检查功能。



我们将在RootCA上为OpenVPN服务器签名证书,并在SubCA上为用户签名证书。让我们立即创建一个目录,在其中添加密钥,证书和客户端配置。



# mkdir -p ~/client-configs/files/
# mkdir ~/client-configs/keys/
# chmod 700 ~/client-configs/
# sudo mkdir /etc/openvpn/vpnsrv1/

# ./easyrsa gen-req vpnsrv1 nopass
# ./easyrsa gen-req dumasti nopass
# ./easyrsa gen-dh
# sudo openvpn --genkey --secret ta.key
# cp /home/dumasti/easyrsa/pki/private/dumasti.key ~/client-configs/keys/
# sudo cp /home/dumasti/easyrsa/pki/dh.pem /etc/openvpn/vpnsrv1/
# sudo cp /home/dumasti/easyrsa/ta.key /etc/openvpn/vpnsrv1/
# sudo cp /home/dumasti/easyrsa/ta.key ~/client-configs/keys/
# sudo cp /home/dumasti/easyrsa/pki/private/vpnsrv1.key /etc/openvpn/vpnsrv1/
# scp ~/easyrsa/pki/reqs/vpnsrv1.req user@ip_RootCA:/tmp
# scp ~/easyrsa/pki/reqs/dumasti.req user@ip_SubCA:/tmp


转到RootCA服务器并签署证书。要为服务器签名证书,请为客户端“ client”使用“ server”属性:



# cd ~/easyrsa/
# ./easyrsa import-req /tmp/vpnsrv1.req vpnsrv1
# ./easyrsa sign-req server vpnsrv1


将要求确认,您必须输入“是”。



# scp ~/easyrsa/pki/issued/vpnsrv1.crt user@ip_OpenVPN:/tmp
# scp ~/easyrsa/pki/ca.crt user@ip_OpenVPN:/tmp/RootCA.crt


转到SubCA服务器并签署证书:



# cd ~/easyrsa/
# ./easyrsa import-req /tmp/dumasti.req dumasti
# ./easyrsa sign-req client dumasti


将要求确认,您必须输入“是”。



# scp ~/easyrsa/pki/issued/dumasti.crt user@ip_OpenVPN:/tmp
# scp ~/easyrsa/pki/ca.crt user@ip_OpenVPN:/tmp/SubCA.crt


我们返回OpenVPN服务器,并将签名的证书转移到所需的目录:



# cd /tmp


为了使OpenVPN服务器能够接受客户端密钥,我们必须将客户端的公共密钥和下级/签名CA合并到一个文件中:



# cat dumasti.crt SubCA.crt > ~/client-configs/keys/dumasti.crt
# cp /tmp/RootCA.crt ~/client-configs/keys/ca.crt
# sudo mv /tmp/RootCA.crt /etc/openvpn/vpnsrv1/
# sudo mv /tmp/vpnsrv1.crt /etc/openvpn/vpnsrv1/


现在,我们在正确的位置提供了所有必需的认证。剩下的工作就是创建OpenVPN服务器和客户端的配置(在这个问题上,每个人都有自己的信念和看法,但是,例如,将有以下配置)。



您可以使用服务器和客户端配置模板并自己编辑:



# sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
# sudo gzip -d /etc/openvpn/server.conf.gz
# cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf ~/client-configs/base.conf


但是在下面,我将提供现成的配置文件的内容(符号;并在行中注释#):



# sudo cat /etc/openvpn/vpnsrv1.conf

port 1194
proto udp
dev tun
ca vpnsrv1/RootCA.crt
cert vpnsrv1/vpnsrv1.crt
key vpnsrv1/vpnsrv1.key
dh vpnsrv1/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
;push "route 192.168.10.0 255.255.255.0"
;push "route 192.168.20.0 255.255.255.0"
;client-config-dir ccd
;client-config-dir ccd
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
client-to-client
;duplicate-cn
keepalive 10 120
tls-auth vpnsrv1/ta.key 0
key-direction 0
cipher AES-256-CBC
auth SHA256
max-clients 100
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append /var/log/openvpn/openvpn.log
verb 3
;mute 20
explicit-exit-notify 1

# cat ~/client-configs/base.conf

client
dev tun
proto udp
remote your_server_ip 1194
;remote my-server-2 1194
;remote-random
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
remote-cert-tls server
;tls-auth ta.key 1
cipher AES-256-CBC
auth SHA256
key-direction 1
verb 3
;mute 20
# script-security 2
# up /etc/openvpn/update-resolv-conf
# down /etc/openvpn/update-resolv-conf


我们还需要配置防火墙和数据包转发。可以配置iptables,但这里我们将介绍ufw。



首先,让我们找出接口的名称:



# ip addr 


让我们打开以下端口(我在端口22上有ssh,在1194上有openvpn,如果还有其他端口,请采取相应措施):



# sudo ufw allow 1194
# sudo ufw allow 22


接下来,打开ufw配置文件并在过滤器链开始之前粘贴以下内容(用我自己的值替换我的值):



# sudo vim /etc/ufw/before.rules

# START OPENVPN RULES

# NAT table rules

*nat

:POSTROUTING ACCEPT [0:0]

# Allow traffic from OpenVPN client to eth0 (change to the interface you discovered!)

-A POSTROUTING -s 10.8.0.0/8 -o ens192 -j MASQUERADE

COMMIT

# END OPENVPN RULES


在那之前:



# Don't delete these required lines, otherwise there will be errors
*filter


默认情况下,您需要启用UFW转发数据包。找到所需的行,并将值“ DROP”更改为“ ACCEPT”:



# sudo vim /etc/default/ufw

DEFAULT_FORWARD_POLICY="ACCEPT"


配置报文转发 找到行#net.ipv4.ip_forward = 0或#net.ipv4.ip_forward = 1,删除#,如果值是0,则将其更改为1:



# sudo vim /etc/sysctl.conf

net.ipv4.ip_forward=1

# sudo sysctl -p
# sudo ufw enable


接下来,我们启动VPN:



# sudo systemctl start openvpn@vpnsrv1


检查启动:



# ip addr


应该有一个新的带有IP 10.8.0.1的tun0网络接口



# sudo systemctl status openvpn@vpnsrv1


如果您需要VPN在重新启动后自行启动,请将服务添加到自动运行:



# sudo systemctl enable openvpn@vpnsrv1


接下来,我们创建一个客户端配置。之前,我们将所有密钥和证书放在〜/ client-configs / keys /目录中。



让我们创建一个脚本,将配置,密钥和证书收集到一个文件user.ovpn中:



# cd ~/client-configs/
# vim configs-maker.sh

#!/bin/bash
# First argument: Client identifier
KEY_DIR=/home/dumasti/client-configs/keys
OUTPUT_DIR=/home/dumasti/client-configs/files
BASE_CONFIG=/home/dumasti/client-configs/base.conf
cat ${BASE_CONFIG} \
	<(echo -e '<ca>') \
	${KEY_DIR}/ca.crt \
	<(echo -e '</ca>\n<cert>') \
	${KEY_DIR}/${1}.crt \
	<(echo -e '</cert>\n<key>') \
	${KEY_DIR}/${1}.key \
	<(echo -e '</key>\n<tls-auth>') \
	${KEY_DIR}/ta.key \
	<(echo -e '</tls-auth>') \
	> ${OUTPUT_DIR}/${1}.ovpn


该脚本将使用您在启动期间提供的名称命名文件,并将在files目录中配置一个文件。



让我们将文件设为可执行文件:



# chmod +x configs-maker.sh


让我们运行它:



# sudo ./configs-maker.sh dumasti


现在,我们从/ home / dumasti / client-configs / files /目录将客户端配置传输到您的计算机,启动



VPN。



出于安全原因,托管CA的服务器应仅为签名证书而关闭和打开。



我们不会忽略证书的撤销。为了吊销证书,我们转到在其上签名证书的CA服务器,然后执行以下操作(例如,吊销在SubCA服务器上签名的用户证书(dumasti))。我们转到SubCA服务器:



# cd ~/easyrsa/
# ./easyrsa revoke dumasti


系统将要求您确认提款,输入“是”



# ./easyrsa gen-crl


crl.pem文件已生成。我们需要将其放置在OpenVPN服务器上,并在服务器配置中向文件添加指令和路径:



# scp ~/easyrsa/pki/crl.pem user@ip_OpenVPN:/tmp


转到OpenVPN服务器:



# sudo mv /tmp/crl.pem /etc/openvpn/vpnsrv1/
# sudo vim /etc/openvpn/vpnsrv1.conf


在编写密钥和证书的位置添加以下行:



crl-verify vpnsrv1/crl.pem


重新启动openvpn:



# sudo systemctl restart openvpn@vpnsrv1


现在,dumasti客户端将无法连接到VPN。



感谢您的关注!



All Articles