7 de enero de 2016

pfSense como cliente OpenVPN

Empiezo esta entrada mientras se termina de instalar una máquina virtual con Debian Jessie, 8.2, que utilizaré como servidor OpenVPN y con la que comentaré el procedimiento para conectar el cliente incluido por defecto en pfSense. En una "próxima" entrada (entrecomillo eso de próxima) me gustaría comentar la instalación de un servidor OpenVPN y las distintas opciones de configuración.

Para el que dudo no haya leído, conozca o haya tocado en alguna ocasión pfSense, comentar someramente que es una distribución basada en FreeBSD orientada al mundo de las redes y más especificamente a routers y firewalls. Cuenta con infinidad de opciones de configuración y servicios que vienen instalados por defecto, además de bastantes aplicaciones de terceros que podemos instalar para añadir más servicios a nuestro equipo.

Pero vamos al trabajo... Partiendo de una instalación básica de un servidor OpenVPN como la que se muestra en la siguiente captura del fichero de configuración, comentaré los pasos realizados para la conexión de pfSense revisando el log del servidor para la resolución de problemas que surjan en el proceso.


Una vez realizada la configuración, revisamos el fichero /var/log/syslog para ver los mensajes que envia el demonio tras un incio del servicio. La información que arroja va desde las versiones del software, el usuario con el que se ejecuta el servicio e información sobre la red como el gateway por defecto o los comandos para levantar la IP virutal que establecerá el tunel cifrado de los clientes.


Una vez tengamos nuestra máquina de pfSense instalada y realizada la configuración inicial, deberemos importar el certificado de nuestra Certificate Authority que habremos generado a la hora de configurar nuestro servidor VPN. Todos los certificados han sido creados con la herramienta easy-rsa. Para ello desde el menú System > Cert Manager, en la pestaña CAs agregaremos el certificado de nuestra CA de pruebas.


Del mismo modo en la pestaña Certificates, es necesario añadir el certificado y la clave privada generados para este cliente.


Ahora es el momento de definir las opciones de configuración del cliente OpenVPN. Para ello accedemos a la pestaña Client desde el menú VPN > OpenVPN:


Siendo necesario rellenar los siguientes parametros de la configuración:

- Server host or address: Dirección del servidor OpenVPN.
- Description: Nombre descriptivo para la conexión.
- Peer Certificate Authority: El certificado de la CA añadida anteriormente.
- Client Certificate: El certificado del cliente VPN añadido anteriormente.
- IPv4 Tunnel Network: La dirección de red junto con la máscara de red de la VPN.


Con estos parametros podemos empezar a jugar y a observar los distintos mensajes del servidor. En primer lugar nos arroja el siguiente error:

TLS Error: reading acknowledgement record from packet
[...]
TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
TLS Error: TLS handshake failed
SIGUSR1[soft,tls-error] received, client-instance restarting

Dicho error es debido a la autenticación TLS que se utiliza para establecer el túnel ya que no hay concordancia entre lo que envía el cliente, recibe y responde el servidor. Por defecto pfSense habilita dicha opción (TLS Authentication) y genera una nueva clave para la conexión:


En el fichero de configuración del servidor OpenVPN, lo encontramos como una recomendación de seguridad añadida y nos informa del comando a ejecutar para generar dicha clave: openvpn --genkey --secret ta.key.


Podemos simplemente deshabilitar dicha opción o como medida de protección y un extra en seguridad, acostumbrarnos a utilizarlo en nuestras instalaciones. Para ello deberemos copiar la clave generada con el comando anterior a la configuración del cliente OpenVPN de nuestro pfSense.


Una vez guardados cambios, el cliente vuelve a intentar conectar con el servidor y se observa como la verificación del certificado del cliente es correcta y prosigue el intento de conexión:


Hay algunos warnings y como veremos, el causante del siguiente error se trata de este:


El log del servidor se inunda del siguiente mensaje que informa que ha fallado el descifrado y ha expirado el tiempo de inactividad del cliente por lo que es rechazado por el sistema:

Authenticate/Decrypt packet error: cipher final failed
[...]
[fw.home.lab] Inactivity timeout (--ping-restart), restarting
SIGUSR1[soft,ping-restart] received, client-instance restarting

¿Cómo solucionar este error? pfSense utiliza el método de cifrado AES-128-CBC mientras que OpenVPN por defecto utiliza BF-CBC como se muestra en la siguiente captura:


Podemos utilizar tanto el cifrado AES como el Blowfish, ambos de 128 bits dado que ambas plataformas lo soportan.


En mi caso, opto por el cifrado AES. Una vez guardados cambios y reiniciado el servicio, volvemos a revisar los mensajes del servidor en busca de más errores en la configuración. Siguen apareciendo algunos warnings pero en este caso podemos ver que se inicializa el cifrado AES-128-CBC correctamente:


La conexión de nuestro cliente pfSense contra el servidor se realiza como podemos observar en la siguiente captura:


Pero en el log del servidor no dejan de aparecer los siguientes mensajes:

