SysAdmin Nazareno

[SAD] - Práctica: VPN con OpenVPN y certificados x509

Para esta tarea puedes usar el fichero heat del primer ejercicio. En esta tarea vas a realizar el segundo ejercicio del tema:

Configura una conexión VPN de acceso remoto entre dos equipos:

  • Uno de los dos equipos (el que actuará como servidor) estará conectado a dos redes

  • Para la autenticación de los extremos se usarán obligatoriamente certificados digitales, que se generarán utilizando openssl y se almacenarán en el directorio /etc/openvpn, junto con los parámetros Diffie-Helman y el certificado de la propia Autoridad de Certificación.

  • Se utilizarán direcciones de la red 10.99.99.0/24 para las direcciones virtuales de la VPN. La dirección 10.99.99.1 se asignará al servidor VPN.

  • Los ficheros de configuración del servidor y del cliente se crearán en el directorio /etc/openvpn de cada máquina, y se llamarán servidor.conf y cliente.conf respectivamente. La configuración establecida debe cumplir los siguientes aspectos:

    • El demonio openvpn se manejará con systemctl.
    • Se debe configurar para que la comunicación esté comprimida.
    • La asignación de direcciones IP será dinámica.
    • Existirá un fichero de log en el equipo.
    • Se mandarán a los clientes las rutas necesarias.
  • Tras el establecimiento de la VPN, la máquina cliente debe ser capaz de acceder a una máquina que esté en la otra red a la que está conectado el servidor.

  • Instala el complemento de VPN en networkmanager y configura el cliente de forma gráfica desde este complemento.


Prepararemos el entorno instalando openvpn/easy-rsa, en nuestras maquinas previamentes ya tendremos instalado openvpn y git(si has usado el Vagrantfile de esta practica ya los tendras incorporados).

root@servidor:/home/vagrant# git clone https://github.com/OpenVPN/easy-rsa

Copiaremos el directorio /easyrsa3/vars.example en /easyrsa3/vars y modificaremos lo siguiente:

root@servidor:/home/vagrant# cp easy-rsa/easyrsa3/vars.example easy-rsa/easyrsa3/vars
root@servidor:/home/vagrant# nano easy-rsa/easyrsa3/vars
set_var EASYRSA_REQ_COUNTRY     "ES"
set_var EASYRSA_REQ_PROVINCE    "Sevilla"
set_var EASYRSA_REQ_CITY        "Dos Hermanas" 
set_var EASYRSA_REQ_ORG         "iesgn.org"
set_var EASYRSA_REQ_EMAIL       "frandh1997@gmail.com"
set_var EASYRSA_REQ_OU          "iesgn.org"

Utilizaremos el script de easyrsa para generar el directorio /pki/ que será donde se almacenarán las claves y certificados.

root@servidor:/home/vagrant/easy-rsa/easyrsa3# chmod 700 ./easyrsa
root@servidor:/home/vagrant/easy-rsa/easyrsa3# ./easyrsa init-pki

Note: using Easy-RSA configuration from: /home/vagrant/easy-rsa/easyrsa3/vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /home/vagrant/easy-rsa/easyrsa3/pki

Comenzaremos creando las Credenciales CA utilizando el parámetro build-ca.

root@servidor:/home/vagrant/easy-rsa/easyrsa3# ./easyrsa build-ca

Note: using Easy-RSA configuration from: /home/vagrant/easy-rsa/easyrsa3/vars
Using SSL: openssl OpenSSL 1.1.1d  10 Sep 2019

Enter New CA Key Passphrase: #fran
Re-Enter New CA Key Passphrase: #fran
Generating RSA private key, 2048 bit long modulus (2 primes)
.........+++++
...........+++++
e is 65537 (0x010001)
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]:iesgn.org

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/home/vagrant/easy-rsa/easyrsa3/pki/ca.crt

Credenciales Servidor, utilizaremos el script build-server-full mas el nombre del fichero, nos pediran la frase de paso que pusimos anteriormente.

root@servidor:/home/vagrant/easy-rsa/easyrsa3# ./easyrsa build-server-full servidor

