Tutorial: ngrok - cómo publicar en Internet cualquier página o aplicación web que tengas en tu equipo local

30/11/2018
Artículo original

Está claro que si queremos publicar un sitio o aplicación web de manera permanente debemos configurar y gestionar un servidor web, o contratar algún tipo de servicio básico (hosting) o avanzado (Cloud PaaS) para hacerlo. Pero en muchas ocasiones lo único que queremos es poder exponer temporalmente hacia el exterior de manera sencilla un desarrollo que hemos hecho y que tenemos en nuestra máquina local. Existen muchos casos en los que esto es interesante:

  • Queremos compartir con otras personas un trabajo para que puedan verlo, revisarlo, opinar o ayudarnos a probarlo.
  • Queremos hacer alguna integración con un sistema externo (por ejemplo, una pasarela de pagos), no podemos hacerla en producción pero al mismo tiempo necesitamos que el servicio pueda hacer llamadas a nuestra app en desarrollo.
  • Necesitamos depurar un servicio REST, un Webhook que recibe llamadas desde sistemas externos.
  • Queremos probar una aplicación desde dispositivos móviles o máquinas que están fuera de nuestra red
  • Nos interesa exponer hacia Internet una aplicación de uso interno pero que queremos que algunos usuarios concretos puedan acceder desde diferentes lugares del mundo, pero sin que la queramos montar en un servidor "real" por costes o porque el tráfico va a ser bajo y la disponibilidad no tiene que ser del 99,999% ni nada similar.
  • Exponer al exterior servicios web corporativos que están en nuestra red local, con acceso controlado y sin forzar a los usuarios a utilizar una VPN o similar.
  • Etc...

Para suplir estas necesidades, una herramienta estupenda y cada vez más utilizada es ngrok (pronunciado "en-groc"). Como me gusta mucho y le saco mucho partido, m he decidido a crear este tutorial para que tú también puedas exprimirle toda su utilidad.

ngrok es un ejecutable único y sin dependencias que podemos descargar para Windows, Linux, macOS y FreeBSD, y que con una simple instrucción nos permite exponer hacia el exterior cualquier servicio web local que tengamos en nuestro ordenador, en cualquier puerto. Con ngrok poner en marcha un servicio en Internet albergado en nuestra máquina es cuestión de 4 o 5 segundos. Además la app expuesta puede funcionar tanto con HTTP como con HTTPS, podremos establecerle credenciales de acceso y muchas otras cosas más.

En este artículo te voy a contar cómo ponerlo en marcha y cómo configurarlo. También cómo saltarte algunas limitaciones de ciertos servidores que solo pueden servir páginas en local, como por ejemplo IISExpress.

¡Vamos a allá!

Puesta en marcha de ngrok

Lo primero que debemos hacer es crear una cuenta en ngrok.com, para lo cual solo necesitamos un email y una contraseña. El hecho de registrarnos nos proporciona un token que es el que nos permitirá generar de manera segura nuestros servicios y que no los pueda "secuestrar" otro usuario, además de darnos acceso a información de estado de los "túneles" que creemos entre nuestro equipo e Internet.

Una vez registrado debes bajarte el ejecutable de ngrok para tu sistema operativo, algo que ya se te ofrece nada más entrar en la web de ngrok tras haberte dado de alta (paso 1 de esta captura):

 Lo bajas en un ZIP y lo único que tienes que hacer es descomprimirlo en la carpeta desde la cual lo quieras utilizar. Por ejemplo, en Windows yo lo tengo en C:\Program Files, pero puedes ponerla en cualquier carpeta a la que tengas acceso de lectura sin necesidad de ser administrador.

Con esto ya llegaría, puesto que ngrok.exe es un programa auto-contenido, es decir, no tiene otras dependencias y puede funcionar por si solo. De todos modos lo más recomendable es añadir el ejecutable a tu "path" del sistema, de modo que el comando ngrok lo tengas disponible desde cualquier ventana de línea de comandos. Para ello, dependerá de cada sistema operativo. En Windows la manera más sencilla es abrir  una línea de comandos con permisos de administrador y escribir:

setx path "%path%;C:\Program Files\ngrok\"

con la ruta a la carpeta donde lo hemos descomprimido.

Esto introduce esa ruta en el "path" del usuario local, tal y como te muestro en la siguiente animación:

Una vez hecho esto podemos abrir una línea de comandos (buscando cmd) y podremos usar el comando ngrok en cualquier carpeta del sistema.

