7 de junio de 2016

Concentrador VPN Site-to-Site: Infraestructura PKI y Configuración del servidor

Tal y como dicta el título, en esta entrada vamos a configurar un concentrador VPN utilizando OpenVPN (2.2.1) para el servicio en sí y Debian Wheezy (7.10) como Sistema Operativo. Podriamos optar por soluciones comerciales de renombrados fabricantes y gastarnos los cuartos en aparatitos bonitos con interfaces de gestión mejoradas que facilitan la vida de los administradores. Pero no.... A mi me gusta el riesgo de las licencias GPL y del software sin garantía del desarrollador pero con la garantía y el compromiso de la comunidad.

Como su nombre indica, un concentrador VPN no es mas que un equipo que se encarga de aglutinar todas las conexiones VPN de nuestros clientes, ya bien sea de nuestros puestos de trabajo como de sedes remotas conectadas a través de Internet de una forma segura. En nuestro caso vamos a realizar una configuración Site-to-Site que normalmente se utiliza para conectar dos o más sedes remotas y enrutar el direccionamiento LAN entre los distintos clientes.


Lo primero que debemos hacer es instalar el software del servidor. Por manias o costumbres que tiene cada uno, además de instalar el paquete openvpn siempre me gusta instalar las utilidades User Mode Linux (uml-utilities) que no son necesarias pero yo lo hago. Una vez hecho esto, debemos crear nuestra infraestructura de clave pública (PKI) que utilizaremos a la hora de conectar nuestros equipos.


Para la creación de todos los certificados utilizaremos easy-rsa y como ya comenté en entradas anteriores, en la versión Wheezy de Debian viene integrado en la documentación del paquete. Concretamente, en la ruta /usr/share/doc/openvpn/examples/easy-rsa/2.0/ que es donde está alojada la última versión de los scripts. Lo primero que haremos será editar el fichero de configuración vars para adecuarlo a nuestra infraestructura.


Una vez guardados los cambios del fichero, que no son más que variables como su nombre indica, deberemos aplicarlo en el sistema. Para ello ejecutamos la comando source vars ó . vars desde el directorio raíz de easy-rsa y obligatoriamente tendremos que ejecutar el script clean-all si es la primera vez que lo utilizamos. Mención especial a que dicho script nos borra el directorio donde se generan los certificados por lo que mucho cuidado de ejecutarlo si no tenemos un backup de los mismos.


Una vez tenemos realizada la configuración para nuestra infraestructura, lo primero que hay que hacer es crear nuestra Certificate Authority y lo realizaremos utilizando el script build-ca. De la siguiente captura, reseñar que el campo Country Name (variable KEY_COUNTRY) utiliza alguna nomenclatura estandar y no puede contener más de dos caracteres por lo que no nos dejará utilizar "Pais" como valor de dicha variable.


Una vez generada nuestra propia CA, lo siguiente que generaremos será la clave con los parámetros Diffie-Hellman y lo creamos utilizando el script build-dh.


Ahora toca el turno de crear el certificado para el servidor VPN, para ello ejecutamos el script build-key-server pasándole como argumento el Common Name con el que queremos que se genere dicho certificado. Será necesario aceptar o modificar las variables globales anteriormente definidas en el fichero vars así como introducir nuevos datos según nos valla pidiendo el script.


A continuación nos muestra la información que va estar visible en el certificado y nos pregunta si queremos firmarlo. La respuesta obvia es si y con ello se genera el Certificate signing request que deberemos confirmar para la creación del certificado.


De igual manera crearemos los certificados de los clientes utilizando el script build-key pasándole nuevamente el CN con el que queremos que se genere el certificado. Aceptaremos y añadiremos los datos que nos vaya pidiendo el script.


Tras ello firmaremos el certificado para generar el CSR y lo confirmamos para creación del mismo al igual que hicimos a la hora de crear el certificado del servidor.


Crearemos tantos certificados clientes como sean necesarios. En el caso que nos ocupa sólo son dos y están almacenados junto con el resto de certificados en un directorio llamado keys dentro de la raiz de easy-rsa.


