VPN entre dos servidores con openVPN

2 Octubre 2013 at 16:02 by Adrián Pérez

openvpntech_logo1Hoy vamos a montar una VPN entre dos servidores ubicados en dos CPDs distintos, para que puedan comunicarse entre ellos a través de un canal seguro. En mi caso, he usado el túnel VPN (Full TLS) para conectar dos servidores MySQL que replican los datos el uno del otro. De esta forma, los datos que se replican de la base de datos viajan por Internet a través de un canal privado y seguro.

He hecho las pruebas en el siguiente entorno:

  • OpenVPN 2.3.2 x86_64-redhat-linux-gnu

Un servidor CentOS 6.4 con 512MB de RAM, instancia de RackSpace (sí, 512MB de RAM, y estamos en 2013, sí).

  • Hostname: vpntest1
  • IP pública: 80.80.80.81
  • IP privada: 10.10.10.81

Un segundo servidor CentOS 6.4 con 512MB de RAM, instancia de RackSpace en un CPD diferente.

  • Hostname: vpntest2
  • IP pública: 80.80.80.82
  • IP privada: 10.10.10.82

Por defecto, los servidores vienen con selinux deshabilitado, iptables parado, y no pueden hacer ping entre sí mediante sus ips privadas pero sí mediante sus ips públicas. He seguido, en mayor parte, este fantástico tutorial que han hecho los técnicos de Rackspace.

También es importante configurar ntp en ambos servidor, para que tengan la hora sincronizada.

Instalar openVPN en CentOS 6

Lo primero que haremos, será instalar openVPN en ambos servidores. Para ello, primero instalaremos el repositorio EPEL para CentOS 6 x86_64, que es nuestra arquitectura:

[root@vpntest1 ~]# uname -m
x86_64
[root@vpntest1 ~]# wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
[root@vpntest1 ~]# wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
[root@vpntest1 ~]# rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

Una vez tengamos el repositorio EPEL (y el de remi) instalados, podremos instalar openVPN en ambos servidores, directamente desde yum:

[root@vpntest1 ~]# yum install openvpn

Al acabar la instalación de openVPN, podremos deshabilitar el repositorio EPEL, si así lo queremos, para mantener la integridad del sistema.

[root@vpntest1 ~]# vi /etc/yum.repos.d/epel.repo
...
enabled=0

Configurar el túnel VPN