Lo único que tenemos que hacer para configurarlo y poder empezar a usarlo es asignarle nuestro token personalizado. Como comentaba antes, este token nos identifica ante la herramienta de modo que nuestros túneles a la Web sean exclusivamente nuestros. Este token lo obtenemos desde la propia portada de la web (ver figura anterior a la animación) o bien, mejor, yendo al apartado "Auth" en el lateral:

En esta página se nos muestra el token (que es una cadena de caracteres muy larga) y podemos copiarlo al portapapeles directamente. También se nos muestra el comando que tenemos que utilizar para asignarlo a la herramienta en nuestra máquina y poder empezar a usarla:

ngrok authtoken XXXXXXXXXXXXXXX

siendo esas "X" el token que se nos haya asignado. Una vez ejecutado este comando se anotará el token en un archivo dentro de la ruta de nuestro usuario, subcarpeta de nombre ".ngrok2", en un sencillo archivo de texto de tipo YAML (pares nombre:valor), como se puede ver en esta captura:

Nota: si por casualidad ese token se viese comprometido, podríamos resetearlo yendo al apartado "Admin" de la web de ngrok:



Dentro del apartado "Dangerous operations" puedes introducir el token actual y dándole a resetear obtendrías uno nuevo. Pero luego tendrías que volver a establecerlo y tendrías que reiniciar los túneles que hubieses creado.

¡Vale! Ya tenemos ngrok configurado y listo para ser utilizado. ¡Vamos a empezar a sacarle partido!

Estableciendo un túnel para exponer nuestra app a Internet

Parto de la base de que tienes un servidor web local funcionando con alguna aplicación. Para aplicaciones Front-End puras, sin nada de código de servidor, yo suelo utilizar Fenix, que aunque lleva mucho tiempo sin actualizarse, funciona muy bien y es muy rápido de poner en marcha y sencillo de utilizar. Para lo demás, en Windows, suelo usar IISExpress, y el add-on para integrarlo con Visual Studio Code. Pero es muy habitual usar Live Server entre otros muchos.

A los efectos de este artículo voy a suponer que tienes una aplicación Web funcionando en un servidor local cualquiera de estos, en el puerto 15666 (por poner uno concreto, ya que en local no sueles usar el puerto 80 convencional).

Bien, para levantar un túnel entre nuestra máquina local y ngrok y exponer nuestra aplicación hacia afuera, lo único que hay que escribir es:

ngrok http 15666

es decir, indicar el comando http y el puerto. Esto levantará un túnel inmediatamente, como se ve en esta animación:

Si te fijas en la información que se muestra nada más ejecutarlo, te indica en qué ubicaciones está disponible el servicio expuesto. Son los dos "forwarding" del final, que en este caso asignan un subdominio de ngrok aleatorio a nuestra aplicación. En el ejemplo: https://0c057449.ngrok.io y  https://0c057449.ngrok.io.

Para comprobar que todo funciona como es debido, abre un navegador cualquiera y navega a una de estas direcciones (que son el mismo URL pero accedido mediante HTTP o HTTPS respectivamente). Deberías ver tu aplicación local (si no la ves, luego veremos cuál puede ser el motivo).

Lo que está ocurriendo en este momento es que ngrok está actuando como proxy entre los usuarios que se conectan a esa dirección y tu máquina, tal y como muestra esta figura sacada de su propia web:

Es decir, el usuario se conecta a ngrok a través de la dirección anterior, y ngrok está conectado directamente a tu máquina y replica las peticiones al servidor local, devolviendo el resultado al usuario. Es un intermediario entre ambos.

Si abres tu cuenta de ngrok en el navegador, podrás ver esos nuevos túneles que se han creado y conocer su estado:

Cada vez que pares el túnel y lo vuelvas a reiniciar cambiará la dirección en el que está expuesto. Esto es una limitación de la versión gratuita. En cualquiera de las ediciones de pago puedes reservar estos nombres es incluso utilizar subdominios o dominios propios, lo cual es muy interesante para algunos usos de la herramienta.

Es interesante señalar que puedes usar ngrok en una máquina para acceder a un servicio ubicado en otra de la misma red, no solo al servidor local. Si, por ejemplo, tienes una aplicación en la dirección 192.168.1.30 de tu red local escuchando en el puerto 15666, puedes levantar un túnel hacia ella desde tu máquina usando: ngrok http 192.168.1.30:15666.

 

Ubicación geográfica

