Qué es una VPN y para qué sirve

Una VPN (Virtual Private Network) es una red privada virtual que permite conectar dos o más redes privadas entre sí a través de una red pública como Internet. Las VPNs son muy útiles para conectar redes privadas a través de Internet de forma segura, ya que los datos que se transmiten a través de una VPN están cifrados y protegidos de forma que sólo los usuarios autorizados pueden acceder a ellos.

Acceso remoto con OpenVPN y certificados x509

En este apartado vamos a realizar un VPN de acceso remoto con OpenVPN y certificados x509. Para ello vamos a utilizar una máquina virtual en Proxmox con Debian 11.

Preparando el escenario

  1. Vamos a crear el escenario con 3 máquinas virtuales en Vagrant. Para ello, creamosun directorio y ejecutamos lo siguiente:
vagrant init

Se nos creará el fichero Vagrantfile. Añadimos lo siguiente:

Vagrant.configure("2") do |config|
    config.vm.provider :libvirt do |libvirt|
        libvirt.memory = 1024
    end
    config.vm.define :nodo1 do |nodo1|
      nodo1.vm.box = "debian/bullseye64"
      nodo1.vm.hostname = "VPNServer"
      nodo1.vm.synced_folder ".", "/vagrant", disabled: true
      nodo1.vm.network :private_network,
       :libvirt__network_name => "VPN1",
       :libvirt__dhcp_enabled => false,
       :ip => "192.168.10.10",
       :mode => "veryisolated"
      nodo1.vm.network :private_network,
       :libvirt__network_name => "VPN2",
       :libvirt__dhcp_enabled => false,
       :ip => "192.168.11.10",
       :libvirt__forward_mode => "veryisolated"
    end
    config.vm.define :nodo2 do |nodo2|
      nodo2.vm.synced_folder ".", "/vagrant", disabled: true
      nodo2.vm.box = "debian/bullseye64"
      nodo2.vm.hostname = "VPNClient1"
      nodo2.vm.network :private_network,
        :libvirt__network_name => "VPN1",
        :libvirt__dhcp_enabled => false,
        :ip => "192.168.10.11",
        :libvirt__forward_mode => "veryisolated"
    end
    config.vm.define :nodo3 do |nodo3|
        nodo3.vm.synced_folder ".", "/vagrant", disabled: true
        nodo3.vm.box = "debian/bullseye64"
        nodo3.vm.hostname = "VPNClient2"
        nodo3.vm.network :private_network,
          :libvirt__network_name => "VPN2",
          :libvirt__dhcp_enabled => false,
          :ip => "192.168.11.11",
          :libvirt__forward_mode => "veryisolated"
    end
end
  1. Instalamos openvpn en VPNServer:
apt install openvpn

Y activamos el bit de IP forwarding:

echo 1 > /proc/sys/net/ipv4/ip_forward
  1. La configuración que aparece en el fichero /usr/share/easy-rsa al fichero /etc/openvpn:
cp -r /usr/share/easy-rsa /etc/openvpn
  1. Nos dirigimos al directorio /etc/openvpn/easy-rsa/ y ejecutamos en la consola ./easyrsa init-pki para inicializar el PKI.

Creamos la clave privada y realizamos la firma de la misma

  1. Ya completado el paso anterior, vamos a generar el certificado de la Autoridad de Certificación (CA) y la clave con la que vamos a firmar los certificados del servidor y los clientes.
./easyrsa build-ca

#Frase de paso: admin
**NOTA**: La clave privada la encontraremos en `/etc/openvpn/easy-rsa/pki/private/ca.key` y el certificado en `/etc/openvpn/easy-rsa/pki/ca.crt`.

Vamos a generar parámetros Diffie-Helman para la autenticación de los extremos de la VPN. Pero, ¿por qué es necesario? El fin de los parámetros Diffie-Helman es evitar que un atacante pueda descifrar los mensajes cifrados en la VPN. Para ello, se generan dos números primos grandes y se calcula el módulo de su producto. Este módulo se envía a los extremos de la VPN, que lo utilizan para generar una clave de sesión.