Si queremos configurar la seguridad TLS (SSL) para nuestro túnel VPN, en este entorno no podremos seguir los pasos que comenta la guía de RackSpace, puesto que según el changelog de openVPN, a partir de la versión openvpn-2.3_alpha2 ya no se incluyen los scripts de "easy-rsa" para generar los certificados. Sin embargo, easy-rsa se continúa manteniendo como un paquete a parte, que podemos descargar. El siguiente proceso lo ejecutaremos únicamente en el primer servidor (vpntest1 en el ejemplo):

  • Vamos a la página del proyecto [https://github.com/OpenVPN/easy-rsa].
  • Descargamos el zip del proyecto (está a la derecha de la página) en el primer servidor -vpntest1- (puedes descargarlo en tu local y subirlo por sftp, o hacer un git clone desde el server).
  • Finalmente descomprimimos el proyecto en /tmp y movemos la carpeta easy-rsa 2.0 al directorio de openVPN:

[root@vpntest1 ~]# yum install unzip

[root@vpntest1 ~]# cd /tmp/
[root@vpntest1 tmp]# unzip easy-rsa-master.zip

[root@vpntest1 tmp]# mkdir /etc/openvpn/easy-rsa
[root@vpntest1 tmp]# cp -R /tmp/easy-rsa-master/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
[root@vpntest1 easy-rsa-master]# cd /etc/openvpn/
[root@vpntest1 openvpn]# chmod -R 777 easy-rsa/
[root@vpntest1 openvpn]# cd easy-rsa/

A continuación usaremos los scripts de easy-rsa para crear los certificados que usaremos para cifrar las conexiones. De nuevo, sólo en el primer servidor, vpntest1:

[root@vpntest1 easy-rsa]# mkdir keys
[root@vpntest1 easy-rsa]# source ./vars
[root@vpntest1 easy-rsa]# ./clean-all
[root@vpntest1 easy-rsa]# ./build-ca

La última instrucción nos pedirá los parámetros necesarios para nuestro certificado:

Country Name (2 letter code) [US]:ES
State or Province Name (full name) [CA]:Barcelona
Locality Name (eg, city) [SanFrancisco]:Barcelona
Organization Name (eg, company) [Fort-Funston]:TestVPN
Organizational Unit Name (eg, section) [MyOrganizationalUnit]:Data
Common Name (eg, your name or your server's hostname) [Fort-Funston CA]:vpntest1
Name [EasyRSA]:TestVPN
Email Address [me@myhost.mydomain]:adrian.perez@mimail.com

A continuación generaremos el certificado con la siguiente instrucción. De nuevo se nos pedirán los mismos valores que acabamos de introducir para el certificado, sólo que esta vez nos pedirá un password (que dejaremos vacío) y un par de preguntas finales que aceptaremos.

[root@vpntest1 easy-rsa]# ./build-key-server vpntest1

Le hemos pasado "vpntest1" como parámetro (en la guía de Rackspace le pasan "ServerA"), únicamente a modo identificativo del servidor actual. "vpntest1" es el hostname del server actual.

En este momento, y desde el mismo servidor vpntest1, generaremos el certificado para el segundo servidor usando build-key en lugar de build-key-server:

[root@vpntest1 easy-rsa]# ./build-key vpntest2

Rellenaremos los parámetros del certificado con los mismos valores, excepto para el Common Name que le daremos como valor "vpntest2". En estos momentos, ya podremos ejecutar la siguiente instrucción:

[root@vpntest1 easy-rsa]# ./build-dh

Al finalizar, estaremos listos para primero definir un enlace simbólico contra las claves que hemos generado, y después copiar los certificados al segundo servidor (con IP 80.80.80.82):

[root@vpntest1 easy-rsa]# ln -s /etc/openvpn/easy-rsa/keys /etc/openvpn/keys
[root@vpntest1 easy-rsa]# scp -r /etc/openvpn/keys root@80.80.80.82:/etc/openvpn/keys

Ahora sí, nos loguearemos al segundo servidor (vpntest2) y ejecutaremos lo siguiente:

[root@vpntest2 tmp]# rm -f /etc/openvpn/keys/*.pem
[root@vpntest2 tmp]# rm -f /etc/openvpn/keys/vpntest1*
[root@vpntest2 tmp]# rm -f /etc/openvpn/keys/index*
[root@vpntest2 tmp]# rm -f /etc/openvpn/keys/serial*

En este momento, deberíamos tener en /etc/openvpn/keys del segundo servidor (vpntest2) cinco ficheros y ningún sub-directorio.

[root@vpntest2 ~]# ls /etc/openvpn/keys/
ca.crt ca.key vpntest2.crt vpntest2.csr vpntest2.key

Iniciar el túnel VPN TLS

Llegados a este punto, estaremos listos para iniciar el túnel.

En el primer servidor ejecutaremos la siguiente instrucción (sí, es una única instrucción):

/usr/sbin/openvpn --remote 80.80.80.82 --dev tun1 --ifconfig 172.16.1.1 172.16.1.2 --tls-server --dh /etc/openvpn/keys/dh2048.pem --ca /etc/openvpn/keys/ca.crt --cert /etc/openvpn/keys/vpntest1.crt --key /etc/openvpn/keys/vpntest1.key --reneg-sec 60 --verb 5

Es importante verificar los parámetros.

  • En "remote" indicaremos la IP pública del segundo servidor.
  • En "ifconfig" indicaremos primero la IP privada que se le asignará al servidor actual y a continuación la que se le asignará al segundo servidor. Ambas han de ser IPs privadas que no estén en uso en nuestros servidores.
  • Finalmente, tendremos que verificar los nombres de los ficheros con los certificados, ya que variarán en función de lo que hayamos decidido indicar durante la generación de los mismos.

Una vez ejecutado, nos iremos al segundo servidor y ejecutaremos un comando parecido (que no igual) con los cambios pertinentes:

/usr/sbin/openvpn --remote 80.80.80.81 --dev tun1 --ifconfig 172.16.1.2 172.16.1.1 --tls-client  --ca /etc/openvpn/keys/ca.crt --cert /etc/openvpn/keys/vpntest2.crt --key /etc/openvpn/keys/vpntest2.key --reneg-sec 60 --verb 5

Vemos que en este caso, "remote" tiene la IP pública del primer servidor, y en ifconfing están las mismas IPs que hemos indicado en el primer servidor, pero en orden cambiado. También hay algunos parámetros que no están y otros que cambiamos (como tls-client). Finalmente, notar que los certificados que pasamos son los correspondientes al segundo servidor.

Con ambos túneles levantados, deberíamos poder llegar de un servidor al otro a través de la IP privada definida para la VPN (172.16.1.1 y 172.16.1.2). Verás que las instrucciones para levantar el túnel se han ejecutado en primer plano y por tanto, se han apropiado del terminal. Puedes abrir un nuevo terminal para realizar las pruebas o usar Ctrl+z y el comando "bg" para recuperar el terminal y mover la ejecución del túnel a background. Así por ejemplo, he testeado conectando desde el segundo servidor al primero, por SSH mediante la IP privada de la VPN:

[root@vpntest2 ~]# ssh root@172.16.1.1
root@172.16.1.1's password:
Last login: Thu Sep 5 09:37:12 2013 from XXXXXXXXX
[root@vpntest1 ~]#

Configuración permanente

Aunque con ésto bastaría para tener nuestro túnel VPN con TLS funcionando, es mejor dejar configurados los parámetros en un fichero de configuración para openvpn, para no tener que pasar todos los parámetros cada vez que tengamos que iniciar el túnel. Si no lo has hecho ya, detén el túnel VPN (con Ctrl+c si el túnel se está ejecutando en primer plano).

En el primer servidor, crearemos el fichero de configuración de openvpn:

[root@vpntest1 keys]# vi /etc/openvpn/server.conf

local 80.80.80..81
port 1194
proto udp
dev tun
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/vpntest1.crt # Replace with the key/certificate pair you created
key /etc/openvpn/keys/vpntest1.key # Replace with the key/certificate pair you created
dh /etc/openvpn/keys/dh2048.pem
server 172.16.1.0 255.255.255.0 # This is the network range that your server will give out. These MUST be non-routeable.
ifconfig-pool-persist ipp.txt
keepalive 10 120
comp-lzo
user nobody
group nobody
status openvpn-status.log
verb 3
client-to-client
client-config-dir ccd

De aquí, lo importante está marcado en negrita. Primero introduciremos la IP pública que tiene el propio servidor ("vpntest1"). Ésta será la IP que escuchará esperando peticiones de conexión desde los clientes VPN. También nos aseguraremos de indicar la ruta a los ficheros con los certificados que hemos creado. Recalcar que en "server", indicaremos el rango de IPs privadas que se le asignarán a los clientes. Finalmente, como lo que queremos es asegurarnos de que siempre se le asigna al cliente (vpntest2) la misma IP privada, crearemos un directorio llamado "ccd" que indicaremos con la directiva "client-config-dir", que usaremos para especificar la IP privada que siempre le asignaremos a ese cliente. Así pues, tras este fichero de configuración, especificaremos la IP para este cliente así:

[root@vpntest1 openvpn]# cd /etc/openvpn
[root@vpntest1 openvpn]# mkdir ccd
[root@vpntest1 openvpn]# vi ccd/vpntest2
ifconfig-push 172.16.1.2 255.255.255.0

Hay que tener en cuenta que el nombre del fichero ha de coincidir con el hostname del servidor. En este caso, se le asignará al cliente vpn "vpntest2" la IP privada 172.16.1.2/24.

En el segundo servidor "vpntest2" crearemos el siguiente fichero:

[root@vpntest2 keys]# vi /etc/openvpn/client.conf

client
dev tun
port 1194
proto udp
remote 80.80.80.81 1194 # Replace with your VPN server's IP
nobind
persist-key
persist-tun
ca /etc/openvpn/keys/ca.crt
cert /etc/openvpn/keys/vpntest2.crt # Replace with the key/certificate pair you created
key /etc/openvpn/keys/vpntest2.key # Replace with the key/certificate pair you created
comp-lzo
verb 3

En  este caso, en "remote" pondremos la IP pública del primer servidor "vpntest1", y de nuevo, nos aseguraremos de introducir las rutas a los certificados creados para este segundo servidor.

Hecho ésto, ya podremos ejecutar, primero en el primer servidor y después en el segundo, las siguientes instrucciones:

[root@vpntest1 ~]# chkconfig openvpn on
[root@vpntest1 ~]# /etc/init.d/openvpn start

Si todo va bien, se habrá iniciado el túnel y ya habrá quedado configurado para que se inicie automáticamente con el boot del sistema. Si hay algún error, tocará revisar el fichero /var/log/messages en busca de más información. Podemos verificar las IPs asignadas a los servidores con:

[root@vpntest1 openvpn]# ifconfig tun0
tun0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
inet addr:172.16.1.1 P-t-P:172.16.1.2 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:7 errors:0 dropped:0 overruns:0 frame:0
TX packets:15 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:588 (588.0 b) TX bytes:1132 (1.1 KiB)

Una vez verificadas las IPs en ambos servidores, podremos verificar como podemos hacer ping de un servidor al otro medianet sus IPs privadas para la VPN.

Firewall e iptables

Hasta ahora no nos ha preocupado la seguridad, pero en un entorno en producción, tendremos un firewall y/o iptables activo en nuestros servidores. Para ello, necesitaremos ejecutar en el servidor principal (vpntest1 en este caso):

iptables -A INPUT -p udp --dport 1194 -j ACCEPT
iptables -A OUTPUT -p udp --dport 1194 -j ACCEPT
iptables -A INPUT -i tun0 -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT

En el secundaio, nos aseguraremos de permitir también todo el tráfico VPN:

iptables -A INPUT -i tun0 -j ACCEPT
iptables -A OUTPUT -o tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -j ACCEPT

De esta forma, estaremos permitiendo la conexión VPN únicamente desde el servidor vpntest2 con IP 80.80.80.82, y aceptando cualquier tráfico siempre que venga de este servidor, a través del túnel VPN.

Fuentes:

https://workaround.org/openvpn-faq

http://www.rackspace.com/knowledge_center/article/centos-vpn-tunneling-with-openvpn