Copiaremos el certificado de la CA, los parametros DH y del servidor tanto el certificado como la clave privada a la raiz del directorio de configuración. En el caso que queramos almacenar los certificados en otro directorio deberemos especificar la ruta correcta (absoluta o relativa) de los mismos en el fichero de configuración.


No esta de mas decir la importancia que tienen estos ficheros y con mayor relevancia la clave privada de nuestra CAca.key. Dentro de la documentación de OpenVPN hay un apartado en el que explica con más detalle toda la creación de la infraestructura PKI y en la que encontramos una tabla (subapartado Key Files) con información de quién necesita cada fichero, por qué y si es necesario mantenerlo a buen recaudo.


Bien, en este punto tenemos toda la configuración de nuestra infraestructura de clave pública preparada para empezar a desplegar el servicio. Dentro de la documentación incluida en el paquete, /usr/share/doc/openvpn, también tenemos a nuestra disposición ficheros de configuración de ejemplo en los que basar nuestras configuraciones tanto para los servidores como los clientes.


Ahora realizamos la configuración del servidor donde modificaremos la directiva local para establecer la IP donde escuchará el servicio, así como las directivas ca, cert, key y dh con los valores del certificado de la CA, certificado del servidor, la clave privada del servidor y el fichero con los parámetros DH respectivamente.

Siguiendo el fichero de configuración, adecuaremos el direccionamiento que vayamos a utiliza con la directiva server y en mi caso me gusta habilitar la directiva client-to-client para que los clientes se puedan ver entre sí pero eso es otro tema. Recomendablemente, activaremos la autenticación TLS con la directiva tls-auth y cambiaremos el algoritmo de cifrado a AES-128-CBC en la opción cipher.

Como última recomendación, para sistemas Linux podemos reducir los privilegios del proceso tras la inicialización del servicio con las directivas user y group. En la siguiente captura se recogen todos los parámetros de configuración con los que podríamos levantar perfectamente el servicio y conectar nuestros clientes de forma satisfactoria.


Antes de ello deberemos generar la clave para la autenticación TLS activada anteriormente. El comando que debemos ejecutar es openvpn --genkey --secret <Name>.key y colocaremos la clave resultante en la raiz del directorio de configuración de OpenVPN o el la ruta que hayamos especificado en la directiva tls-auth.


Pero nuestra idea es montar un concentrador Site-to-Site, actualmente tenemos la parte del concentrador pero no la del Site-to-Site. Para ello será necesario agregar las algunas directivas al fichero de configuración.


Empezaré comentando topology porque hasta hace poco no lo conocía y me parece un parámetro de configuración muy llamativo, del que no comprendo por qué no está ya implementado por defecto ni siquiera en la rama actual del desarrollo por motivos de retrocompatibilidad.Tal y como dicen en la documentación de la directiva:

"The only real reason to use the net30 topology is when requiring support for Windows clients before 2.0.9, or when any Windows clients must be supported and non-Windows clients must be supported that cannot set IP+netmask on the tun adapter. These conditions are rare, and the 2.0.9 client is around 7 years out of date as of 2014."

El valor por defecto es net30 pero si establecemos el valor a subnet, conseguimos entregar todo el direccionamiento de la red que hayamos especificado en la directiva server entregando una IP por cliente y no utilizar cuatro direcciones por cada uno de ellos. He de reconocer que la versión actual de Wheezy no está compilada a la última versión (OpenVPN 2.2.1 [...] built on Dec  1 2014) pero me parece que 7 años de retrocompatibilidad más otros dos a la fecha actual de una versión obsoleta por unas condiciones muy específicas es un poco exagerado.

Siguiendo con las directivas, la siguiente será client-config-dir en la que especificar, como su propio nombre indica, el directorio que contendrá las opciones de configuración particulares para cada cliente. En dicho directorio, crearemos un fichero de configuración con el CN que hayamos asignado a cada cliente y en cada uno especificaremos la dirección IP que van a recibir con la directiva ifconfig-push, la ruta LAN interna de cada cliente utilizando la directiva iroute así como le publicaremos la ruta del resto de clientes con la opción push junto con la ruta correspondiente.