Note: using Easy-RSA configuration from: /home/vagrant/easy-rsa/easyrsa3/vars
Using SSL: openssl OpenSSL 1.1.1d  10 Sep 2019
Generating a RSA private key
...............+++++
.......................................................................+++++
writing new private key to '/home/vagrant/easy-rsa/easyrsa3/pki/easy-rsa-3582.ojRSnD/tmp.Uh9gOQ'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
Using configuration from /home/vagrant/easy-rsa/easyrsa3/pki/easy-rsa-3582.ojRSnD/tmp.6ZCHcr
Enter pass phrase for /home/vagrant/easy-rsa/easyrsa3/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'servidor'
Certificate is to be certified until Jun 27 13:28:19 2023 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Clave Diffie Hellman, es un protocolo de establecimiento de claves entre partes que no han tenido contacto previo, utilizando un canal inseguro y de manera anónima (no autenticada). Puede demorarse un poco su generación.

root@servidor:/home/vagrant/easy-rsa/easyrsa3# ./easyrsa gen-dh

Note: using Easy-RSA configuration from: /home/vagrant/easy-rsa/easyrsa3/vars
Using SSL: openssl OpenSSL 1.1.1d  10 Sep 2019
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 /home/vagrant/easy-rsa/easyrsa3/pki/dh.pem

Después de obtener todas las credenciales necesarias configuraremos el fichero de OpenVPN, antes de ello organizaremos un poco nuestros archivos, crearemos y moveremos los archivos a una carpeta pki en openvpn.

root@servidor:/etc/openvpn/pki# tree
.
├── ca
│   ├── ca.crt
│   └── ca.key
├── dh.pem
└── server
    ├── servidor.crt
    └── servidor.key

2 directories, 5 files

Ahora es paso al fichero de configuración del servidor:

root@servidor:/etc/openvpn# nano servidor.conf
#Dispositivo de túnel
dev tun

#Protocolo de red
proto tcp

#Direcciones IP virtuales
server 10.99.99.0 255.255.255.0

#subred local
push "route 192.168.100.0 255.255.255.0"

#Rol de servidor
tls-server

#Parámetros Diffie-Hellman
dh /etc/openvpn/pki/dh.pem

#Certificado de la CA
ca /etc/openvpn/pki/ca/ca.crt

#Certificado local
cert /etc/openvpn/pki/server/servidor.crt

#Clave privada local
key /etc/openvpn/pki/server/servidor.key

#Activar la compresión LZO
comp-lzo

#Detectar caídas de la conexión
keepalive 10 60

#Nivel de información
verb 3

# Contraseña del certificado del servidor
askpass passwd.txt

Crearemos un archivo para almacenas las contraseñas de askpass.

root@servidor:/etc/openvpn# nano passwd.txt
fran

Ahora toca probar el resultado reiniciaremos el servicio de openvpn y comprobaremos que este escuchando por el puerto 1194.

Nota: En algunos casos como el que me ocurrio a mi los cambios no se implementaron hasta que no reinicie la máquina reboot.

root@servidor:/etc/openvpn# service openvpn restart
root@servidor:/home/vagrant# lsof -i -P -n | grep openvpn
openvpn   659     root    6u  IPv4  14154      0t0  TCP *:1194 (LISTEN)

root@servidor:/etc/openvpn# service openvpn status
● openvpn.service - OpenVPN service
   Loaded: loaded (/lib/systemd/system/openvpn.service; enabled; vendor preset: enabled)
   Active: active (exited) since Wed 2021-03-24 14:02:35 UTC; 18s ago
  Process: 3892 ExecStart=/bin/true (code=exited, status=0/SUCCESS)
 Main PID: 3892 (code=exited, status=0/SUCCESS)

Mar 24 14:02:35 servidor systemd[1]: Starting OpenVPN service...
Mar 24 14:02:35 servidor systemd[1]: Started OpenVPN service.
#nueva interfaz generada
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
    link/none 
    inet 10.99.99.1 peer 10.99.99.2/32 scope global tun0
       valid_lft forever preferred_lft forever

Configuración del cliente