Si te fijas, hay un detalle que quizá te haya pasado inadvertido, pero es el hecho de que tu túnel se ha creado en la región denominada us. Esto quiere decir que el proxy que actúa de intermediario entre tus usuarios y tu equipo está ubicado en Estados Unidos. Esta es la opción por defecto.

La ubicación geográfica no suele tener gran importancia para un uso sencillo, pero lo que es indudable es que si todos tus usuarios (incluso si el usuario eres tú mismo) están en una misma zona geográfica, cuanto más cerca de ellos geográficamente se encuentre el proxy más rápido será el acceso a la aplicación, lógicamente.

Debido a ello es posible que quieras cambiar la ubicación del proxy por defecto.

ngrok ofrece ahora miso cuatro regiones para ubicar los proxies:

  • us - Estados Unidos (Ohio)
  • eu - Europa (Frankfurt)
  • ap - Asia/Pacífico (Singapore)
  • au - Australia (Sydney)

Así, por ejemplo, dado que yo estoy en España y sé que mis usuarios van a estar también en España, lo lógico sería ubicar el proxy a mis túneles en Europa, ya que así el cuádruple viaje que tiene que hacer cada petición (usuario-ngrok-mi equipo-ngrok-usuario) tendrá que recorrer el menos espacio físico posible y será más rápido.

Para ello puedo utilizar el parámetro region de la herramienta, así:

ngrok http -region eu 15666

De esta manera mis túneles ahora se crearán contra Frankfurt y todo irá más rápido (aunque es probable que no lo notes demasiado).

Importante: el comando ngrok solo permite establecer túneles contra una única ubicación. Por ello aunque establezcamos varios túneles a la vez (luego veremos cómo) todos deben estar ubicados en la misma zona geográfica.

Si queremos evitarnos el tener que meter este parámetro cada vez que lancemos un túnel, y queremos que sea el valor por defecto, podemos abrir el archivo de configuración ngrok.yml que vimos antes y añadir esto:

region: eu

justo debajo del token.

Inspeccionando las peticiones

En la línea de comandos desde la que lanzamos el túnel se van mostrando las diferentes peticiones que se reciben, pero se trata de una información muy escueta que nos sirve poco más que para saber que hay actividad en el túnel.

Si abrimos un navegador y visitamos la dirección http://localhost:4040, o lo que es lo mismo http://27.0.0.1:4040, tenemos acceso a un completo inspector de peticiones e información sobre la actividad del túnel. Podremos examinar todas y cada una de las peticiones viendo sus cabeceras y contenidos, así como obtener otro tipo de informaciones, como se ve en esta animación que he grabado:

Incluso podremos reproducir las peticiones (volver a ejecutarlas), lo cual nos puede resultar muy útil cuando estamos depurando algún tipo de servicio o Webhook.

Se trata de un añadido muy interesante cuando estamos depurando o probando algún servicio, pero es algo innecesario que puede cargar más nuestra maquina y ocuparnos mucho espacio en otros escenarios, por ejemplo cuando estamos compartiendo un desarrollo con clientes. Es por eso que se puede desactivar el log de las peticiones que recibimos y toda la información relacionada. Basta con usar el parámetro inspect, así:

 ngrok http -inspect=false 15666

De modo que ya no se registrarán las peticiones.

Proteger el servicio/app que estamos exponiendo en Internet

Si no queremos simplemente poner el servicio abierto a todos en la red, podemos proteger el túnel de varias maneras.

La más sencilla y disponible incluso en la versión gratuita de ngrok es mediante el uso de una usuario y una clave. Para ello se utiliza el parámetro auth, así:

ngrok http -auth="usuario:clave" 15666

A partir de que levantemos el túnel de esta manera, cuando alguien intente acceder se le mostrará un diálogo del navegador solicitándole el usuario y la clave correspondientes. Se trata de una autnticación básica tradicional (Http Basic Auth de las de toda la vida) y por lo tanto simple. Si la usas debes asegurarte de que todos entren a través de HTTPS ya que las credenciales se envían en claro a través de la red. Lo bueno es que la soportan incluso los navegadores más antiguos y las bibliotecas de programación más cutres.

En las ediciones de pago se puede limitar también el acceso solamente a ciertas IPs.

Problemas con cabeceras y nombres de dominio