Bad LZO decompression header byte: 42
[...]
[fw.home.lab] Inactivity timeout (--ping-restart), restarting
SIGUSR1[soft,ping-restart] received, client-instance restarting

Hasta que el cliente supera el tiempo de inactividad y se resetea la conexión del mismo.


Si nos fijamos en la advertencia en cuestión:

WARNING: 'comp-lzo' is present in local config but missing in remote config, local='comp-lzo'

Vemos claramente que nos indica que el servidor está utilizando el parámetro de configuración comp-lzo mientras que en el cliente no aparece. Dicha opción hace que el servidor comprima el tráfico a través del algoritmo LZO y también debe ser habilitada en el cliente.

Para ello, dentro de la configuración de nuestro cliente OpenVPN en pfSense, buscamos la opción Compression y en la lista desplegable seleccionamos la opción Enabled with Adaptative Compression como se muestra en la siguiente imagen.


Una vez guardados los cambios, podemos ver el log del servidor sin ningún tipo de errores o advertencias a la hora de establecerse la conexión de nuestro cliente VPN:


No debemos olvidar que pfSense es una distribución orientada al mundo de firewalls por lo que hasta que no permitamos el tráfico por la VPN no vamos a tener mucho éxito en nuestras pruebas. Para ello, deberemos acceder desde el menú Firewall > Rules a la pestaña OpenVPN para agregar una nueva regla a nuestra máquina.


En este caso como se trata de máquinas de laboratorio, sólo voy a permitir el tráfico ICMP sobre IPv4 para comprobar que hay conexión en la red VPN.


Pudiendo apreciar que la regla aplicada al firewall funciona correctamente así como la conexión de nuestro cliente al servidor OpenVPN.


Una vez hecho esto y comprobado que todo funciona como debe, ahora toca revisar el log de nuestro querido pfSense del que de momento no hemos hablado siquiera. Para ello desde el menú Status entramos en el apartado System Logs y accedemos a la pestaña OpenVPN para ver los mensajes del cliente:


Podemos observar algunos warnings y el más preocupante se trata del siguiente:

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

Como podemos leer en la página que el mismo mensaje nos ofrece, se trata de añadir una capa más de seguridad para evitar en la medida de lo posible ataques MitM sobre la conexión SSL/TLS con la que se establece el tunel.

Para ello, a partir de la version 2.1, si hemos utilizado el script build-key-server incluido en la suite easy-rsa para crear el certificado del servidor, simplemente añadiremos la directiva: remote-cert-tls server en las opciones avanzadas de la configuración:


En este punto solamente comentar que en Debian Jessie, easy-rsa es un paquete independiente que es sugerido a la hora de instalar OpenVPN, a diferencia de la versión en Debian Wheezy que estaba incluida en la documentación del mismo.

La siguiente advertencia dice lo siguiente:

WARNING: using --pull/--client and --ifconfig together is probably not what you want

Buscando por Internet no he encontrado nada relacionado con el mensaje por lo que he tirado del fichero de configuración que está almacenado en el directorio /vat/etc/openvpn.


Se puede observar que está incluida la directiva ifconfig que se utiliza para especificar el direccionamiento del cliente dentro del tunel VPN. Como no encontraba mucha información me puse a revisar los scripts que generan los archivos de configuración del cliente.

La interfaz gráfica de pfSense está escrita en PHP y los ficheros de configuración se generan tras guardar cambios en los parámetros de configuración de cada servicio. Las funciones PHP que la interfaz gráfica utiliza están almacenadas en el directorio /etc/inc y en el caso de OpenVPN, se llama openvpn_reconfigure y se encuentra en el fichero openvpn.inc:


El parámetro ifconfig del fichero de configuración se crea en el condicional que muestra la siguiente captura de pantalla, donde si la opción IPv4 Tunnel Network está habilitada se utilizará para asignar la IP local y la máscara de red en el caso de interfaces TAP y la IP local y la del servidor en el caso de interfaces tipo TUN.


Por lo que quitando dicho valor en la configuración del cliente OpenVPN desaparece dicha advertencia y todos contentos.


Ya para ir acabando, queda comentar una notificación que aparece en el log del cliente informando que la directiva script-security está habilitada y permite ejecutar scripts definidos por el usuario:

NOTE: the current --script-security setting may allow this configuration to call user-defined scripts


OpenVPN permite ejecutar scripts personalizados de inicio y cierre de conexión que se definen con las directivas up y down respectivamente. Para poder ejecutar dichos scripts, es necesario habilitar la directiva script-security comentada anteriormente y asociarle un valor igual o mayor que 2 como se puede leer en el man del programa.


pfSense habilita dicha opción con el valor 3 que no se recomienda por ser inseguro ya que permite almacenar contraseñas como variables de entorno. Si cambiamos el valor a 2 sigue apareciendo la notificación anterior pero ganaremos algo en seguridad.

De igual manera si descomentamos las directivas user y group de la función openvpn_reconfigure, el servicio se ejecutará con el usuario y el grupo nobody y aseguraremos aun más la configuración de nuestro cliente.


Un saludo, Brixton Cat.