Recientemente tuve una amistad que me pidió ayuda. Él quiere conectar la PC de su casa a un servidor VPN (1), y que luego ese servidor se conecte a otro servidor VPN (2); siendo su objetivo final salir a internet con el IP público del servidor VPN 2.
La solución a su problema tiene nombre y es MULTI-HOP VPN. Pero que es MULTI-HOP VPN?
Como su nombre lo indica es una VPN de múltiples saltos que agrega una capa adicional de cifrado y un servidor adicional a su conexión VPN normal al «encadenar» o «conectar en cascada» dos o más servidores VPN juntos. El propósito es aumentar la seguridad y la privacidad proporcionadas por una conexión VPN estándar de un solo servidor.
Las VPN de múltiples saltos a veces se denominan VPN dobles, aunque se puede incluir cualquier cantidad de servidores VPN en la cadena. Esta guía le explicará todo lo que necesita saber sobre las VPN multisalto y como implementar una.
Así es como funciona una VPN típica de doble salto:
- Sus datos se cifran en su dispositivo una vez, luego encriptada en su dispositivo por segunda vez (dos capas de encriptación).
- Los datos cifrados se envían al primer servidor VPN. Se elimina la segunda capa de cifrado.
- Los datos cifrados se envían al segundo servidor VPN.
- Se elimina la primera capa de cifrado y los datos se descifran por completo.
- Los datos descifrados se envían a su destino final.
Tenga en cuenta que cada capa de cifrado se elimina en el orden inverso al que se aplicó: el último en entrar, el primero en salir. La primera VPN en cifrar datos en el dispositivo será el último servidor de la cadena, y el último en cifrar datos será el primero de la cadena. Este túnel dentro de un túnel resuelve algunos de los problemas que pueden afectar a las conexiones VPN normales.
Este embrollo de palabras tal vez sea más fácil de entender en el siguiente esquema:
Pues bien, planteado el problema toca aplicar la solución.
- La solución vpn a utilizar es el OpenVPN, pero puede utilizarse cualquier vpn (WireGuard, Outline…).
- El cliente, por cuestiones de comodidad, será una VM con Ubuntu 22.04 corriendo localmente en mi propia laptop
- El servidor VPN1 será una VM corriendo en un IaaS que ofrece buenos precios llamado Virtalus. Correrá Ubuntu 20.04. La misma tiene el IP público 144.168.40.133.
- El servidor VPN2 será una instancia de EC2 en AWS. Correrá Ubuntu 20.04. La misma tiene el IP público 99.79.50.37.
NOTA: Recuerde siempre que cree alguna VM en algún Cloud Provider abrir los protocolos/puertos en los que va a ofrecer los servicios. En este caso específico son UDP/1194.
Debido a que los CloudProvider cobran por recursos utilizados y esto es un “home” lab, la RAM y CPU de cada VM son los mínimos (512 RAM y 1vCPU).
Comenzamos por la parte más fácil: instalar openvpn en cada una de nuestras VMs:
apt update && apt install openvpn -y
Configuración del VPN2
El siguiente paso es configurar el servidor OpenVPN en la instancia EC2 de AWS (VPN2). Para configurar servidores openvpn hay muchos artículos en línea, el presente tutorial no está enfocado en mejorar la velocidad ni la seguridad de la conexión, así que utilizo un script que me levanta un servidor openvpn en cuestión de segundos. El código del script no me pertenece, pero es libre de usar y está aquí.
Así que, entre a su VPN2 utilizando su cliente SSH de preferencia:
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh && \ chmod +x openvpn-install.sh && \ ./openvpn-install.sh
El script te hace algunas preguntas que te llevarán a configurar el servidor OpenVPN por ti, respóndalas a placer. Son preguntas simples y fáciles de responder y en todos los casos vienen con opciones pre-configuradas. Personalmente siempre dejo las opciones por defecto. Algo a tomar en cuenta es que en el caso específico de este script configura la vpn para utilizar la subred 10.8.0.0/24, detalle que será de importancia en la configuración del VPN1 (Virtalus).
En el proceso del propio script, en el penúltimo paso pregunta si quiere crear los criptomateriales para una conexión, basta con escribir un nombre cualquiera, por ejemplo “vpn1”, y en el paso final pregunta si quieres generarlos con contraseña, la opción por defecto es NO, pero es a gusto del consumidor si utilizar contraseña o no. Una vez termina el proceso sólo queda copiar los criptomateriales generados, si lee bien el output del script, los mismos estarán situados en /root/$nombre_que_introdujo. Hágale un cat
, y cópielos en su editor de textos favorito.
Configuración del VPN1
Ahora vamos con la configuración del VPN1 (Virtalus). Primeramente, dentro de la VM, pegue en algún archivo de texto el contenido que copió previamente de /root/$nombre_que_introdujo del VPN2. Puede utilizar su editor de preferencia (nano rules!!!). O:
cat << EOF > aws.ovpn client proto udp explicit-exit-notify remote 99.79.50.37 1194 dev tun resolv-retry infinite nobind persist-key persist-tun remote-cert-tls server verify-x509-name server_T0GIeh2k4iadzPG6 name auth SHA256 auth-nocache cipher AES-128-GCM tls-client tls-version-min 1.2 tls-cipher TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 ignore-unknown-option block-outside-dns setenv opt block-outside-dns # Prevent Windows 10 DNS leak verb 3 <ca> -----BEGIN CERTIFICATE----- MIIB1jCCAX2gAwIBAgIUEjODUqaBjx6j/o7NlCtR2eiavoAwCgYIKoZIzj0EAwIw HjEcMBoGA1UEAwwTY25fQ3o0ZWNCQ1h4Y29oNG5ENDAeFw0yMzAzMDMwMTA3MDBa Fw0zMzAyMjgwMTA3MDBaMB4xHDAaBgNVBAMME2NuX0N6NGVjQkNYeGNvaDRuRDQw WTATBgcqhkjOPQIBAATCfi0I9sdt5jXsHek9U/xFUxVahu9t Fe4rNxhQSM4NSpoGPHqP+js2UK1HZ6Jq+gDALBgNVHQ8E BAMCAQYwCgYIKoZIzj0EAwIDRwAwRAIgTAkg5zjZDZSbckMnKcpHbVusWtI2N2+O ulQqKve5GN8CIHLBhldYtNlAGrlj2jjfjj+Yz61grjIy20pEBCUX1WGD -----END CERTIFICATE----- </ca> <cert> -----BEGIN CERTIFICATE----- MIIB2TCCAX6gAwIBAgIQeiajnD5gZhfP41efFymPFTAKBggqhkjOPQQDAjAeMRww GgYDVQQDDBNjbl9DejRlY0JDWHhjb2g0bkQ0MB4XDTIzMDMwMzAxMDcxMloXDTI1 MDYwNTAxMDcxMlowETEPMA0GA1UEAwwGY2xpZW50MFkwEwYHKoZIzj0CAQYIKoZI zj0DAQcDQgAEx3De0wOu9Rqt+3zcGlG7oiZEJt9Ay/a0NRbQhbslzm763NLH9OKa lzF4/tQSzWWuyxk7eITFBiQ291GAZNlHmKOBqjCBpzAJBgNVHRMEAjAAMB0GA1Ud DgQWBBTQ4MkIs0fxZEsalAJWujFhzpy+VDBZBgNVHSMEUjBQgBQqZCjeVgWHWRo6 l+RxdocmHnDcoaEipCAwHjEcMBoGA1UEAwwTY25fQ3o0ZWNCQ1h4Y29oNG5ENIIU EjODUqaBjx6j/o7NlCtR2eiavoAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwCwYDVR0P BAQDAgeAMAoGCCqGSM49BAMCA0kAMEYCIQDJcxYgqtEvgsItBNAKIzA+ZQ+uIFq9 agOikJxvEImTmwIhAPqdSYiCK7wuD/aXzO5joBNWhjLkSjVhwXGyfH+zNJNL -----END CERTIFICATE----- </cert> <key> -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg9dPiuNa9E/3NNkVh aXFoPbhaPo2zqGBuK87Dcl4KcwehRANCAATHcN7TA671Gq37fNwaUbuiJkQm30DL 9rQ1FtCFuyXObvrc0sf04pqXMXj+1BLNZa7LGTt4hMUGJDb3UYBk2UeY -----END PRIVATE KEY----- </key> <tls-crypt> # # 2048 bit OpenVPN static key # -----BEGIN OpenVPN Static key V1----- 3b664d17a7f00280f7455e41cc984456 7c491b34a557305b52673539fa6690bd ab7dac2e982e61dac78fe5a14048e55a 97493dc8158413e96bd1bd33cc4ee2ab 95a19e5c60cca0be557f708191b83cce 74b918530e7331fb18b298d6dbe24f64 b99df95bdfee7945ae4e1ab5b0a2e1d2 2885139ffc03ce3fa0b40fd069d30de2 4732b0da0c966bfeaca44d36eb909a2a 94e79c141fb49721b7b941ebde906576 6ce2ce4bf65686f12d67d8c94fd877e6 7d44abc3d600e731a44e8dfa73bb9f04 852234dc784a819dcb128b74f78245f1 faa4d95317a990e45132dddb147c273b 4d18332a082b0dfd5292e2fc6eb5335e 90117550dc2f1b1a7cc8c1406f125232 -----END OpenVPN Static key V1----- </tls-crypt> EOF
NOTA: Lo anterior es sólo un ejemplo de cómo se vería un archivo de criptomateriales de openvpn
Para probar el servidor OpenVPN corriendo en el VPN1 intente realizar una conexión:
tmux new -s vpn
Una vez dentro de la sesión de tmux:
openvpn aws.ovpn
NOTA: Lo más seguro es que en este punto pierda la conexión con el VPN1, esto ocurre a que al conectarse a un servidor OpenVPN, este le configura las rutas por defecto para salir al internet usando la conexión del VPN2. En este caso solamente tiene que abrir una consola a esa VM desde el servicio web que contrató para instanciarla, en el caso de Virtalus el proceso es sencillo. Les dejo los links para los casos de AWS, Linode y Azure. Una vez dentro de la consola virtual abre la sesión de tmux
llamada (en mi caso) vpn y solamente envía Ctrl+C
, esto detendrá la conexión y podrá volver a conectarse a su VPN1 usando el cliente SSH de preferencia.
Probada que la conexión fue satisfactoria ahora queda configurar el servidor OpenVPN en VPN1, para ello hacemos la misma operación que en el caso del VPN2:
curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh && \ chmod +x openvpn-install.sh && \ ./openvpn-install.sh
Recuerde que el script genera un archivo con el nombre que usted le escriba, en dicho archivo están los criptomateriales para la conexión openvpn. Cópielos en algún editor de texto y téngalo a mano!
Ahora, aquí deberemos de hacer un pequeño arreglo en la configuración del servidor OpenVPN, así que detenga el servicio y abra el archivo de configuración:
systemctl stop openvpn@server &&\ nano /etc/openvpn/server.conf
En este archivo tenemos que buscar la línea siguiente:
server 10.8.0.0 255.255.255.0
Y cambiar la subred 10.8.0.0
, por alguna otra de su preferencia. En mi caso en particular utilicé la 10.10.0.0
. Hecho este cambio puede proceder a iniciar el servicio que detuvo:
systemctl start openvpn@server
NOTA: El cambio es requerido hacerlo debido a que ambos servidores vpn (VPN1 y VPN2 como servidor ambos) van a estar en el mismo segmento de red, y eso creará errores de configuraciones.
Aún falta por hacer algunos pequeños cambios. Si escribimos ip a
veremos que nuestro servidor VPN1 tiene una interfaz de red llamada tun0
:
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 100 link/none inet 10.10.0.1/24 brd 10.10.0.255 scope global tun0 valid_lft forever preferred_lft forever inet6 fe80::fb6b:910f:fa01:9a43/64 scope link stable-privacy valid_lft forever preferred_lft forever
Bien, esa interfaz hace referencia a la creada por el servidor OpenVPN. Cuando nos conectemos de VPN1 a VPN2 se creará otra interfaz de red llamada (usualmente) tun1
, tenemos que hacer que nuestro servidor VPN1 enrute todo el tráfico que le entra por la interfaz tun0
hacia la tun1
. Esto lo hacemos utilizando iptables
de la siguiente forma:
iptables -t nat -I POSTROUTING 1 -s 10.10.0.0/24 -o eth0 -j MASQUERADE iptables -A FORWARD -i tun0 -o tun1-j ACCEPT iptables -t nat -A POSTROUTING -o tun1-j MASQUERADE
Lo siguiente debería de hacerlo automáticamente el script, pero nunca está de más comprobar:
sysctl -w net.ipv4.ip_forward=1
Y listo! Ahora que tiene configurado el servidor VPN1 correctamente sólo resta conectarse como cliente al VPN2, para ello abra la sesión de tmux que dejó en segundo plano, y reconecte la vpn que utilizó de prueba anteriormente. Perderá la conexión hacia el VPN1 si está utilizando algún cliente SSH (PuTTY, XShell, MobA…) como se explicó anteriormente.
NOTA: Antes de conectar el cliente, recuerde haber obtenido y copiado en algún lugar los criptomateriales generados por el servidor OpenVPN de VPN1!!!
Configuración del Cliente
La configuración del cliente es la más sencilla. Si ya instaló el paquete de openvpn solamente queda pegar en algún archivo los criptomateriales generados por VPN1 y conectar el cliente (en mi caso llamé el archivo de texto vpn1.ovpn
):
openvpn vpn1.ovpn
Para comprobar que, en efecto, estamos saliendo a internet a través de VPN2 y no de VPN1, basta con, desde el cli de nuestro cliente, ejecutar algo como:
curl https://ipinfo.io/ip
Y listo todo!!!
El tutorial es muy básico, puede mejorarse en muchos aspectos, sobre todo de seguridad, pero ofrece un punto de inicio para los que deseen hacer algo similar.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Autores:
- Frank Morales
- Franco Díaz