Usando el ProxyPass de Apache para acceder a servidores que están detrás de un host enmascarado.

ArticleCategory: [Choose a category for your article]

System Administration

AuthorImage:[Here we need a little image form you]

[Photo of the Author]

TranslationInfo:[Author and translation history]

original in en Atif Ghaffar en to es Marcelo E. Buil

AboutTheAuthor:[A small biography about the author]

Vivo en Suiza y trabajo como webmaster y administrador de unix. Mis pasiones incluyen Linux, Unix, Perl, Apache y software GPL. Podeis saber más sobre mi en mi página web

Abstract:[Here you write a little summary]

Tengo en casa una pequeña red con Linux usando enmascaramiento IP y un cortafuegos (de aca en adelante lo llamaremos firewall). Aunque todas las máquinas en mi red pueden acceder a toda la informacion que está en internet, únicamente la máquina que está haciendo el enmascarado de IP se puede acceder desde internet. En mi último artículo sobre Apache, mostré cómo reciclar direcciones IP. En éste artículo mostraré cómo hacer que un webserver detras de su firewall pueda ser accedido a través de internet, sin cambiar ninguna de las reglas de su firewall ni comprometiendo la seguridad de su red. En este artículo veremos como usar la sentencia ProxyPass de Apache para lograr esto. Al público que apunto con este artículo es a los administradores de sistema o cualquiera que está construyendo una red local pequeña o mediana en su hogar o trabajo.

ArticleIllustration:[This is the title picture for your article]

[Illustration]

ArticleBody:[The article body]

El problema con el enmascaramiento IP

Por un largo periodo en mi LAN, el router (la máquina que estaba haciendo el trabajo de enmascaramiento y de firewall) estaba también como servidor web, servidor de mail, de ftp, de DNS y todo lo demás que se puedan imaginar. Un día tuve la necesidad que una de las máquinas detras del firewall brindase contenidos web y que puedan ser vistos desde internet. También quería tener en línea algunos documentos desde una máquina SGI IRIX que estaba detrás de la red (un servidor de vídeo que ofrecía imagenes en línea). Esta máquina tenía acceso total a internet, pero los usuarios de internet que querían accederlo no lo podían hacer. Aunque no tenía ninguna intención de conectar a la red la máquina IRIX, era necesario que la gente se conectase a ésta. En el trabajo me enfrentaba con el mismo problema con una red y un firewall similar. Cada vez que alguien quería un servidor web para desarrollo que sea accesible desde internet, para uso únicamente de prueba, había que cambiar las reglas del firewall y había que darle a esa máquina una direccion IP externa y comprometer la seguridad de la red.

Apache al rescate: ProxyPass

Después de considerar varias soluciones, implementé una que incluía al Apache y su sentencia ProxyPass. ProxyPass requiere que el mod_proxy esté compilado o cargado como módulo con su servidor Apache. A continuación tenemos la definición del ProxyPass tal y como viene en el manual de Apache.

ProxyPass

Syntax: ProxyPass <path> <url>
Default: None
Context: server config, virtual host
Override: Not applicable
Status: Base
Module: mod_proxy
Compatibility: ProxyPass está disponible unicamente en Apache 1.1 y sucesivas versiones.

Esta sentencia permite mapear en el servidor local a servidores remotos; el servidor local no actúa como un proxy en un sentido conveniente, pero aparece como un espejo del servidor remoto. <path> es el nombre de la direccion local virtual; <url> es la direccion URL del servidor remoto.

Supongamos que el servidor local tiene la siguiente direccion: http://wibble.org/; entonces

   ProxyPass /mirror/foo/ http://foo.com/
daría como resultado un pedido local para <http://wibble.org/mirror/foo/bar > para ser convertido internamenet a un pedido proxy a <http://foo.com/bar>.

Ejemplo en el mundo real

Mapeando el servidor de v;ideo interno al servidor web externo.
Red interna: hometranet.home 192.168.1.0/255.255.255.0
(En el teatro de internet, intranet, extranet, llamé a mi red hogareña hometranet)
Red externa: developer.ch 193.192.254.50

Servidor de vídeo (interno) corriendo en el host cam.hometranet.home dando servicios de vídeo en línea desde http://cam.hometranet.home:5555/cams/sony/video y fotos desde la camara en http://cam.hometranet.home:5555/cams/sony/image
Yo quería ver Ios resultados de estas direcciones cuando visitase http://mozilla.developer.ch/video
y http://mozilla.developer.ch/image
Esto se puede llevar a cabo sencillamente usando la sentencia ProxyPass de Apache simplemente agregando las siguientes líneas en httpd.conf o srm.conf

ProxyPass /image http://cam.hometranet.home:5555/cams/sony/image
ProxyPass /video http://cam.hometranet.home:5555/cams/sony/video
Ahora, después de reiniciar el servidor web (si mod_proxy está disponible), http://mozilla.developer.ch/image responde al servidor web de la camara.
Para el usuario que visita el site es totalmente transparente, y casi* no se compromete a la seguridad de la red mediante este metodo.
*Uso la palabra casi porque no hay seguridad total en internet :-)

Mapeando Servidores Virtuales

El truco de proxypass puede ser usado para mapear un host virtual entero a una máquina completamente diferente. Por ejemplo:
docs.sun.developer.ch mapeado a solsparc.hometranet.home

