lunes, 24 de junio de 2013

Cómo exponer al mundo a tu servidor web de desarrollo.


Aunque este no es un "truco de programación", si es un truco para poder exponer al mundo tu sistema en desarrollo que esta alojado en tu máquina. Este artículo no es un copy-paste de lo que hay en internet, es producto de experiencia personal. Require Linux.

El problema: El servidor web no es accesible.

Te habrás situado ante este problema, en donde el servidor web esta en una red a la cual tu no tienes ningún tipo de permiso para administrar. No puedes habilitar la visibilidad de la máquina en la red, ni siquiera tienes acceso al router, mediante el cual podrias resolver el asunto creando un VirtualPort (Port Forwarding) que te daría acceso a ese equipo requerido.


El problema central es que tu servidor web esta en una red a la cual no tienes acceso desde internet, pero, el servidor si tiene acceso a internet, es decir, el mencionado equipo podría conectarse a un equipo auxiliar tuyo en la red, en internet, y mediante las facilidades de SSH podriamos usar ese equipo auxiliar para conectarnos remotamente al servidor oculto. A esto se le llama: Tunel Inverso.


No siempre el problema es un webserver, pudiera ser un equipo con un servicio especifico: Un escritorio remoto, un servicio DNS, incluso, cosas mas avanzadas, como tener acceso a la Intranet desde afuera pasando por encima de las reglas de red del administrador, o incluso: ocultando tu actividad en la red.  En este ejemplo nos enfocamos en el lado bueno: Darle al servidor web de desarrollo de la oficina acceso desde internet.

Qué es un Tunel Inverso.

Un "Tunel Inverso" es un mecanismo para conectar equipos usando un protocolo de red como TCP/IP.  Permite que quien no tenga la visibilidad en la red sea el equipo que inicie la conexión, debido a que en un ambiente "normal" quien inicia la conexión es un equipo "cliente" hacia un equipo llamado "servidor" el cual es visible en la red. Por ejemplo, un servidor web escucha en el puerto 80 u otro, y la red (con sus reglas) o el mismo equipo "admiten" que otros equipos se conecten a éste. El túnel inverso aplica cuando este caso no se da y el servidor no es visible en la red y tampoco pueden aplicarse filtros en el router para poder lograr esto.

El servidor que inicia la conexión aprovecha la funcionalidad existente en la red: el servidor "si puede" conectarse a otros equipos, es decir "tiene acceso a internet", y con eso basta, ahí entra en juego el tunel inverso y soluciona el problema.

El servidor que usa un tunel inverso iniciará la conexión hacia un equipo visible en internet, recordando que el otro caso no es posible (el servidor es invisible en internet, un cliente no puede conectarse a éste), para ello se usa un comando especial de la herramienta "ssh", el comando "-R", el cual al ser ejecutado en el lado del servidor causa que tras lograrse la conexión al equipo cliente se inicie en este último un proceso que escucha en un puerto dado (el #2048 en el ejemplo de abajo) en consecuencia todo aquel socket que se conecte a este nuevo puerto del equipo cliente será conectado al puerto indicado del servidor (el #80 del ejemplo de abajo).  

De aquí el nombre de tunel "inverso", el "tunel" es la conexión iniciada por el servidor, "inverso" es el modo en que el servidor oirá peticiones: a través del equipo al cual se conectó.

Por qué se requiere un Tunel Inverso.


Tu máquina donde tienes alojado tu trabajo, no es visible desde internet porque: a) no tienes una "IP" o porque b) el router no lo permite o c) el administrador no lo permite o d) el firewall lo bloquea.

Caso #1:
Estas en tu casa y no tienes un servicio de internet donde a ti te dan una IP o te dan el modem con una IP, sino que en cambio alguien te da internet via WiFi.

Caso #2:
La máquina donde tienes el trabajo que quieres publicar en la web esta en tu lugar de trabajo en una oficina en donde el dueño de la red jamás te dara acceso directo a tu máquina desde la calle.

Cómo se implementa el Tunel Inverso.


1) Se hace iniciando una conexión con la herramienta ssh desde "el servidor".  Aquí "el servidor" es el equipo invisible en internet, aquel equipo que tiene los datos que queremos hacer visibles a traves del tunel inverso, y "mi.cliente.net" es aquel equipo que si es visible en internet, el cual usaremos como tunel.

#ssh -R 2048:localhost:80 root@mi.cliente.net


Este comando (arriba) se inicia desde el servidor, se conecta como root al equipo en internet con la dirección "mi.cliente.net" (o su IP), y mediante el argumento "-R" se le indica que "en ese equipo" abra un puerto número 2048 (o cualquier otro) el cual estará enlazado al puerto 80 del equipo servidor.  Es decir, desde el equipo mi.cliente.net se podrá iniciar una conexión a:
http://mi.cliente.net:2048 y eso será equivalente a haber hecho: http://servidor:80/ (claro está si tuviesemos acceso directo a ese equipo, cosa que no esta sucediendo).

No basta solo eso, también hay que crear un un port-forwarding en "mi.cliente.net" usando el comando "ssh -L", debido a la seguridad tras ssh, la cual solo admitirá (por defecto) conexiones a root, es decir, en "mi.cliente.net" solo funcionarán llamadas locales como:

#wget localhost:2048

El resto de las llamadas no funcionará, por ejemplo:  http://mi.cliente.net:2048, debido a que solo estará admitido para localhost y bajo root.

Para resolver esto, se inicia un port-forwading del lado del cliente (el comando "ssh -L") ejecutando:

2) Crea un puerto en mi.cliente.net con el número 9999 y rediriges todo el tráfico en ese puerto hacia la conexión localhost:2048, la cual ha sido creada previamente por el uso del comando ssh -R (iniciada por servidor).

#ssh -L mi.cliente.net:9999:localhost:2048 localhost

(va a pedir la clave de "localhost", es la misma clave de root de el equipo donde estas ejecutando el comando)


Ahora ya podemos acceder desde cualquier parte al equipo servidor, simplemente ejecutando:

http://mi.cliente.net:9999


Ejemplo de Tunel Inverso.

PCLOCAL_01
la máquina en la red de la oficina, sin acceso a esta desde internet, directo o indirecto (via virtual-ports).

mi.equipo.net (190.165.123.10)
un equipo auxiliar bajo nuestro control, que si tiene acceso directo a internet, se usará para acceder a PCLOCAL_01 mediante un tunel inverso.

1. Hacer login como root en PCLOCAL_01:
#ssh -R 2048:localhost:80 root@190.165.123.10

2. Hacer login como root en 190.165.123.10
#ssh -L 190.165.123.10:9999:localhost:2048 localhost

3. Desde ahora y mientras la sesión ssh en ambos equipos este activa se podrá navegar a "PCLOCAL_01" con esta URL:
http://190.165.123.10:9999/


Simplemente cambiando los puertos, puedes acceder a cualquier servicio de tu EQUIPO_PRIVADO.
Suerte!