SafeChildren Banner

Havoc Oracle Solaris Experts

miércoles, 3 de marzo de 2010

Archivos de Configuración de Proxy Automática - Proxy PAC

Introducción
Hace un tiempo hablábamos de Cómo Utilizar los Archivos de Configuración Automática de Proxy (PAC), pero parece ser que este formato tiene algunos problemas -principalmente por las dudas que me han ido enviando- así que vamos a ver Cuáles son los problemas de una configuración automática (PAC) y cómo solucionarlas

Archivos PAC
Ya hemos hablado de cuál es su formato, pero vamos a hacer un pequeño repaso. Un archivo PAC, simplemente es una función JavaScript que devuelve si es necesario utilizar un Proxy -y cual- para una URL determinada.

El Problema
Nuestro principal problema viene dado con los equipos móviles, es decir, aquellos que necesitan diferentes configuraciones, veamos un ejemplo:

"Un equipo portátil que se conecta desde La Oficina, VPN y Wifi públicas"

Este equipo, deberá tener las siguientes configuraciones: Proxy 01 para la oficina, Proxy 02 para VPN y SIN Proxy para Wifi públicas

Si hemos definido un Archivo PAC que -por ejemplo- está en $HOME/proxy.pac tendremos un problema ya que no podemos identificar cuándo y dónde se encuentra <JavaScript Nos permite saber la IP local, pero cómo sabemos si esa IP es nuestra?>

La Solución

Para solucionar este problema está perl que nos va a aportar las funciones necesarias para poder crear un archivo PAC bajo demanda en función de quién y desde dónde -es cierto que cualquier lenguaje de script nos permite esto php, jsp, pero con yo he optado por perl-

Como podemos ver en el gráfico, necesitamos tener un DNS -o utilizar el archivo /etc/hosts- para resolver la dirección proxy.test.com de forma interna y un pequeño servidor Web -en mi caso Apache- capáz de ejecutar scripts.

Además, nuestro archivo de configuración <pac> estará ubicado en una dirección web y éste se creará mediante un script dinámicamente. Por último, necesitaremos que el DNS público resuelva también el host, en mi caso, la URL  es http://proxy.test.com/cgi-bin/proxy-conf.sf

Instalación del Sistema de Configuración
Lo primero que debemos hacer es Instalar Apache en Solaris 10 y le añadimos soporte para ejecución de <cgi>, para ello, editaremos el archivo $APACHE_HOME/conf/httpd.conf en la sección de <mod_mime.c> añadiremos la siguiente entrada
AddHandler cgi-script .sf
A continuación definiremos el VirtualHost
<VirtualHost *:80>
    ServerName proxy.test.com
    DocumentRoot /www/proxy.test.com
    ServerAdmin support@test.com
    # Script
    ScriptAlias /cgi-bin /www/proxy.test.com/cgi-bin
    ErrorLog logs/proxy.test.com-error_log
    CustomLog logs/proxy.test.com-access_log combined
</VirtualHost>
Verificamos y recargamos Apache
# /opt/www/apache-1.3.41/bin/apachectl configtest
Syntax OK
# /opt/www/apache-1.3.41/bin/apachectl restart
Creación del script en Perl
Vamos a crear un pequeño script en perl que, básimanente buscará la dirección IP origen, y en función de cuál sea, devolverá una respuesta a otra. En el ejemplo, si la dirección IP es 192.168.0.0/16 entonces, devolverá el proxy "PROXY-01.test.com", en caso contrario el acceso será DIRECT
# vi /www/proxy.test.com/cgi-bin/proxy-conf.sf
#!/usr/bin/perl -w
use strict;
use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

# #################################################
# PROYX-CONF.SF
#
# Description:
#       - script encargado de configurar los accesos de los clientes
#       hacia los diferentes proxy's y/o las excepciones necesarias
#
#       - la validacion de la configuracion se hace mediante el uso
#       de reglas.
# #################################################

# #################################################
# INFO SISTEMA
# #################################################
my ($cgiversion) = "ProxyAutoconf 3.0.0b_1 on Producction on 03.MAR.2008 by Urko";

# #################################################
# inicio del sistema de configuracion
# #################################################
## escribimos el tipo de archivo y las configuraciones necesarias
print "Content-type: application/x-ns-proxy-autoconfig\n\n";

# SOURCE_IP
my ($sourceip) = $ENV{REMOTE_ADDR};

# escribimos un pequeno comentario
print "// $cgiversion\n";
print "// (c) SafeChildren S.L. 2005-2010\n";

# generamos las cabeceras de la funcion
print "function FindProxyForURL(url, host) {\n";

# generamos el cuerpo en funcion de la IP origen
# si esta en la LAN 192.168.0.0/8
my($islan) = rindex($sourceip, "192.168");


if ( $islan >= 0) {
        print "return \"PROXY proxy-01.sfchildren.com:3128\";\n";
}else   {
        print "return \"DIRECT\";\n";
}

# generamos el fin de la funcion
print "\n}\n\n";
Ahora vamos a comprobar su funcionamiento, primero desde un host de la LAN <192.168.0.0/16> y luego desde Internet

$ wget http://proxy.sfchildren.com/cgi-bin/proxy-conf.cgi
--16:14:25--  http://proxy.sfchildren.com/cgi-bin/proxy-conf.cgi
           => `proxy-conf.cgi'
Resolving proxy.sfchildren.com... 10.4.7.17
Connecting to proxy.sfchildren.com|10.4.7.17|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/x-ns-proxy-autoconfig]

    [ <=>                                                     ] 184           --K/s

16:14:25 (10.26 MB/s) - `proxy-conf.cgi' saved [184]