Ahora daremos paso a la configuración del cliente, necesitaremos crear las credenciales necesarias para su conexión, el primer paso sera pasar la credenciales que generamos en el servidor, serán necesarias:

  • Credenciales del Cliente

    • certificado .crt
    • clave privada .key
  • Certificado CA.crt

Crearemos una carpeta llamada pki y donde guardaremos los archivos necesarios para tenerlos organizados.

Crearemos una clave privada RSA para el cliente.

root@cliente1:/home/vagrant# openssl genrsa -out cliente1.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.......++++
......................................................................................................................................................++++
e is 65537 (0x010001)

Generaremos un fichero CSR utilizando la key creada.

root@cliente1:/home/vagrant# nano cliente1.conf
[ req ]
default_bits       = 4096
default_keyfile    = cliente1.key
distinguished_name = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = SP
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Sevilla
localityName                = Locality Name (eg, city)
localityName_default        = Dos Hermanas
organizationName            = Organization Name (eg, company)
organizationName_default    = iesg.org 
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = iesgn.org 

[ req_ext ]
subjectAltName = @alt_names

[alt_names]
DNS.1   = servidor

root@cliente1:/home/vagrant# openssl req -new -nodes -sha256 -config cliente1.conf -out cliente1.csr
Generating a RSA private key
......++++
...................................................................................................................................................++++
writing new private key to 'cliente1.key'
-----
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.
-----
Country Name (2 letter code) [SP]:ES
State or Province Name (full name) [Sevilla]:
Locality Name (eg, city) [Dos Hermanas]:
Organization Name (eg, company) [iesg.org]:
Common Name (e.g. server FQDN or YOUR name) [iesgn.org]:

Mandaremos el fichero csr al servidor y lo firmaremos.

#en el servidor
root@servidor:/etc/openvpn/pki# openssl x509 -req -in /home/vagrant/cliente1.csr -CA ca/ca.crt -CAkey ca/ca.key -CAcreateserial -out cliente1-firmado.crt
Signature ok
subject=C = ES, ST = Sevilla, L = Dos Hermanas, O = iesg.org, CN = iesgn.org
Getting CA Private Key
Enter pass phrase for ca/ca.key:

Una vez generado se lo devolveremos al cliente para que realize su configuración.

Crearemos el archivo de configuración para el cliente.

root@cliente1:/etc/openvpn# nano cliente.conf
#Dispositivo de túnel
dev tun

#IP del servidor
remote 192.168.2.75

#Direcciones IP virtuales
ifconfig 10.99.99.0 255.255.255.0
pull

#Protocolo
proto tcp-client # Protocolo tcp

#Rol de cliente
tls-client

#Certificado de la CA
ca /etc/openvpn/pki/ca.crt

#Certificado cliente
cert /etc/openvpn/pki/cliente1-firmado.crt

#Clave privada cliente
key /etc/openvpn/pki/cliente1.key

#Activar la compresión LZO
comp-lzo

#Detectar caídas de la conexión
keepalive 10 60

#Nivel de la información
verb 3

# Contraseña del certificado del cliente
askpass passwd.txt

Crearemos un archivo para almacenas las contraseñas de askpass.

root@cliente1:/etc/openvpn# nano passwd.txt
fran

Comprobaremos que funcione ejecutandolo directamente con el comando.

