23 septiembre 2011

Una autenticación fuerte para Openvpn



Exponer a internet un servicio es siempre un punto de entrada para todo tipo de amenazas. Por supuesto, el nivel de riesgo dependerá de la configuración del servicio, el grado de actualización del software y las medidas de seguridad que tomemos para utilizar dicho servicio.

En mi caso, para acceder a mi red, utilizo OpenVPN. El objetivo, como comenté en uno de mis primeros posts en Security By Default (no ha llovido ni nada desde entonces), es estar conectado, esté donde esté. Respecto a OpenVPN, poco queda que contar que no hayamos hecho ya. Nos permite tener la conectividad con nuestras redes, a miles de kilómetros, como si estuviéramos en la oficina o en el salón de casa. Nuestro tráfico irá autenticado y cifrado mediante OpenSSL, utilizando una PKI, con certificados, tanto en el cliente como el servidor, para asegurar que somos quienes decimos que somos.

Desde 2004 hasta hace relativamente poco, mi configuración principal de OpenVPN era por TCP, utilizando un mecanismo port-knocking basado en TCP Wrappers que abría durante 20 segundos la posibilidad a establecer conexiones contra el servicio final. Pasados esos 20 segundos, no se permitían conexiones nuevas por lo que el grado de seguridad era de nivel paranoico para arriba. En realidad, los internals de la configuración eran algo más complicados, puesto que, al menos antiguamente, OpenVPN no permitía utilizar TCPwrappers, por lo que utilizaba Xinetd (que sí que los habilita) para publicar el TCP 443 al exterior durante 20 segundos y hacer un bind al TCP 444 que es donde corría realmente el servicio OpenVPN.

Sin embargo, harto de no poderme conectar a través de redes wireless públicas gratuitas, decidí cambiar mi filosofía del seguridad al 100% mientras no exponga el servicio, y cambié la configuración de OpenVPN al puerto 53 UDP. Quisé probar si los portales cautivos de determinadas redes gratuitas en aeropuertos, estaciones, hoteles, etc,… no controlaban correctamente que el tráfico que permitían salir al exterior fuera realmente DNS. Lo que me he encontrado en estos días de pruebas, es que efectivamente se comprueba que el tráfico enviado sea DNS, por lo que hay que buscar otra forma. No parece que haya más remedio que utilizar alternativas como Iodine o DNS2TCP ya comentadas en SbD en posts anteriores. Sin embargo, por lo que he leido, Iodine no utiliza cifrado de ningún tipo en el envío del tráfico, por lo que podría tunelizarse OpenVPN dentro del propio túnel Iodine, para asegurar que todo viaja cifrado.

Así pues, este cambio "para ganar en funcionalidad", me hará perder en "seguridad", estando el servicio abierto permanentemente a Internet por mucho que Iodine pueda configurarse para requerir una contraseña de acceso.

Me diréis: "Oye Lorenzo, pero si tienes montada tu propia PKI y utilizas autenticación con certificado de cliente, alguien tendría que tener tu certificado para poderse autenticar. Es un buen nivel de seguridad tal cual ¿No eres demasiado paranoico?" La respuesta es: "Sí, soy paranoico, pero si pierdo físicamente mi portátil, la sesión está abierta, es 29 de febrero, la luna está en cuarto creciente y el Logroñés vuelve a primera división y ficha a Messi y a Ronaldo, entonces es posible que presionando un botón, el que me ha robado y ha salido corriendo con mi Mac, esté en mi red".

Así pues, y dado que trabajo para un fabricante de soluciones de autenticación fuerte, quise darle una vuelta de tuerca y aprovechar que tengo licencia gratis para utilizar la solución de Swivel  :D

OpenVPN permite, realizar autenticación de doble factor utilizando algo que tienes (el mencionado certificado SSL) y algo que conoces (un usuario/contraseña por ejemplo).
Ya hemos contado en SbD, cómo OpenVPN permite utilizar usuarios de un directorio LDAP, por ejemplo. En este caso y dado que será Pinsafe quien provea autenticación mediante OTC (One-Time-Code como variante de One-Time-Password), integraremos esta autenticación contra un servidor RADIUS.

