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

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!
VER TEMA

Reducir una imagen con PHP y GD

Reducir una imagen con PHP y GD
Este simple script permite procesar una imagen, pudiendo ser usado tanto al subir la imagen para guardar una versión reducida de esta, o para emitir una versión ajustada a la medida solicitada leyendo desde una imagen mas grande.
Se requiere que la instalación de PHP tenga incorporada la librería GD.
Efecto Imagen Zoom:  Una variante de este código podría usarse para hacer "Zoom" en una imagen muy alta resolución, programando adecuadamente el vector de desplazamiento sobre la imagen original y trayendo solo un área específica, esta técnica combinada con Ajax realiza el efecto de Zoom

Ejemplo de uso:
// IMAGEN ORIGINAL..EN ALTA RESOLUCION.
$fullName = '/anypath/image.jpg';

// OBTENER INFORMACION DE LA IMAGEN ORIGINAL.
list($ow, $oh, $xmime) = getimagesize($fullName);
$imageSize = filesize($fullName);
$mime = '';
if($xmime == 2) $mime = 'image/jpg';
if($xmime == 3) $mime = 'image/png';

// LEER LA IMAGEN ORIGINAL
$f = fopen($fullName,"r");
$imageData = fread($f, $imageSize);
fclose($f);

// HACER EL RESIZE A 160 x 120 px, con 70% de compresion JPEG    
$r = new ImageResizer();
$newImage = $r->resize($imageData, 160, 120, 70, 'jpg', $ow, $oh);

// EMITIR LA IMAGEN
header('Content-type: '.$mime);
echo $newImage;

Si el ejemplo anterior estuviese alojado en una pagina PHP llamada: 
http://miservidor/imagen.php
podríamos visualizar la imagen en una pagina HTML asi:

<html>
   <img src='http://miservidor/imagen.php'>
</html>

Está demás decir que se pudiera programar el script para recibir argumentos y asi emitir la imagen en un formato especifico:

<html>
   <img src='http://miservidor/imagen.php?w=320&h=200&c=50'>
</html>

El script podria recibir los argumentos pasados aqui y asi emitir la imagen en esa dimensión solicitada.
Por qué "a veces" es incorrecto hacer:  "<img src='...' width=160 height=120  >" ?

Respuesta:  Porque "a veces" la imagen original pesa 4 megas y no vas a querer tener en un website una imagen de 160x120 pixels que pese 4 megas, debido a que aunque estes solicitando esas medidas en tiempo de browsing (es decir al momento de presentarla) esa imagen pesara 4 megas, tardara en bajar al browser para finalmente ser presentada en una medida muy pequeña, aparte de quedar horrible por la fragmentación del pixelado, va a pesar mucho.

Código fuente:
  1. <?php
  2. /**
  3.  * ImageResizer
  4.  *      a helper class to handle image resize.
  5.  *
  6.  *      example usage:
  7.  *             
  8.  *  $fullName = '/anypath/image.jpg';
  9.  *      list($ow, $oh, $xmime) = getimagesize($fullName);
  10.  *      $imageSize = filesize($fullName);
  11.  *      $mime = '';
  12.  *      if($xmime == 2) $mime = 'image/jpg';
  13.  *  if($xmime == 3) $mime = 'image/png';
  14.  *       
  15.  *      $f = fopen($fullName,"r");
  16.  *      $imageData = fread($f, $imageSize);
  17.  *      fclose($f);
  18.  *     
  19.  *      $r = new ImageResizer();
  20.  *      $newImage = $r->resize($imageData, 160, 120, 70, 'jpg', $ow, $oh);
  21.  *      header('Content-type: '.$mime);
  22.  *      echo $newImage;
  23.  *
  24.  *
  25.  * @author Christian Salazar <christiansalazarh@gmail.com>
  26.  * @license NEW BSD.
  27.  */
  28. class ImageResizer {
  29.         /**
  30.          * resize
  31.          *      resizes an image making it to fit into a rectangle
  32.          *
  33.          * @param mixed $image  Binary raw image data.
  34.          * @param mixed $dw     destination viewport width
  35.          * @param mixed $dh     destination viewport height
  36.          * @param mixed $q      quality for jpg or png: 1 to 100.
  37.          * @param mixed $imgtype desired output image type 'jpg' or 'png'
  38.          * @param mixed $ow     original image width
  39.          * @param mixed $oh     original image height
  40.          * @return new image. you can echo it or use GD functions to handle it.
  41.          */
  42.         public function resize($image, $dw, $dh, $q, $imgtype, $ow, $oh){
  43.                 $im = imagecreatetruecolor($dw, $dh);
  44.                 $im_src = imagecreatefromstring($image);
  45.                 $_w = 0;
  46.                 $_h = 0;
  47.                 $this->_scaleVector($dw, $dh, 0.95, $ow, $oh, $_w, $_h);
  48.                 // displacement vector, this vector center the image.
  49.                 $dx = ($dw - $_w)/2;
  50.                 $dy = ($dh - $_h)/2;
  51.                 $fillcolor = imagecolorallocate($im,255,255,255);
  52.                 //$xcolor = imagecolorallocate($im, 200,200,200);
  53.                 imagefilledrectangle($im, 0,0,$dw, $dh, $fillcolor);
  54.                 //imagefilledrectangle($im, $dx,$dy, $dx + $_w, $dy + $_h, $xcolor);
  55.                 imagecopyresampled(
  56.                                 $im, $im_src,
  57.                                 $dx, $dy, 0, 0,
  58.                                 $_w, $_h,
  59.                                 $ow, $oh
  60.                 );
  61.                 if($imgtype == 'png')
  62.                         return imagepng($im, null, $q);
  63.                 return imagejpeg($im, null, $q);
  64.         }
  65.         /**
  66.          * _scaleVector
  67.          *     
  68.          *
  69.          * @param mixed $dw             |       destination viewport:
  70.          * @param mixed $dh             |               d = {w, h}
  71.          * @param mixed $delta          |       delta: is a fixture measurement. max 1.
  72.          * @param mixed $ow             |       original viewport to be scaled into "d":
  73.          * @param mixed $oh             |               o = {w, h}
  74.          * @param mixed $out_w         
  75.          * @param mixed $out_h
  76.          * @access private
  77.          * @author Christian Salazar H. <christiansalazarh@gmail.com>  
  78.          * @return void
  79.          */
  80.         private function _scaleVector($dw, $dh, $delta, $ow, $oh, &$out_w, &$out_h){
  81.                 $dR = $dw / $dh;
  82.                 if($dR >= 1){
  83.                         $out_w = $delta * $dw;
  84.                         $out_h = ($out_w * $oh) / $ow;
  85.                 }else{
  86.                         $out_h = $delta * $dh;
  87.                         $out_w = ($out_h * $ow) / $oh;
  88.                 }
  89.         }
  90. }
VER TEMA
 
Copyright ©2015 ZONAHIT - EXITOS DE LA RED • All Rights Reserved.
back to top