Ya para ir acabando con todo el tema de la configuración del servidor, queda comentar la directiva route que sirve para anunciarle al mismo las redes por las que se espera recibir o enviar paquetes. Tras todos esos cambios, levantamos el servicio y encontramos una serie de mensajes nuevos en el log del servidor.


"[...]
OpenVPN ROUTE: OpenVPN needs a gateway parameter for a --route option and no default was specified by either --route-gateway or --ifconfig options
OpenVPN ROUTE: failed to parse/resolve route for host/network: <Network IP>
[...]"

Según se lee en el mensaje, nos dice algo de que OpenVPN necesita un gateway para la opción route y no hay valores por defecto en la configuración. Nos está diciendo la directiva que está fallando y tras una pequeña búsquedaencontramos una solución (seguro que hay más) que es añadirle la IP que utilizará como gateway el servidor VPN para las rutas de los clientes.


Tras reiniciar el servicio, todo funciona correctamente y el log está limpio de errores o advertencias.


Como la entrada empieza a hacerse un poco larga voy a dividirla en dos, en esta quedaría cubierta toda la parte de la creación de nuestra infraestructura PKI y la configuración del servidor OpenVPN. En la siguiente entrada, realizaré la configuración de un par de clientes basados en pfSense en su última versión así como algunas comprobaciones para corroborar que el sistema funciona correctamente.

Un saludo, Brixton Cat.

4 de mayo de 2016

OpenVPN: Conectando pfSense con Endian UTM

Últimamente el tema va de firewalls y conexiones VPN, en cuanto al blog se refiere, y en este caso se trata de conectar una máquina pfSense contra un Endian UTM utilizando OpenVPN ya que ambas distribuciones lo incorporan por defecto. En mi caso, pfSense es una distribución que conozco hace más tiempo pero Endian hasta hace poco no he tenido el gusto de conocerlo y no me ha decepcionado.

Endian es un proyecto Open Source que nació en el año 2003 por un grupo de profesionales y entusiastas de las telecomunicaciones y Linux que tenían una idea fija: "Desarrollar un Gestor Unificado de Amenazas (UTM) Open Source que fuese el más poderoso del mundo y fácil de usar" (Traducción libre de lo que aparece en la historia de la compañia).

En nuestro caso se trata de montar un servidor OpenVPN en un Endian y para ello utilizaré la versión 3.0.5-beta1 pero el proceso es el mismo para la anterior release (3.0.0), ambas disponibles desde la página de descarga de la Comunidad. El cliente de pruebas será pfSense pero a diferencia de la entrada anterior, utilizaré la versión 2.3 que ha sido publicada a principios de mes pasado.


En esta nueva RC de pfSense hay un cambio generacional que incorpora muchas novedades como la actualización de la GUI a una interfaz Bootstrap dinámica con AJAX mucho más moderna, la gestión de paquetes ahora es controlada completamente por pkg favoreciendo la actualización por partes del software, NGINX como servidor Web, PHP 5.6, y otros tantos cambios como la eliminación del servidor VPN PPTP, el cifrado WEP para los AP, TLS 1.0 para el servidor Web, cifrado DES para conexiones IPsec, etc. Todos los detalles en el changelog. A lo que venimos...

En el menú superior del Endian, vamos a la parte de VPN y tras habilitar el servidor seleccionamos como método de autenticación Certificado X.509 y para el certificado dejamos la opción Usar certificado seleccionado. Al ser de una máquina de pruebas utilizaré tanto la CA como el certificado por defecto para las configuraciones, en un entorno real habría que crear nuestra propia CA y el certificado asociado a la misma.