$ more proxy-conf.cgi
// ProxyAutoconf 3.0.0b_1 on Producction on 03.MAR.2008 by Urko
// (c) SafeChildren S.L. 2005-2010
function FindProxyForURL(url, host) {
return "PROXY proxy-01.sfchildren.com:3128";

}
Y ahora desde una pública
$ wget http://proxy.sfchildren.com/cgi-bin/proxy-conf.cgi
--16:14:25--  http://proxy.sfchildren.com/cgi-bin/proxy-conf.cgi
           => `proxy-conf.cgi'
Resolving proxy.sfchildren.com... 193.24.37.17
Connecting to proxy.sfchildren.com|193.24.37.17|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [application/x-ns-proxy-autoconfig]

    [ <=>                                                      ] 184  --K/s

16:24:35 (1.59 MB/s) - `proxy-conf.cgi' saved [184]
$ more proxy-conf.cgi
// ProxyAutoconf 3.0.0b_1 on Producction on 03.MAR.2008 by Urko
// (c) SafeChildren S.L. 2005-2010
function FindProxyForURL(url, host) {
return "DIRECT";

}

Conclusión
Es cierto que el uso de Proxy PAC puede darnos algún que otro problema -principalmente con Java- pero si somos capaces de crear un entorno donde los usuarios no se vean afectados, esto nos ayudará mucho en nuestras tareas de administración.

Aunque en este post yo os he puesto un pequeño script, éste puede ser tan complejo como queramos, por ejemplo: En función de las Horas, Delegaciones, Usuarios, ... y de esta forma parametrizar de forma eficiente nuestras salidas a Internet.

A modo de anécdota sólo deciros que la implemntación de Java 1.5.x de ProxyPAC no era del todo correcta y fallaba, así que tuve que hacer un apaño para que si era Java devolviese el nombre del proxy sin más, era algo así -no está completo-
sub getRequestAgent () {
    my($agent) = $ENV{HTTP_USER_AGENT};
    my($isagent) = rindex($agent,"Mozilla");
  
    if ( $isagent != -1 ) {
      return "browser";
    } else {
      return "java";
    }
}
sub createFindProxyBody()
{
        my($arg1) = @_;
        my($browser) = &getRequestAgent();
        # si pone "java" entonces devolvemos el PROXY sin mas
        if ( $browser eq "java" ) {
            # ponemos el proxy de Java
                    print "return \"PROXY sol10-proxy-02.sfchildren.com:3128\";\n";
            return 0;
        }else {
                my($sourceIP) = $arg1;
                # esta aquí y no es JavaWS
                &createHTTPS();
                &createCommonExceptions($sourceIP);
                &createCommonRules($sourceIP);
            }       
}  


Referencias

3 comentarios:

  1. Hola, exelente tu aporte de este espacio, pero si no es molestia, cómo podriamos crear un .pac que asigne una ip fija en la oficina y cuando estemos en una wifi publica use asignación dinamica?
    Lo digo porque en dhsp, el pac funciona de maravilla, pero si el portatil requiere la ip fija en la oficina, como podriamos automatizar esto??

    ResponderEliminar
  2. Hola Yesid,

    Lo primero gracias y no, no es molestia. Y ahora vamos con la pregunta.

    Corrígeme si me equivoco, la idea es que tienes un portátil en la oficina que tiene IP fija, y que tiene asignado un PROXY también con IP Fija y quieres que si ese portátil está en una red pública (fuera de la LAN) se asigne otro PROXY.

    Bien, para ello, vamos a necesitar un sistema de PAC dinámico -como comento en este Post- y con algunas modificaciones.

    Por ejemplo, si asumimos que la IP estática del portátil en la Oficina es 192.168.1.117 y que la IP del PROXY es 192.168.1.200, podemos crear el archivo de configuración automática en Perl -o en lo que queramos- y que haga la siguiente comprobación -en pseudocódigo-


    SI ip_origen ES 192.168.1.117 ENTONCES
    PROXY 192.168.1.250
    SINO
    no PROXY
    FIN


    Y en Perl sería algo así:


    my ($sourceip) = $ENV{REMOTE_ADDR};
    my($islan) = rindex($sourceip, "192.168.1.");

    if ( $islan >= 0) {
    print "return \"PROXY proxy:3128\";\n";
    }else{
    print "return \"DIRECT\";\n";
    }


    Y la debemos tener un servidor HTTP que nos permita llamar al CGI para configurarlo, por ejemplo, si suponemos que nuestro servidor está en http://proxy.autoconf.test.com/cgi-bin/proxy.cgi

    De esta forma el CGI creará un archivo PAC diferente para cada una de las redes.

    Realmente este POST habla de cómo solucionar este tema y propone este ejemplo.

    Espero haber resuelto tus dudas, si no es así, no dudes en preguntar.

    Un Saludo,
    Urko

    ResponderEliminar
  3. Oye hermano, como hago para que mi compu cambie de direccion ip, es dinamica, ya agote las que me da prodigy infinutum de telmex, soy de mexico, utilizo firefox, asi que estoy pensando en los proxies, pero necesito que me cambie la direccion proxy cada minuto, es posible, como seria el pac?

    Encontre el foxyproxy y t pregunto para poder configurarlo...

    gracias

    ResponderEliminar