root@cliente1:/etc/openvpn# openvpn --config cliente.conf &
[1] 1817
root@cliente1:/etc/openvpn# Fri Mar 26 17:59:29 2021 WARNING: file 'passwd.txt' is group or others accessible
Fri Mar 26 17:59:29 2021 OpenVPN 2.4.7 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Feb 20 2019
Fri Mar 26 17:59:29 2021 library versions: OpenSSL 1.1.1d  10 Sep 2019, LZO 2.10
Fri Mar 26 17:59:29 2021 WARNING: using --pull/--client and --ifconfig together is probably not what you want
Fri Mar 26 17:59:29 2021 WARNING: No server certificate verification method has been enabled.  See http://openvpn.net/howto.html#mitm for more info.
Fri Mar 26 17:59:29 2021 TCP/UDP: Preserving recently used remote address: [AF_INET]192.168.2.75:1194
Fri Mar 26 17:59:29 2021 Socket Buffers: R=[131072->131072] S=[16384->16384]
Fri Mar 26 17:59:29 2021 Attempting to establish TCP connection with [AF_INET]192.168.2.75:1194 [nonblock]
Fri Mar 26 17:59:30 2021 TCP connection established with [AF_INET]192.168.2.75:1194
Fri Mar 26 17:59:30 2021 TCP_CLIENT link local: (not bound)
Fri Mar 26 17:59:30 2021 TCP_CLIENT link remote: [AF_INET]192.168.2.75:1194
Fri Mar 26 17:59:30 2021 TLS: Initial packet from [AF_INET]192.168.2.75:1194, sid=30ce3d0d 93d0e4f6
Fri Mar 26 17:59:30 2021 VERIFY OK: depth=1, CN=iesgn.org
Fri Mar 26 17:59:30 2021 VERIFY OK: depth=0, CN=servidor
Fri Mar 26 17:59:30 2021 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA
Fri Mar 26 17:59:30 2021 [servidor] Peer Connection Initiated with [AF_INET]192.168.2.75:1194
Fri Mar 26 17:59:31 2021 SENT CONTROL [servidor]: 'PUSH_REQUEST' (status=1)
Fri Mar 26 17:59:31 2021 PUSH: Received control message: 'PUSH_REPLY,route 192.168.100.0 255.255.255.0,route 10.99.99.1,topology net30,ping 10,ping-restart 60,ifconfig 10.99.99.6 10.99.99.5,peer-id 0,cipher AES-256-GCM'
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: timers and/or timeouts modified
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: --ifconfig/up options modified
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: route options modified
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: peer-id set
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: adjusting link_mtu to 1627
Fri Mar 26 17:59:31 2021 OPTIONS IMPORT: data channel crypto options modified
Fri Mar 26 17:59:31 2021 Data Channel: using negotiated cipher 'AES-256-GCM'
Fri Mar 26 17:59:31 2021 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Fri Mar 26 17:59:31 2021 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Fri Mar 26 17:59:31 2021 ROUTE_GATEWAY 192.168.2.1/255.255.255.0 IFACE=eth1 HWADDR=08:00:27:73:db:a3
Fri Mar 26 17:59:31 2021 TUN/TAP device tun0 opened
Fri Mar 26 17:59:31 2021 TUN/TAP TX queue length set to 100
Fri Mar 26 17:59:31 2021 /sbin/ip link set dev tun0 up mtu 1500
Fri Mar 26 17:59:31 2021 /sbin/ip addr add dev tun0 local 10.99.99.6 peer 10.99.99.5
Fri Mar 26 17:59:31 2021 /sbin/ip route add 192.168.100.0/24 via 10.99.99.5
Fri Mar 26 17:59:31 2021 /sbin/ip route add 10.99.99.1/32 via 10.99.99.5
Fri Mar 26 17:59:31 2021 WARNING: this configuration may cache passwords in memory -- use the auth-nocache option to prevent this
Fri Mar 26 17:59:31 2021 Initialization Sequence Completed

Y comprobaremos la conectividad con la máquina de la red local.

root@cliente1:/etc/openvpn# ping -c 1 192.168.100.20
PING 192.168.100.20 (192.168.100.20) 56(84) bytes of data.
64 bytes from 192.168.100.20: icmp_seq=1 ttl=63 time=3.06 ms

--- 192.168.100.20 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 3.058/3.058/3.058/0.000 ms

Si queremos que se inicialize cada vez que arranquemos el sistema añadiremos la siguiente linea en el fichero de /etc/default/openvpn.

AUTOSTART="cliente"

Tarea 2: VPN sitio a sitio con OpenVPN y certificados x509

Esta tarea la puedes hacer con un compañero.

Configura una conexión VPN sitio a sitio entre dos equipos del cloud:

Cada equipo estará conectado a dos redes, una de ellas en común