Tras guardar y aplicar cambios, especificamos la IP en la que escuchará el servicio y el puerto, que por defecto es el 1194, asi como el tipo de interfaz: TUN o TAP y el protocolo. En mi caso son interfaces tipo TUN y sólamente hay que especificar la red para la VPN: 10.8.0.0/24.


Incluso tenemos opciones avanzadas con las que configurar rutas, DNS, nombre de dominio así como otras opciones para nuestros clientes.


Tras hacer todas las configuraciones y volver a guardar y aplicar cambios (lo pongo en negrita porque son apartados de configuración independientes), tenemos nuestro servidor OpenVPN listo y funcional.


Ahora pasaremos a crear el certificado para el cliente y para ello en el menú de la izquierda accedemos al apartado Certificados. Como comentaba antes, por defecto nos crea una CA y un certificado que es usado para el servidor HTTPS y es el mismo que voy a utilizar para el servidor OpenVPN. En este punto, cabe destacar que por defecto también nos crea una Lista de Revocación de Certificados (CRL) por si se da el caso que necesitemos dar de baja algún certificado.


Pulsando en Añadir nuevo certificado pasamos a un formulario en el que escribiremos los datos del propietario del mismo, nuestro cliente pfSense, siendo imprescindibles los campos: Nombre común y la contraseña que protege la lectura del certificado en formato PKCS12.


Una vez creado el certificado, en la lista de los mismos tenemos una serie de herramientas en la columna Acciones. De izquierda a derecha: La primera de ellas nos muestra información del certificado, la segunda nos descarga solamente el certificado en formato PEM, la tercera en formato PKCS12 que es la que nos interesa ya que también incluye el certificado de la CA y la clave privada, con la cuarta eliminamos la clave privada y con la última revocamos el certificado.


Tras haber generado el certificado para nuestro cliente tenemos que prepararlo para poder utilizarlo en nuestro pfSense. Como había comentado, nos descargaremos el certificado en formato PKCS12 y extraeremos de él los datos de la CA, el certificado y la clave privada en formato PEM con el comando:

openssl pkcs12 -in pfSense.home.labcert.p12 -out pfSense.home.labcert.pem -nodes


Después de extraer los datos del certificado descargado del servidor, pasamos a realizar la configuración en el cliente. Para ello accedemos a System > Cert. Manager y lo primero que tenemos que hacer, como ya hicimos en la entrada anterior, es crear la CA de nuestro Endian en el pfSense.


Pulsamos en Add y entramos en el formulario para importar un certificado ya creado: Import an existing Certificate Authority. Damos un nombre descriptivo al certificado y en el campo Certificate data pegamos los datos del certificado de la CA.


En mi caso, el certificado PEM que hemos extraido del Endian me lo ha estructurado de la siguiente manera: Cert. cliente, Cert. CA, Key cliente. Con una serie de campos antes de los bloques BEGIN/END con los datos del certificado o de la clave privada según sea el caso.


Clave privada solo hay una asi que con esa no hay problemas y para los certificados solo tenemos que fijarnos en el campo subject que indica el propietario del mismo ya que el issuer siempre va a ser igual, la CA de nuestro Endian.

Una vez guardados cambios, podemos pasar a importar el certificado y la clave privada para el cliente OpenVPN. Para ello desde el mismo administrador de certificados, pulsamos en la pestaña Certificates y en Add para crearlo dándole un nombre descriptivo y copiando los datos del certificado y de la clave privada del mismo.


Tras guardar cambios, ya podemos pasar a configurar el cliente desde el menú superior accediendo a VPN > OpenVPN y después en la pestaña Clients. El modo de servidor es SSL/TLS, el protocolo UDP, tipo TUN para la interfaz vitual y la WAN como la interfaz física que queremos utilizar del firewall. Además de ello, tendremos que especificar la dirección IP y el puerto donde tratará de conectarse el cliente.


Le damos un nombre descriptivo a la configuración del cliente y pasamos a la parte de autenticación.


