Alta disponibilidad con OpenVPN
Cuando hablamos de VPN para usuarios siempre pensamos en VPN propietarias, como las de Fortigate, Palo Alto, Watchguard...
Pero esto nos lleva inevitablemente a pasar por caja, a no ser que usemos las IPsec.
Hoy traigo una alternativa que, además de evitarnos licencias, nos permite distribuir la carga y tener alta disponibilidad en nuestro servicio de VPN.

¿Por qué OpenVPN?
He escogido OpenVPN porque nos da la versatilidad de poder usar TCP y UDP.
+¿TCP en VPN? Eso añade latencia y baja la velocidad frente a UDP...
-Si, pero no.
Hace no mucho se aceptó el módulo ovpn en el kernel principal de Linux y desde OpenVPN 2.6 existe OpenVPN DCO.
DCO significa Data Channel Offload.
Es una arquitectura que mueve el procesamiento del canal de datos de OpenVPN desde el proceso en espacio de usuario al kernel de sistema operativo.
Para entenderlo, primero hay que distinguir los dos canales de OpenVPN:
Canal de control: negocia la conexión, autentica al cliente, intercambia claves, renegocia sesiones...
Canal de datos: transporta todos los paquetes IP que circulan por el túnel.
¿Qué implica esto? Mucho menos uso de CPU, utilizando la aceleración por hardware como AES-NI y menor latencia.
Laboratorio
En este caso tenemos el siguiente escenario:

Tendremos un firewall de borde, en el que crearemos las rutas estáticas hacia la subred del túnel VPN.
Aguas abajo nos encontramos con un NGINX que nos hará la función de proxy inverso y balanceador de carga, distribuyendo las conexiones entre ambos servidores OpenVPN.
Configuración NGINX
Para poder hacer funcionar nginx como balanceador de carga deberemos instalar los siguientes paquetes:
apt install nginx libnginx-mod-streamDeberemos configurar nginx con la directiva stream.
Directiva stream: ¿qué es? Esta directiva nos da la posibilidad de habilitar la capacidad de proxy para conexiones TCP y UDP. De esta forma, NGINX podrá manejar las conexiones en capa 4, la capa de transporte del modelo OSI.
Deberemos añadir en /etc/nginx/nginx.conf una directiva al mismo nivel que http{}, de la siguiente forma:
# Fuera de la directiva http{}, se puede poner al final del fichero
stream{
include /etc/nginx/streams-enabled/*;
}Ahora deberemos crear la estructura de carpetas correspondiente:
mkdir -p /etc/nginx/streams-available/
mkdir -p /etc/nginx/streams-enabled/Creamos el fichero de configuración que hará de load balancer:
upstream udp_openvpn {
hash $remote_addr consistent;
server 172.16.200.17:1194;
server 172.16.200.18:1194;
}
server {
listen 1194 udp;
proxy_pass udp_openvpn;
}hash $remote_addr consistent: Es la regla que hace que las conexiones de la misma dirección IP se dirijan al mismo servidor, de tal forma que crea conexiones persistentes.
Configuración de OpenVPN
Primero deberemos crear los certificados de servidor y cliente con nuestra PKI, tal y como hicimos en la entrada de creación de PKI con easy-rsa
Instalamos openvpn:
apt install openvpnUna vez hecho, copiaremos los ficheros necesarios en las rutas de openvpn:
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf /etc/openvpn
cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/clientY procedemos a configurar el server.conf.
Al abrir el fichero nos encontramos con que nos pregunta si va a ser TCP o UDP y el puerto. Comentamos la línea que no vayamos a usar. En mi caso voy a usar UDP.


Aquí escogemos el tipo de interfaz que vamos a usar. En mi caso quiero encapsularlo todo en paquetes IP y que tenga una subred distinta.
Si tienes dudas entre una y otra, te dejo un enlace donde puedes leer la diferencia: interfaces TUN y TAP.
A continuación indicamos donde se encuentran los certificados de servidor y la CA.

En mi caso, estoy haciendo el ejemplo de uno de los dos servidores, pero cada uno tiene su propio certificado y debe indicarse en este lugar.
Lo siguiente, y es importante, es modificar las subredes del túnel. Si ambos servidores exponen la misma subred, al establecer rutas estáticas en el firewall no sabrá a qué servidor enviarla. Aún con ECMP enviará los paquetes de forma equitativa, rompiendo así la conexión.

Ahora deberemos decirle que rutas vamos a introducir al cliente cuando se establezca la conexión:

Si queremos que los clientes puedan comunicarse entre sí.

Ahora deberemos seguir las instrucciones del fichero y generar la clave, tal y como dice, y referenciarla.

Y al final del fichero añadiremos lo siguiente:

Por último, deberemos permitir el forwarding en los servidores OpenVPN.
Escribimos en /etc/sysctl.conf:
net.ipv4.conf.all.forwarding = 1Lo hacemos persistente:
sysctl -pNo es obligatorio, pero por costumbre de entornos legacy aún lo sigo haciendo:
echo 1 > /proc/sys/net/ipv4/ip_forwardConfiguración del cliente OpenVPN
Copiamos el client.conf y lo renombramos como el nombre del usuario.ovpn. En mi ejemplo es jose.ovpn
Debemos fijarnos que al principio del archivo pone que es client:

Y comprobamos que el resto de parámetros coincide con el servidor:

En remote ponemos la dirección IP/FQDN y el puerto.
Comentamos la parte de los certificados, ya que va a ir explícitamente en cada fichero:

Y al final del fichero deberemos crear las etiquetas con sus certificados correspondientes:
<ca>
# Contenido de la CA
</ca>
<cert>
# Contenido del certificado del usuario
</cert>
<key>
# Contenido de la clave privada del usuario
</key>
<tls-crypt>
# Contenido del ta.crt
</tls-crypt>Una vez hecho esto, guardamos el .ovpn y se lo entregamos al usuario final para que pueda conectarse.
Como se puede ver, con un test de velocidad con iperf3, esto es lo que me ofrece:

¡Espero que os sirva de ayuda!




Comentarios