Para la autenticación de los extremos se usarán obligatoriamente certificados digitales, que se generarán utilizando openssl y se almacenarán en el directorio /etc/openvpn, junto con con los parámetros Diffie-Helman y el certificado de la propia Autoridad de Certificación.

Se utilizarán direcciones de la red 10.99.99.0/24 para las direcciones virtuales de la VPN.

Tras el establecimiento de la VPN, una máquina de cada red detrás de cada servidor VPN debe ser capaz de acceder a una máquina del otro extremo.

Esta vez la configuración sera muy similar donde habra una conexión entre cliente y servidor, pero esta vez el cliente que en este caso es el servidor1 hará a su vez de servidor del cliente1.

Realizaremos los pasos anteriores para la configuración del servidor2.

root@Servidor2:/etc/openvpn# nano servidor2.conf
# Dispositivo de túnel
dev tun
# Encaminamiento
ifconfig 10.99.99.1 10.99.99.2
route 192.168.100.0 255.255.255.0
# Rol de cliente
tls-server

# Certificado Diffie-Hellman
dh /etc/openvpn/server/dh.pem
# Certificado de la CA
ca /etc/openvpn/server/ca.crt
# Certificado local
cert /etc/openvpn/server/servidor.crt
# Clave privada local
key /etc/openvpn/server/servidor.key

# Activar la compresión LZO
comp-lzo

# Detectar caídas de la conexión
keepalive 10 60

# Nivel de información
verb 3

askpass passwd.txt

Realizaremos los pasos anteriores para la configuración del cliente1 en el servidor1 del nuevo escenario añadiendo las modificaciónes pertinentes.

root@Servidor1:/etc/openvpn# nano cliente1.conf
# Dispositivo de túnel
dev tun
# Encaminamiento
ifconfig 10.99.99.2 10.99.99.1
# Direcciones IP virtuales
remote 192.168.2.243
# Subred remota
route 192.168.200.0 255.255.255.0
# Rol de cliente
tls-client

# Certificado de la CA
ca /etc/openvpn/client/ca.crt

#Certificado local
cert /etc/openvpn/client/cliente1-firmado.crt

#Clave privada local
key /etc/openvpn/client/cliente1.key

#Activar la compresión LZO
comp-lzo

#Detectar caídas de la conexión
keepalive 10 60

#Nivel de información
verb 3

askpass passwd.txt

Ping del cliente1 al cliente2.

vagrant@Cliente1:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:a9:dd:93 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
       valid_lft 86012sec preferred_lft 86012sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:61:88:c0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.200.40/24 brd 192.168.200.255 scope global eth1
       valid_lft forever preferred_lft forever

vagrant@Cliente1:~$ ping -c 3 192.168.100.50
PING 192.168.100.50 (192.168.100.50) 56(84) bytes of data.
64 bytes from 192.168.100.50: icmp_seq=1 ttl=64 time=0.853 ms
64 bytes from 192.168.100.50: icmp_seq=2 ttl=64 time=0.726 ms
64 bytes from 192.168.100.50: icmp_seq=3 ttl=64 time=0.733 ms

--- 192.168.100.50 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 51ms
rtt min/avg/max/mdev = 0.726/0.770/0.853/0.066 ms

Ping del cliente2 al cliente1.

vagrant@Cliente2:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:a9:dd:93 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic eth0
       valid_lft 86193sec preferred_lft 86193sec
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:3f:5d:26 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.50/24 brd 192.168.100.255 scope global eth1
       valid_lft forever preferred_lft forever

vagrant@Cliente2:~$ ping 192.168.200.40
PING 192.168.200.40 (192.168.200.40) 56(84) bytes of data.
64 bytes from 192.168.200.40: icmp_seq=1 ttl=64 time=1.46 ms
64 bytes from 192.168.200.40: icmp_seq=2 ttl=64 time=0.626 ms
64 bytes from 192.168.200.40: icmp_seq=3 ttl=64 time=0.712 ms
^C
--- 192.168.200.40 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 5ms
rtt min/avg/max/mdev = 0.626/0.931/1.456/0.373 ms

Fran Madueño

Escrito por Fran Madueño Estudiante de administración de sistemas operativos
(Dos Hermanas, Sevilla).