Algunas aplicaciones y algunos servidores (según como estén configurados) solamente permitirán el acceso desde ciertas direcciones concretas. Por ejemplo, en IISExpress por defecto solamente se admiten conexiones a localhost o 127.0.0.1, las direcciones locales de la máquina. O a lo mejor si tienes un servidor web con varios servicios/aplicaciones configurados en local en la misma IP y puerto, la única forma de dirigir las peticiones a una u otra es a través de un nombre de dominio.

Pero ngrok por defecto hace todas las peticiones a locahost, y según tu configuración esto puede ser un problema por lo ya expuesto.

Por suerte lo tienen todo en mente y también es posible especificar qué nombre de dominio utilizar en las cabecera para realizar las peticiones al servidor local (o en otra máquina de la red) contra el que estamos estableciendo el túnel. El parámetro adecuado en este caso es host-header:

ngrok http -host-header=localhost 15666

Ahora todas las peticiones se lanzan especificando en las cabeceras de las peticiones el dominio localhost (o el que hayamos especificado), por lo que el servidor verá dicho dominio y atenderá las peticiones de la manera adecuada, como si de verdad estuviese expuesto a Internet mediante el mismo.

Guardando los parámetros para reutilizarlos fácilmente

Si lanzamos un mismo túnel de ngrok a menudo para compartirlo con alguna gente y no queremos estar escribiendo en la línea de comandos los mismos valores una y otra vez, lo que podemos hacer es dejarlos guardados en el archivo de configuración YAML que vimos al principio. Para ello podemos usar la clave tunnels que a su vez nos deja especificar los valores que necesitemos. Por ejemplo, esta imagen muestra la configuración del túnel que hemos creado anteriormente, con todas las opciones que hemos visto ya establecidas:

Fíjate en que todos los parámetros de la línea de comandos tienen su equivalente en el archivo de configuración. Solo hay que fijarse en que los que tienen guiones en su nombre al usarlos desde allí, en el archivo los cambian por guiones bajos. Por ejemplo, host-header se convierte en host_header.

De esta manera podemos dejar definidos todos los túneles que necesitemos y luego utilizarlos tan solo escribiendo su nombre en la línea de comandos, así por ejemplo:

ngrok start iismailer

sin tener que acordarnos nada más que de su nombre.

Múltiples túneles al mismo tiempo

Otra de las cosas interesantes de lo que acabamos de ver es que nos permite lanzar varios túneles a la vez usando su nombre. Por ejemplo:

ngrok start iismailer administracion servicio

que lanzaría los tres túneles llamados iismailer, administracion y servicio que debemos tener definidos en el archivo YAML como acabamos de ver.

Y esto me lleva a hablar de una cosa importante a tener en cuenta. Según el nivel de suscripción a ngrok que tengamos podremos lanzar más o menos túneles y procesos.

Un proceso ngrok es un comando ngrok que lancemos desde la línea de comandos. Y un túnel es una conexión entre un proxy y un servicio local.

Así, en el comando anterior hemos lanzado un solo proceso ngrok con tres túneles.

Esto es importante porque según nuestro nivel de suscripción tenemos ciertas limitaciones. Por ejemplo, en la versión gratuita solo podemos tener un proceso ngrok funcionando en un momento dado, con hasta un máximo de 4 túneles abiertos que pueden recibir 40 peticiones por minuto. Son restricciones bastante razonables para unnivel de suscripción gratuito pensado sobre todo para pruebas o compartir a muy pequeña escala. En otros niveles de pago puedes llegar a tener 2 procesos ngrok con hasta 20 túneles en cada uno y 120 peticiones por minuto. No son para poner un servidor con mucho tráfico en Internet, pero no está pensado para eso tampoco (para eso tienen un producto empresarial específico, ngrok-link, capaz de soportar enormes cargas sin problema).

En resumen

Hoy he querido hablarte de una estupenda herramienta gratuita que personalmente me gusta mucho y que uso sobe todo para realizar ciertas pruebas en desarrollo, pero que tiene multitud de aplicaciones interesantes. Te he contado cómo ponerla en marcha y cómo utilizarla con las opciones más habituales.

Dispone de algunas características avanzadas adicionales (exponer servicios no HTTP, Websockets, túneles TLS con certificados propios...) que están reservadas a las versiones de pago y que puedes descubrir si te lees con calma la documentación, que es muy clara y concisa.

Ofrece también de una API local a la que se accede a través de http://localhost:4040/api/ y que te permite automatizar el servicio local y obtener información sobre el mismo.

Si no has utilizado nunca te animo a probarlo y sacarle partido en tus desarrollos.

¡Espero que te resulte útil!