OpenVPN con jerarquía de CA de dos niveles

Recientemente me encontré con la tarea de crear una jerarquía de dos niveles de autoridad certificadora para OpenVPN en debian. Muchas veces tuve la oportunidad de plantear OpenVPN con una CA y entendí perfectamente cómo debería ser en teoría con dos CA, pero en la práctica me enfrenté al hecho de que no entendía qué y dónde firmar. Google no me dio respuestas que serían adecuadas para Linux (o no las busqué en Google) y comencé a resolverlo. A continuación, proporciono un manual que recopilé en el proceso de creación y configuración.



Quiero señalar de inmediato que aquí pongo más énfasis en configurar la CA que en OpenVPN.



Antes de comenzar, le diré a alguien que pueda usarlo con mi ejemplo.



Tenía la tarea de crear un sistema para una gran empresa de tal manera que solo una persona firmara los certificados del servidor OpenVPN, hay muchos servidores VPN, se instalaron varios servidores VPN para cada departamento. Hay incluso más empleados (clientes) y certificados de control (emisión / revocación) cada vez que un empleado llega / deja una carga muy pesada (sin mencionar a los empleados temporales). Los empleados de cada departamento son supervisados ​​por el jefe del departamento, quien emite o revoca certificados para empleados nuevos / antiguos, respectivamente.



Para lo que se necesitan certificados y claves digitales, mucho se ha dicho y no repetiré a otros autores, pero en definitiva:



  • para verificar la confiabilidad (se produce un "apretón de manos doble"), el cliente y el servidor se aseguran de quiénes son, si pueden confiar entre sí y establecer una conexión;
  • cifrado / descifrado;
  • excepciones "Hombre en el medio (MITM)" para asegurarse de que alguien no esté interceptando mensajes / tráfico;
  • para crear contraseñas encriptadas, lo que aumenta la seguridad y dificulta que los atacantes accedan al host.


El principio de funcionamiento de la jerarquía de CA multinivel es que la CA de nivel superior (RootCA) firma su certificado por sí misma durante un período de tiempo suficientemente largo (pero esto es un asunto puramente individual), cada uno de los siguientes en la jerarquía de CA o servicio firma sus certificados con una CA superior (lo habitual burocracia) con la condición de que el certificado de nivel inferior debe tener un período de validez no superior a la mitad del período de validez del certificado de nivel superior.







Al crear una CA, se crean dos archivos: ca.crt - la clave pública y ca.key - la clave privada.

La clave privada debe estar protegida y no debe compartirse con terceros.



Cuando necesitamos crear una CA subordinada / firmante, creamos una clave privada en ella y una solicitud de firma de RootCA.



¿Cómo sabrán las computadoras y los usuarios de todo el mundo que pueden confiar en un servicio o sitio? Es simple (bueno, en teoría), la clave pública de CA (RootCA) se coloca en las computadoras de los usuarios y estas computadoras confían en todos los certificados emitidos por esta CA. En la práctica, esto es ciertamente más difícil y no barato. Pero dentro de su propia empresa es bastante fácil de hacer.



Para la implementación, necesitamos tres servidores. En este tutorial usaremos debian 9. Nombraremos los servidores según su aplicación: OpenVPN, SubCA, RootCA.



Todas las acciones se realizan bajo el usuario no root.



Para hacer esto, su usuario debe estar en el grupo sudo.



Si sudo no está instalado en el servidor, inicie sesión como root:



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


Instale las utilidades necesarias en todos los servidores (las utilidades pueden diferir dependiendo de las creencias y creencias, wget, ufw, vim son obligatorias, ya que aquí he dado comandos con estas utilidades):



# 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


Instale openvpn en el servidor OpenVPN:



# sudo apt-get install openvpn -y


Vaya al servidor RootCA. Aquí necesitamos crear un archivo del cual easyrsa tomará los valores de las variables:



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


Busque el bloque, elimine # y sustituya nuestros valores. Para no ingresar nuestros datos al firmar certificados, los escribiremos aquí:



#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"


A continuación, busque la siguiente configuración, elimine # y edite sus valores. Estas directivas son responsables de la vida útil de los certificados (la primera es durante la vida útil del certificado de CA, la segunda es durante la vida útil del certificado que se está firmando):



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


Más lejos:



# ./easyrsa init-pki


Al ejecutar el siguiente comando, se solicitará CN. Puede dejar el predeterminado, pero es mejor ingresar un nombre de identificación de host (RootCA). El valor "nopass" significa que no es necesario crear una contraseña:



# ./easyrsa build-ca nopass


Vaya al servidor SubCA y siga los mismos pasos con cambios menores:



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


Encuentra el bloque, borra # y sustituye nuestros valores:



#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"


A continuación, encontramos las siguientes configuraciones, eliminamos # y editamos sus valores:



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


Más lejos:



# ./easyrsa init-pki


Ejecutar el siguiente comando solicitará CN. Puede dejar el valor predeterminado, pero es mejor ingresar un nombre de identificador de host (SubCA). El valor "subca" indica que estamos creando una CA subordinada y necesitamos crear una solicitud de firma de certificado:



# ./easyrsa build-ca subca nopass


A continuación, buscamos el archivo ~ / easyrsa / pki / reqs / ca.req (esta es la misma solicitud) y lo transferimos al servidor RootCA (puede usar dos métodos: WinSCP y scp):



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