Este procedimiento serviría para integrar VPN con cualquier servidor RADIUS, aunque en este caso, además tiene la ventaja de que la contraseña a utilizar cambia en cada autenticación.


Cómo se hizo:
  • Parto de una máquina virtual en la que está instalado el servidor RADIUS en el que delegaré el segundo factor de autenticación en la IP 192.168.52.3.
  • Así pues lo primero es configurar en Swivel Pinsafe los parámetros necesarios para permitir que la IP del servidor openVPN pueda hacer consultas Radius utilizando un secreto compartido.
  • En el servidor OpenVPN instalamos el paquete pam_radius. En el fichero de configuración del propio servicio Openvpn (/etc/openvpn/openvpn.conf) añadimos la línea 
       "plugin /usr/share/openvpn/plugin/lib/openvpn-auth-pam.so openvpn"  
  • En el fichero /etc/pam_radius.conf añadimos una línea de la forma: 
     "192.168.52.3    atitelovoyacontar     10" ->  IP del servidor RADIUS // clave compartida // timeout
  • En el fichero /etc/pam.d/openvpn indicamos que este servicio utilizará el módulo pam_radius_auth.so. Para ello añadimos las siguientes líneas en dicho fichero.
      auth required pam_radius_auth.so no_warn try_first_pass
      account required pam_radius_auth.so

  • Reiniciamos el servicio openvpn -> /etc/init.d/openvpn restart
  • En el fichero de configuración del lado cliente, deberemos añadir la línea "auth-user-pass" de manera que antes de efectuar conexión alguna contra el servidor, el programa cliente pida usuario y contraseña (en este caso de un sólo uso) para enviarlo al servidor.
  • Así pues, cuando desde mi Mac me conecto con Tunnelblick, ahora me pide usuario y contraseña, siendo en este caso, de un solo uso.

6 comments :

Arturo Borrero Gonzalez dijo...

Hola.

No entiendo eso de la contraseña de un solo uso. ¿Podrías concretar más?

Gracias, un saludo.

Lorenzo_Martinez dijo...

Hola Arturo: Expliqué el funcionamiento del OTC (One Time Code) aquí: http://www.securitybydefault.com/2011/07/swivel-pinsafe-autenticacion-fuerte-sin.html Échale un vistazo y si necesitas que te explique algo más, me dices. La idea es que, cada vez que me conecte con OpenVPN, me pida usuario/contraseña. El usuario será siempre el mismo, pero la contraseña cambia en cada autenticación.

D. Rubia dijo...

¿Has probado a poner OpenVPN en el puerto 80? Yo lo he probado en la mayoria de las redes públicas funciona sin problema :P

Lorenzo_Martinez dijo...

La idea inicial era que en redes del tipo hotspot con portal cautivo, funcionase. Lo único que suelen permitir esas redes es UDP 53. Por otra parte, si pones OpenVPN en el puerto 80 TCP, dependiendo si en la red desde la que te conectas, hay un proxy o un firewall que analiza tu tráfico saliente, detectará que no es HTTP "puro" y posiblemente deniegue la conexión. Para eso es mejor utilizar el TCP 443, por aquello de que el SSL es más sencillo que esté permitido (o al menos no sea analizado)
Evidentemente desde un 3G, funcionará cualquier puerto sin problemas

SiD dijo...

Por un lado fail2ban con la siguiente línea y un solo "impacto" en el servicio de openvpn

failregex = :[0-9]{1,5} WARNING: Bad encapsulated packet length from peer 

Y por otro lado un correcto fichero de crl en la configuración de openvpn en el que publicar el hipotético "certificado robado"

Y yo pensaba que era un paranoico O:)

Usted sí que riza el rizo ;P

Adrian Pulido dijo...

¡Qué estoy mu loco! Que me llaman del 1004 y devuelvo la llamada pa ver que querían... Joder, y yo que pensaba que configuraba mis equipos en modo "Dios quiere acceso a tu red para borrar los videos de gatitos...!"