Cómo usar Latch para proteger el acceso a sitios web de la Intranet publicados en Internet en un servidor Nginx
La idea de esto surge de la necesidad de poder habilitar bajo demanda la publicación de sitios en mi red hogareña a Internet de una forma simple. De esta forma se evita tener habilitados todo el tiempo en Internet servicios que se usan de forma esporádica, bajando la probabilidad de cualquier intento de acceso no autorizado. Una idea muy sencilla que pretende reducir la superficie de exposición temporal de un servicio en Internet para fortificar un servidor GNU/Linux.
¿Qué sale un 0day para las tecnologías que soportan el sitio? Solo tengo que esperar a parchearlo y volver a abrir el acceso. Para hacer esto utilizo Latch y un script que actualiza la configuración del webserver usado como Proxy Reverso que en mi caso es un servidor Nginx. Este es el proceso completo y los scripts que yo he utilizado para montar esta arquitectura de seguridad que publica y des-publica los sitios usando Latch.
Prerrequisitos para instalar el entorno
Integrar Latch con el Servidor Nginx: Creación de la app Latch
Integrar Latch con el Servidor Nginx: Pareo de la aplicación con cuenta Latch
Para parear la aplicación se puede utilizar este pequeño usamos este script de Python que hace el proceso con un sencillo menú para interactuar.
Antes de ejecutar el script debemos iniciar sesión en la aplicación de Latch en el terminal móvil con nuestra cuenta de usuario de Latch y marcar en la opción inferior, Añadir nuevo servicio y luego en el botón: Generar nuevo código. Cuando tengamos el código temporal de pareado visible lanzamos el script pair.py:
Integrar Latch con el Servidor Nginx: Reverse Proxy permitido o denegado
Llegados a este punto, ya estamos listos para configurar el script que se ejecutara de forma recurrente, cada n minutos por crontab en mi caso, pero que cada uno puede configurar a su gusto. La lógica de este script es:
Con todos los puntos anteriores revisados y preparados, ya podemos correr este script para confirmar el estado de nuestro Latch:
Figura 1: Cómo proteger sitios en NGINX con Latch |
¿Qué sale un 0day para las tecnologías que soportan el sitio? Solo tengo que esperar a parchearlo y volver a abrir el acceso. Para hacer esto utilizo Latch y un script que actualiza la configuración del webserver usado como Proxy Reverso que en mi caso es un servidor Nginx. Este es el proceso completo y los scripts que yo he utilizado para montar esta arquitectura de seguridad que publica y des-publica los sitios usando Latch.
Prerrequisitos para instalar el entorno
• PythonAntes de ponernos con el paso a paso, les cuento que no tengo experiencia en Python por lo que seguramente encontraran formas más elegantes o eficientes de hacer esto, son bienvenidos los comentarios constructivos.
• Una cuenta de desarrollador del Latch
• Una cuenta de usuario del Latch
• La librería con el SDK de Latch para Python
• WebServer de su elección: Puede ser Apache Http Server, Nginx, o cualquier otro, configurado para actuar como Proxy Reverso.
• Un rato de tu tiempo
Integrar Latch con el Servidor Nginx: Creación de la app Latch
• Generar una cuenta de desarrollador de Latch: Una vez que tengas una cuenta de Latch, puedes convertirla en una cuenta de desarrollador. Si quieres proteger esta cuenta, ya sabes que también puedes por Latch a los accesos a Latch.
Figura 2: Poner Latch a la cuenta de desarrollador de Latch |
• Generar una aplicación: El proceso es sencillo. Esto se hace primero haciendo clic en Mis Aplicaciones. Luego en el botón Añadir una nueva aplicación. En esa parte del proceso
Figura 3: Creación de una aplicación en Latch |
• Le asignamos un nombre. En mi ejemplo: Mis Webs y luego tomamos nota de los campos remarcados (Id de aplicación y Secreto). Los necesitaremos para aparear nuestra aplicación cliente (en el celular) y el script.
Figura 4: Creación de la aplicación en Latch |
Integrar Latch con el Servidor Nginx: Pareo de la aplicación con cuenta Latch
Para parear la aplicación se puede utilizar este pequeño usamos este script de Python que hace el proceso con un sencillo menú para interactuar.
pair.py: import os import json import latch appid = input("Ingrese el Applicatrion ID:") seckey = input("Ingrese Secret Key:") api = latch.Latch(appid,seckey) pair_code = input("Ingrese el Pairing Code entregado por su celular:") response = api.pair(pair_code) responseData = response.get_data() responseError = response.get_error() print "Respuesta: ", responseData if responseError != "" : print "Error:" , responseError try: salida=json.dumps(responseData) except (TypeError, ValueError) as err: print 'ERROR:', err
Antes de ejecutar el script debemos iniciar sesión en la aplicación de Latch en el terminal móvil con nuestra cuenta de usuario de Latch y marcar en la opción inferior, Añadir nuevo servicio y luego en el botón: Generar nuevo código. Cuando tengamos el código temporal de pareado visible lanzamos el script pair.py:
~/latch $ python pair.pySi este paso no muestra errores, la aplicación del terminal móvil indicará que hay un nuevo servicio asociado a nuestra cuenta de Latch. De esta forma hemos apareado la aplicación (nuestro script), con nuestra cuenta de Latch. Tomen nota del accountID, lo necesitaremos más adelante.
Ingrese el Applicatrion ID:"*****hqH3usJ4"Ingrese Secret Key:"j32mbXBfhHUyn*******************CrF"Ingrese el Pairing Code entregado por su celular:"*****Asqg"Respuesta: {u'accountId': u'7z3ZTP6p2H3***************************cHaYwmRQyHrk6JYae'}
Figura 5: Cuenta de Latch pareada con la aplicación |
Integrar Latch con el Servidor Nginx: Reverse Proxy permitido o denegado
Llegados a este punto, ya estamos listos para configurar el script que se ejecutara de forma recurrente, cada n minutos por crontab en mi caso, pero que cada uno puede configurar a su gusto. La lógica de este script es:
• Consultar el estado del LatchA continuación un archivo de configuración que configura el Proxy Reverso:
• En base al cambio de estado del Latch manipularemos los archivos de configuración de Nginx para que opere como un Proxy Reverso o simplemente como una web con autenticación http.
El primer paso para hacer funcionar este script es reemplazar las tres variables appid, seckey (provistas por la web de latch) y el accid (accountId que anotamos al momento del pareo de la aplicación).
• Luego debemos generar un archivo de configuración de Nginx que bloquee el acceso y otro que lo habilite.
/etc/nginx $ more rproxy.conf.allow
server { listen 80; return 301 https://$host$request_uri; } server { listen 443; server_name xxxx.com; # Change this to the location you installed lirc_web root /home/nginx/web; index index.html index.htm; access_log /var/log/SSL-rproxy.nginx.log; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass https://sitiointerno:443/; proxy_redirect off; } error_page 401 /401.html; location ~ (401.html)$ { alias /usr/share/nginx/www/$1; } }Y este que lo inhabilita forzando a autenticarse :
/etc/nginx $ more rproxy.conf.deny
server { listen 80; return 301 https://$host$request_uri; } server { listen 443; server_name x.x.x.x; # Change this to the location you installed lirc_web root /home/pi/web; index index.html index.htm; access_log /var/log/SSL-rproxy.nginx.log; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass https://sitiointerno:443/; proxy_redirect off; auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; } error_page 401 /401.html; location ~ (401.html)$ { alias /usr/share/nginx/www/$1; } }Integrar Latch con el Servidor Nginx: Consulta del estado de Latch
Con todos los puntos anteriores revisados y preparados, ya podemos correr este script para confirmar el estado de nuestro Latch:
estado.py:
import os import json import latch appid = "[reemplazar por application id]" seckey = "[reemplazar por Secret Key];" accid = "[Reemplazar por account id]" api = latch.Latch(appid,seckey) response = api.status(accid) responseData = response.get_data() responseError = response.get_error() #print "Respuesta: ", responseData if responseError != "" : print "Error:" , responseError try: salida=json.dumps(responseData) except (TypeError, ValueError) as err: print 'ERROR:', err response = json.loads(salida) estado = response['operations'][appid]['status'] print "Estado:", estado if estado == "on" :
print "Ejecutando script de habilitación de Proxy Reverso" # os.system("diff /etc/nginx/conf.d/rproxy.conf /etc/nginx/rproxy.conf.deny -q >/dev/null && sudo cp -p /etc/nginx/ rproxy.conf.allow /etc/nginx/conf.d/ rproxy.conf && sudo service nginx reload")
else:
Si el resultado es el esperado:print "Ejecutando script de bloqueo de Proxy Reverso" # os.system("diff /etc/nginx/conf.d/rproxy.conf /etc/nginx/rproxy.conf.allow -q >/dev/null && sudo cp -p /etc/nginx/rproxy.conf.deny /etc/nginx/conf.d/rproxy.conf && sudo service nginx restart")
$ python /home/pi/latch/estado.py Estado: off Ejecutando script de bloqueo de Proxy ReversoEn este punto sólo es cuestión de descomentar las líneas del script estado.py donde se toma acción sobre el servidor Nginx:
print "Ejecutando script de habilitación de Proxy Reverso"# os.system("diff /etc/nginx/conf.d/rproxy.conf /etc/nginx/rproxy.conf.deny -q >/dev/null && sudo cp -p /etc/nginx/ rproxy.conf.allow /etc/nginx/conf.d/ rproxy.conf && sudo service nginx reload") else: print "Ejecutando script de bloqueo de Proxy Reverso"# os.system("diff /etc/nginx/conf.d/rproxy.conf /etc/nginx/rproxy.conf.allow -q >/dev/null && sudo cp -p /etc/nginx/rproxy.conf.deny /etc/nginx/conf.d/rproxy.conf && sudo service nginx restart")
Por último, ya solo quedaría agregar nuestro script al crontab o similar. En este punto hay algo que debes tener en cuenta. Si llegaste a este punto puede que te estés dando cuenta de algo muy molesto está pasando con tu terminal. Cada consulta sobre el estado del Latch (cuando este está bloqueado) nos dispara una notificación de intento de acceso no autorizado. Esto es parte de la seguridad de Latch y por ahora no existe la forma de “silenciar” las alertas de un Latch en particular. Como workaround en la configuración de Android he deshabilitado las notificaciones de la aplicación.
Nota de Chema Alonso: Desde Eleven Paths estamos trabajando en un sistema de silenciado de alertas para evitar el flooding de notificaciones en escenarios como éste. En la modalidad Silver de Latch - que puedes tener gratis si eres una Pyme Española, está disponible vía API la consulta silenciosa.
3 comentarios:
Lo voy a probar, interesante :)
Y dale con el "desde Eleven Paths", con lo sencillo que sería "en Eleven Paths estamos trabajando"...
Crontab me pareció una buena idea y la facilidad de las solicitudes silenciosas es bienvenida!
Publicar un comentario