Vaya al servidor RootCA y firme la solicitud. Antes de firmar la solicitud, debemos importarla al directorio de trabajo. para firmar el certificado de la CA subordinada usamos el atributo "ca" y el nombre del certificado (puedes llamarlo ca, pero para no confundirte lo llamaremos el nombre del servidor al que lo estamos firmando, y cuando lo transfiramos al servidor, le cambiaremos el nombre):



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


Se solicitará confirmación, debe ingresar "sí".

Devolvemos el certificado firmado SubCA.



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


Vaya al servidor SubCA y mueva el certificado al directorio de trabajo de easyrsa:



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


En este punto, ya tenemos una CA raíz y una CA secundaria raíz firmada.

Ahora entremos en el servidor OpenVPN. Al configurarlo, se repiten algunos de los pasos anteriores. Vaya al servidor OpenVPN.



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


Ahora comencemos a crear certificados para firmar. Crearemos una clave Diffie-Hellman (dh.pem / dh2048.pem / dh1024.pem) para usar en el intercambio de claves, y crearemos una firma HMAC (ta.key) para mejorar la función de verificación de integridad TLS.



Firmaremos certificados para el servidor OpenVPN en RootCA y firmaremos certificados para usuarios en SubCA. Inmediatamente crea un directorio donde almacenaremos claves, certificados y configuraciones de cliente.



# 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


Vaya al servidor RootCA y firme el certificado. Para firmar el certificado para el servidor, use el atributo "servidor", para el cliente "cliente":



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


Se solicitará confirmación, debe ingresar "sí".



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


Vaya al servidor SubCA y firme el certificado:



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


Se solicitará confirmación, debe ingresar "sí".



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


Regresamos al servidor OpenVPN y transferimos los certificados firmados a los directorios requeridos:



# cd /tmp


Para que el servidor OpenVPN acepte claves de cliente, debemos combinar las claves públicas del cliente y la CA subordinada / firmante en un archivo:



# 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/


Ahora tenemos todas las certificaciones necesarias en los lugares correctos. Queda por crear la configuración del servidor y cliente OpenVPN (cada uno puede tener sus propias creencias y puntos de vista al respecto, pero por ejemplo habrá la siguiente configuración).



Puede utilizar la plantilla de configuración de servidor y cliente y editar usted mismo:



# 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


Pero a continuación, daré el contenido de los archivos de configuración listos para usar (símbolos; y # comentar la línea):



# 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


También necesitamos configurar el firewall y el reenvío de paquetes. Es posible configurar iptables, pero aquí veremos ufw.



Primero, averigüemos el nombre de nuestra interfaz:



# ip addr 


Abramos los siguientes puertos (tengo ssh en el puerto 22 y openvpn en 1194, si tiene otros, actúe en consecuencia):



# sudo ufw allow 1194
# sudo ufw allow 22


A continuación, abra el archivo de configuración de ufw y pegue lo siguiente allí antes del inicio de la cadena de filtros (reemplace mis valores por los suyos):



# 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


Antes de que:



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


Debe habilitar el reenvío UFW de paquetes de forma predeterminada. Busque la línea requerida y cambie el valor "DROP" a "ACCEPT":



# sudo vim /etc/default/ufw

DEFAULT_FORWARD_POLICY="ACCEPT"


Configuración del reenvío de paquetes. Busque la línea # net.ipv4.ip_forward = 0 o # net.ipv4.ip_forward = 1, elimine #, si el valor es 0, luego cámbielo a 1:



# sudo vim /etc/sysctl.conf

net.ipv4.ip_forward=1

# sudo sysctl -p
# sudo ufw enable


A continuación, lanzamos nuestra VPN:



# sudo systemctl start openvpn@vpnsrv1


Comprobando el lanzamiento:



# ip addr


Debería haber una nueva interfaz de red tun0 con ip 10.8.0.1



# sudo systemctl status openvpn@vpnsrv1


Si necesita que la VPN se inicie por sí sola después de reiniciar, agregue el servicio a la ejecución automática:



# sudo systemctl enable openvpn@vpnsrv1


A continuación, creamos una configuración de cliente. Anteriormente, colocamos todas las claves y certificados en el directorio ~ / client-configs / keys /.



Creemos un script que recopilará la configuración, las claves y los certificados en un archivo 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


Este script tomará archivos con el nombre que le dé durante el inicio y configurará un archivo en el directorio de archivos.



Hagamos que el archivo sea ejecutable:



# chmod +x configs-maker.sh


Vamos a ejecutarlo:



# sudo ./configs-maker.sh dumasti


Ahora transferimos la configuración del cliente a su computadora desde el directorio / home / dumasti / client-configs / files /



Inicie VPN.



Por razones de seguridad, los servidores que alojan la CA deben apagarse y encenderse solo para firmar certificados.



No ignoraremos la revocación de certificados. Para revocar el certificado, nos dirigimos al servidor CA en el que se firmó el certificado y hacemos lo siguiente (Por ejemplo, revocaremos el certificado de usuario (dumasti) que firmamos en el servidor SubCA). Vamos al servidor SubCA:



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


Se le pedirá que confirme la revocación, ingrese "sí"



# ./easyrsa gen-crl


Se ha generado el archivo crl.pem. Necesitamos ponerlo en el servidor OpenVPN y agregar la directiva y la ruta al archivo en la configuración del servidor:



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


Vaya al servidor OpenVPN:



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


Agregue la siguiente línea donde se escriben las claves y los certificados:



crl-verify vpnsrv1/crl.pem


Reinicie openvpn:



# sudo systemctl restart openvpn@vpnsrv1


Ahora el cliente dumasti no podrá conectarse a VPN.



¡Gracias por su atención!



All Articles