NameVirtualHost 193.192.254.50
<VirtualHost 193.192.254.50>
     ServerName sun.docs.developer.ch
     ProxyPass / http://solsparc.hometranet.home/
     TransferLog /net/www/logs/sun.docs.access
     ErrorLog    /net/www/logs/sun.docs.errror
</VirtualServer>

también se puede derivar a hosts por su dirección IP

<VirtualHost 193.192.254.50>
     ServerName sun.docs.developer.ch
     ProxyPass / http://192.168.1.7/
     TransferLog /net/www/logs/sun.docs.access
     ErrorLog    /net/www/logs/sun.docs.errror
</VirtualServer>

Advertencia

Dado que su principal servidor web está haciendo pedidos al servidor web interno a petición de sus usuarios, no se puede hacer ningun logeo razonable al host al que se apunta, en cambio se tienen que cargar todos los pedidos al host original. En el caso anterior yo cargué todas las entradas al host principal sun.docs.developer.ch en lugar de de hacerlo a solsparc.hometranet.home
Resultados de cargarlo en sun.docs.developer.ch (resultado incorrecto)

197.0.22.3 - - [05/Nov/1999:22:09:04 +0100] "GET /index.html HTTP/1.0" 
304 -
187.0.45.67 - - [05/Nov/1999:22:09:04 +0100] "GET /navi.html HTTP/1.0" 
304 -
177.0.5.45 - - [05/Nov/1999:22:09:04 +0100] "GET /entrees.html HTTP/1.0" 
304 -
227.0.9.67 - - [05/Nov/1999:22:09:15 +0100] "GET /complets.html 
HTTP/1.0" 304 -
137.0.7.23 - - [05/Nov/1999:22:09:19 +0100] "GET /menu_poisson.html 
HTTP/1.0" 200 841
193.192.245.73 - - [05/Nov/1999:22:09:25 +0100] "GET /volailles.html 
HTTP/1.0" 304 -
192.167.0.1 - - [05/Nov/1999:22:09:44 +0100] "GET /agneau.html HTTP/1.0" 
304 -                                                            

Resultados de cargarlo en solsparc.hometranet.home

192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /index.html HTTP/1.0" 
304 -
192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /navi.html HTTP/1.0" 
304 -
192.168.1.1 - - [05/Nov/1999:22:09:04 +0100] "GET /entrees.html 
HTTP/1.0" 304 -
192.168.1.1 - - [05/Nov/1999:22:09:15 +0100] "GET /complets.html 
HTTP/1.0" 304 -
192.168.1.1 - - [05/Nov/1999:22:09:19 +0100] "GET /menu_poisson.html 
HTTP/1.0" 200 841
192.168.1.1 - - [05/Nov/1999:22:09:25 +0100] "GET /volailles.html 
HTTP/1.0" 304 -
192.168.1.1 - - [05/Nov/1999:22:09:44 +0100] "GET /agneau.html HTTP/1.0" 
304 -
192.168.1.1 - - [05/Nov/1999:22:09:56 +0100] "GET /desserts_ind.html 
HTTP/1.0" 304 -
192.168.1.1 - - [05/Nov/1999:22:10:00 +0100] "GET /cocktails.html 
HTTP/1.0" 304 -
192.168.1.1 - - [05/Nov/1999:22:10:10 +0100] "GET /cgi-bin/commande.cgi 
HTTP/1.0" 200 2146       =20

Lo mismo se aplica a ACLs( listas de control de acceso) basadas en nombres o IP.
Si se quieren bloquear algunos host/direcciones de IP o se quiere dar acceso a ciertas direcciones de IP a áreas especiales, esto se debe hacer en el servidor principal (el que está disponible para acceso remoto) en lugar de de al servidor local.
Mas aún, no se puede restringir usuarios basándonos en Directories.
Igualmente se puede usar las sentencias Location o Files o FilesMatch.
El siguiente ejemplo trata algunas de éstas sentencias.

<VirtualHost 193.192.254.50>
     ServerName sun.docs.developer.ch
     #esta regla permite usuarios del dominio good.host.com unicamente
     <Location /private>
          order deny,allow
          deny from all
          allow from good.host.com
     </Location>
     #Esta regla prohibe el ayudante del Browser de Microsoft.
     BrowserMatch MSIE uncool_browser
     <Location /coolpages>
         order allow,deny
         allow from all
         deny from env=3Duncool_browser
     </Location>
     #Esta regla permite unicamente usuariosque se encuentran en el 
archivo passwd.httpd
     <Location /coolpages>
         AuthName "only for registered users"
         AuthType Basic
         AuthUserFile "/etc/httpd/passwd.httpd"
         <Limit GET>
              require valid-user
         </Limit>
     </Location>

     ProxyPass / http://192.168.1.7/
     TransferLog /net/www/logs/sun.docs.access
     ErrorLog    /net/www/logs/sun.docs.errror
</VirtualServer>

Recursos adicionales

[Documentacion de Apache mod_proxy]
http://www.apache.org/docs/mod/mod_proxy.html
[Soporte para el Host Virtual basado en nombres de Apache (Apache name-based Virtual Host)]
http://www.apache.org/docs/vhosts/name-based.html
[Documentacion del Virtual Host de Apache]
http://www.apache.org/docs/vhosts/index.html