Como en nuestro caso se realiza a través de certificados, obviamos los campos Username y Password y nos centramos en la parte de Cryptographic Settings. Tenemos que deshabilitar la autenticación TLS dado que no está configurada en el servidor, el certificado de la CA es el del Endian que es el único que tenemos y el certificado del cliente es el que acabamos de crear.


Haciendo un poco de memoria de la entrada anterior, OpenVPN por defecto utiliza el cifrado Blowfish por lo que también deberemos cambiarlo en la configuración del cliente.


Ya por último cambiar el tipo de compresión a Enabled with Adaptive Compression.


Una vez guardados los cambios se establece la conexión entre los peers y si todo ha salido correctamente deberíamos verlo en Estado > Conexiones VPN de nuestro Endian.


Bien, una vez he tenemos conexión entre las máquinas vamos a pasar a ver los logs para corregir errores o alertas. Revisando el log del servidor vemos como se inicializa el servicio y nos encontramos la primera advertencia:

WARNING: file "/var/efw/vpn/ca/certs/192.168.173.243key.pem" is group or others accessible.


Nos conectamos por SSH al Endian y nos dirigimos a la ruta en cuestión, /var/efw/vpn/ca/certs, y comprobamos que efectivamente la clave privada tiene permisos de lectura y escritura para el propietario, root, pero también de lectura para el grupo y el resto.


El servicio se ejecuta con el usuario openvpn y si tratamos de cambiarlo a nobody se ejectuta pero da unos errores a la hora de borrar archivos temporales. Como el usuario openvpn tiene las mismas limitaciones que nobody, he cambiado el propietario y el grupo y le he quitado el permiso de lectura al grupo y al resto.


Tras reiniciar el servicio con el comando jobcontrol restart openvpnjob, el servicio se ejectuta correctamente sin dicha advertencia pero salta la notificación de la ejecución de scripts personalizados y por defecto está en 3 al igual que pasaba en pfSense.


Cambiando dicho valor a 2 en el archivo de plantilla /etc/openvpn/openvpn.conf.tmpl sigue apareciendo el mensaje pero no permitiremos el pase de contraseñas como variables de entorno.


En el log del pfsense nos aparece una advertencia ya conocida de la entrada anterior:

WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.


Para quitar dicha advertencia deberemos añadir en la configuración avanzada de nuestro cliente la opción: ns-cert-type server.


Ya para ir acabando, en ambos equipos aparecen mensajes de alerta informando que no hay concordancia entre el tamaño máximo de paquetes (MTU) tanto de la interfaz virtual, tun_mtu, como del total del enlace, link_mtu. La advertencia en cuestion en el lado del clientes es:

WARNING: 'link-mtu' is used inconsistently, local='link-mtu 1542', remote='link-mtu 1574'
WARNING: 'tun-mtu' is used inconsistently, local='tun-mtu 1500', remote='tun-mtu 1532'.


Se trata de una advertencia que comentan en la documentación oficial (Al final del todo) de Endian, pero que me queda con la mosca detrás de la oreja... En ella dicen que utilizan la directiva mssfix de OpenVPN para anunciar a los clientes tamaño máximo de MTU que deben utilizar, que por defecto y por compatibilidad se establece en 1500 bytes.

"The Endian UTM Appliance sets a limit of 1450 bytes to the size of the VPN’s MTU, to prevent problems with the common MTU value used by the ISP, which is 1500."

Pero revisando el archivo de plantilla que utiliza Endian para generar el fichero de configuración, /etc/openvpn/openvpn.conf.tmpl, nos encontramos la directiva tun-mtu-extra con valor 32.


Para solucionar dicha alerta, en el lado del servidor podemos comentar simplemente la línea dentro del fichero de configuración que amplia el tamaño de los paquetes.


O en el lado del cliente podremos utilizar las directivas tun-mtu y tun-mtu-extra para que haya concordancia entre el tamaño que espera el servidor y el que tiene configurado el cliente.


En cualquier caso, tanto si modificamos la configuración del servidor como del cliente deberíamos de tener conexión entre las máquinas y sin ningún error o advertencia en los logs.


Un saludo, Brixton Cat.