./easyrsa gen-dh

Ahora le toca elturno al certificado y a la clave privada del servidor, teniendo en cuenta que deshabilitaremos la frase de paso. Para ello, ejecutamos:

./easyrsa build-server-full server nopass

Ya configurado el servidor, vamos a ponernos manos a la obra y le toca el turno a VPNClient1.

./easyrsa build-client-full client1 nopass

Realizados todos estos pasos, nos quedaría enviar los ficheros de configuración del servidor hacia el cliente. Por ello, (y para no caer en el desastre de no tener localizados los ficheros de configuración) vamos a crear un directorio en el que almacenarlos.

#Creamos el directorio
mkdir /etc/openvpn/VPNClient1

#Copiamos los ficheros
cp -rp /etc/openvpn/easy-rsa/pki{ca.crt,issued/VPNClient1.crt,private/VPNClient1.key}

#Cambiamos los propietarios
chown -R vagrant: /etc/openvpn/VPNClient1/

#Enviamos por scp los ficheros al cliente
scp -r /home/vagrant/VPNClient1 vagrant@192.168.10.11:

Nos dirigimos al servidor y creamos el fichero de configuración con el que configuraremos (valga la redundancia), el tunel VPN.

nano /etc/openvpn/server/server.conf
#Configuracion del servidor

#Puerto de escucha, protocolo y dispositivo
port 1194
proto udp
dev tun

#Autenticacion
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
dh /etc/openvpn/easy-rsa/pki/dh.pem

#Topologia de red
topology subnet

server 10.99.99.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt

#Ruta hacia el cliente
push "route 192.168.11.0 255.255.255.0"


keepalive 10 120
cipher AES-256-CBC
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
verb 3
explicit-exit-notify 1

Tras toda esta configuración, vamos a habilitar el servicio de OpenVPN y a reiniciar el servicio.

systemctl enable --now openvpn-server@server

Configuración del cliente

Ahora en nuestro VPNClient1 vamos a configurar el cliente, y empezaríamos instalando el paquete de OpenVPN y traspasamos los ficheros de configuración del servidor.

sudo apt install openvpn
---
mv VPNClient1 /etc/openvpn/client/

Será necesario que cambiemos el propietario de los ficheros de configuración y, como hicimos en VPNServer, crearemos el fichero de configuración del cliente.

#Cambiamos el propietario
chown root: /etc//openvpn/client/*
nano /etc/openvpn/server/client1.conf
#Configuracion del cliente

#Puerto de escucha, protocolo y dispositivo
client
dev tun
proto udp

#Autenticacion
remote 192.168.10.10 1194
resolv-retry infinite
nobind
persist-key
persist-tun

#Autenticacion
ca /etc/openvpn/client/ca.crt
cert /etc/openvpn/client/VPNClient1.crt
key /etc/openvpn/client/VPNClient1.key

#Topologia de red
remote-cert-tls server
cipher AES-256-CBC
verb 3

Habilitamos el servicio de OpenVPN y lo reiniciamos.

systemctl enable --now openvpn-client@client1

Como podemos ver en las siguientes imágenes, el tunel está creado y funcionando.

Por último, vamos a cambiar la ruta por defecto de nuestro cliente interno para que pueda usar el servidor como puerta de enlace.

ip route del default
ip route add default via 192.168.11.10

En las imágenes siguientes podemos ver que el cliente tiene acceso a Internet, y el servidor tiene acceso a la red interna del cliente.

Conclusiones

En este ejercicio hemos configurado un servidor OpenVPN, y hemos creado un cliente que se conecta a él. El cliente tiene acceso a Internet, y el servidor tiene acceso a la red interna del cliente.

Es importante destacar que, en este ejercicio, hemos utilizado certificados digitales para la autenticación de los extremos. Esto es debido a que, en la práctica, es la forma más segura de autenticar los extremos de la VPN.

También es importante destacar que, en este ejercicio, hemos utilizado una topología de red en subredes, en la que cada extremo de la VPN tiene una dirección IP propia. Esto es debido a que es la forma más segura de configurar la VPN.