SafeChildren Banner

Havoc Oracle Solaris Experts

miércoles, 31 de marzo de 2010

Monitorizar Servicios Solaris 10 Nagios - Parte 1

Introducción
Una de las cosas que más echo en falta en la versión actual de SMF sobre Solaris 10u8 es poder Monitorizar los estados de los servicios. La verdad es que se habla mucho de poder utilizar SNMP para hacer consultas a los estados, pero, a día de hoy no está implementado.

Para solucionar este problema -hasta que implementen SNMP- podemos utilizar diferentes scripts que nos proporcionaran la funcionalidad de monitorización necesaria.

En este primer acercamiento vamos a utilizar una versión modificada de un PlugIn para Nagios que nos permitirá saber el estado de un servicio, su uso es el siguiente:
check_svc <service name>
Este sencillo plugin nos devuelve OK si el servicio está online, WARNING si está en online* y CRITICAL si está en maintance.  Si el servicio está OFFLINE, entonces devuelve UNKNOW, veamos un ejemplo sencillo:
# ./check_svc tomcat_6:default_64bits
OK tomcat_6:default_64bits is online
# echo $?
0
# ./check_svc tomcat_6:default_32bits
UNKNOWN tomcat_6:default_32bits is disabled
# echo $?
3
Este plugin tiene como ventaja que es realmente rápido, sin embargo, tiene deficiencias ya que no podemos establecer cuando un estado de disabled es un WARNING o CRITICAL, siempre nos devuelve UNKNOWN. Además, para hacer que sea rápido he tenido que hacer algunos cambios en el código original. Aquí os dejo una versión de verificación de Solaris SMF para Nagios modificada

Para verificaciones más complejas tenemos otra versión -también en Nagios Exchange- llamada check_solaris_smf que nos permite parametrizar el nivel de CRITICAL, WARNING y OK de la siguiente forma:
check_solaris_smf -f <frmi> -c <critical> -w <warning> -o <ok>
Por ejemplo, si queremos evaluar el servicio tomcat_6:default_64bits y los valores són: CRITICAL si está disabled u offline, WARNING si está en maintance o degraded y OK si está en online. Para ello utilizaremos el siguiente comando:
# ./check_solaris_smf -f tomcat_6:default_64bits -c DIS,OFF -w MNT,DGD -o ON
SMF SVCS OK - tomcat_6:default_64bits ON
# echo $?
0
Cuál Utilizo?
La verdad es que depende un poco de las necesidades, pero la mayor potencia del script check_solaris_smf hace que sea más lento. Aquí os dejo los tiempos de ambos scripts al ejecutar la misma comprobación:
# time ./check_solaris_smf -f tomcat_6:default_64bits -c DIS,OFF -w MNT,DGD -o ON
SMF SVCS OK - tomcat_6:default_64bits ON

real    0m0.184s
user    0m0.046s
sys     0m0.095s
# time ./check_svc tomcat_6:default_64bits
OK tomcat_6:default_64bits is online

real    0m0.084s
user    0m0.021s
sys     0m0.039s
Conclusión
En esta primera parte, hemos visto cómo podemos crear -utilizar- unos pequeños scripts que nos van a permitir ver el estado de los servicios, y devolvernos un nivel para la monitorización con Nagios.

El principal problema que tienen, es que asumen que los servicios que vamos a monitorizar se encuentran en la misma máquina donde tenemos instalado nuestro Nagios y eso -normalmente- no es así.

En las siguientes entregas, veremos cómo configurar los sistemas de monitorización para que remotamente podamos checkear los servicios utilizando un usuario no privilegiado

Referencias

lunes, 29 de marzo de 2010

Eliminar archivos con caracteres especiales, más formas

Introducción
En post anteriores hemos visto Cómo eliminar archivos utilizando su inode para poder eliminar archivos con caracteres especiales. Sin embargo, existen otras formas de poder utilizar los comandos rm sin tener que hacer malabares con ellos.

Si nuestro archivo contiene como primer carácter <-> entonces, rm lo entenderá como argumento y no como nombre -esto es debido al uso de getopt()-, pero tenemos una opción para ello, utilizar el fin de opciones <--> y los comandos no evaluarán el resto como opciones sino como argumentos -en BSD fin de argumentos se crea con <-.>-. Por lo tanto, la sintaxis será la siguiente:
$ comando -opciones -- argumentos
Veamos un ejemplo con un archivo con nombre <-r>
# ls -ltr
total 16
-rw-r--r--   1 root     root          70 mar 23 11:44 -r
# rm *
sintaxis: rm [-fiRr] archivo ...
# rm -- -r
# ls -l
total 0
 También podemos utilizar ./nombre para proceder a eliminar el archivo, por ejemplo,
# ls -ltr
total 16
-rw-r--r--   1 root     root          30 mar 23 12:08 -rF
# rm ./-rF
# ls
total 0
Referencias

viernes, 26 de marzo de 2010

rm lista demasiado larga para borrar archivos

Introducción
Si tenemos muchos archivos en un directorio -más que <MAX_ARGVS>-y queremos borrarlos utilizando <rm> puede que nos diga <Lista de argumentos demasiado larga>. Para solucionar este problema, utilizaremos el comando find con la opción <-exec rm {} \;>, veamos un ejemplo donde queremos borrar todos los archivo .req de un directorio
# rm *.req
bash: /usr/bin/rm: Lista de argumentos demasiado larga
# find . -name "*.req" -exec rm {} \;
# ls -l *.req
*.req: No existe tal archivo o directorio
Debeis tener en cuenta que -como comenta Joan- <find> realiza las operaciones de forma recursiva, por lo tanto, debemos tener cuidad cuando ejecutamos estos comandos.


Referencias

miércoles, 24 de marzo de 2010

Cómo Borrar la Cache de Squid - Limpiar Caché de Squid

Introducción
Si queremos borrar toda la caché de squid, simplemente deberemos crear un archivo sin contenido en <$SQUID_HOME/var/cache/swap.state> y reiniciar nuestro squid. Esto hará que la caché de disco se marque como inválida, pero no la caché de memoria. Es muy importante entender este concepto, ya que si squid nos muestra en el log MEM_HIT utilizando este método no se borrará. Para ello, simplemente paramos/iniciamos squid y ya está.

Veamos un ejemplo para marcar la caché de disco como inválida <vaciar caché>
# echo "" > $SQUID_HOME/var/cache/swap.state
# $SQUID_HOME/sbin/squid -k reconfigure
Sin embargo, si lo que queremos es eliminar una entrada de la caché, deberemos utilizar el comando <PURGE> con el siguiente formato:
# $SQUID_HOME/bin/squidclient -m PURGE -h proxy-host url
Para poder hacer esta llamada, debemos permitir el método en el archivo de configuración  <squid.conf>, para ello, declararemos como permitido el método PURGE de la siguiente forma
acl purge-host src 127.0.0.1
acl purge method PURGE
http_access allow purge purge-host
Para aquellos intrépidos os dejo un script en perl que se le pasa por argumento la url que queremos que expire y lo realiza en todos los proxys declarados, su formato es el siguiente:
http://url.script.com/cgi-bin/purgecache.cgi?f=http://url-a-expirar

Referencias

lunes, 22 de marzo de 2010

Buscar Archivos Mediante su Fecha de Modificación y/o Acceso

 Introducción
 En ocasiones es necesario buscar archivos utilizando su último acceso y/o última modificación -principalmente para borrar archivos antiguos- para ello podemos utilizar las opciones <-atime> y <-ctime> del comando <find>.
    -atimen        True if the file  was  accessed  n  days
                         ago.  The  access time of directories in
                         path is changed by find itself.

     -ctime n      True if the file's status was changed  n
                         days ago.
Sin embargo, en otras ocasiones lo que queremos es saber a partir de una fecha en concreto los archivos creados/accedidos, para ello debemos utilizar la opción <-newer _file_> donde _file_ será nuestro archivo de referencia de búsqueda.

Para poder crear un archivo con una fecha concreta, utilizaremos el comando <touch> con la opción <-t YYMMDDHHMM.SS>, veamos un ejemplo donde crearemos tres archivos -prueba1,prueba2 y prueba3- donde el primero tendrá la fecha-hora actual, y los otros dos serán establecidas con la opción <-t>

$ touch prueba1
$ ls -l
total 0
-rw-r--r--   1 itily    sysadmin       0 mar 22 10:09 prueba1
$ touch -t 7812281000.00 prueba2
$ ls -l
total 0
-rw-r--r--   1 itily    sysadmin       0 mar 22 10:09 prueba1
-rw-r--r--   1 itily    sysadmin       0 dic 28  1978 prueba2
$ touch -t 0001010000.00 prueba3
$ ls -l
total 0
-rw-r--r--   1 itily    sysadmin       0 mar 22 10:09 prueba1
-rw-r--r--   1 itily    sysadmin       0 dic 28  1978 prueba2
-rw-r--r--   1 itily    sysadmin       0 ene  1  2000 prueba3
Una vez creados, vamos a buscar utilizándolo como fecha inicial 
$ find . -newer prueba3 -print
.
./prueba1
$ find . -newer prueba2 -print
.
./prueba1
./prueba3
$ find . -newer prueba1 -print
.
 Referencias

viernes, 19 de marzo de 2010

Como eliminar archivos utilizando su inode

Introducción
Puede que alguna vez nos encontremos con un nombre de archivo un tanto extraño -por ejemplo con "-" o "/"- y desde la línea de comandos -con rm- no podemos borrarlo.

No hay problema, para ello, debemos utilizar el valor de su inode y utilizaremos el comando find para poder borrarlo. Vamos a ver un pequeño ejemplo, donde crearemos un archivo con nombre -h y lo intentaremos borrar con rm
# vi
  este archivo no se puede  borrar con rm
:w-h
:q
# ls -ltr
total 16
-rw-r--r--   1 root     root           7 mar 19 10:29 -h
# rm *
rm: opción no permitida -- h
sintaxis: rm [-fiRr] archivo ...
Como ya sabíamos, <-h> se le pasa a rm y éste lo interpreta como una opción y no como nombre del archivo.

Vamos a utilizar el comando <find> con la opción <-inum> y el inode del archivo para poder eliminarlo, el formato será el siguiente
# find _path_ -inum _inode_ -exec rm {} \;
Lo primero  que debemos conocer es el número de nodo <inode> y para ello, utilizaremos la opción <-i> de <ls> y posteriormente, ejecutaremos nuestro comando find para eliminarlo, veamos un ejemplo
# ls -li
total 16
  30475938 -rw-r--r--   1 root     root           7 mar 19 10:29 -h
# find . -inum 30475938 -print
./-h
# find . -inum 30475938 -exec rm {} \;
# ls -li
total 0
Conclusión
Aunque serán en contadas ocasiones este pequeño tip nos solucionará problemas, sobre todo si tenemos un servidor de archivos y tenemos MacOS y/o Windows como clientes.



Referencias

miércoles, 17 de marzo de 2010

Cómo Activar el log de IPFilter

Introducción
Hemos visto Cómo Activar IPFilter para Hadoop en Solaris 10, sin embargo, este procedimiento se puede aplicar a cualquier servicio -ya que depende de las reglas y no del servicio-, sin embargo, en esta ocasión vamos a ver cómo podemos Activar el Sistema de Log de IPFilter para que nos logee los accesos. Para ello, debemos utilizar el modificador <log> en nuestras reglas, por ejemplo,

block in log quick from any with ipopts
block in log quick proto tcp from any to any with short
Esto hará que se registren en el fichero de log de IPFilter, para ello, debemos activar <local0.debug> en nuestra configuración de syslog y reiniciar el demonio, vamos a verlo. Recordar que la separación entre <local0.debug> y el nombre del fichero </var/log/ipfilter.log> debe ser tabuladores y no espacios
# vi /etc/syslog.conf
  ############################################
  ## IPFilter Log
  ############################################
  local0.debug                              /var/log/ipfilter.log
:wq
# touch /var/log/ipfilter.log
# chmod 600 /var/log/ipfilter.log
# svcadm restart system-log

Referencias

lunes, 15 de marzo de 2010

Dónde esta ip_forwarding en Solaris 10

Introducción
En versiones anteriores de Solaris <8 y 9> para poder activar el soporte de router, debíamos -a parte de tener al menos dos interfaces de red- poner a <1> el valor de la propiedad <ip_forwarding> del módulo del kernel </dev/tcp> para ello, simplemente debíamos hacer
# ndd -set /dev/tcp ip_forwarding 1
El valor <1> es para activar, y <0> para desactivarlo.

A partir de Solaris 10, esto ya no tiene efecto y debemos utilizar el comando <routeadm> para comprobar y activar el reenvío de paquetes -y protocolos de enrutado-

# routeadm
              Configuration   Current              Current
                     Option   Configuration        System State
---------------------------------------------------------------
               IPv4 routing   disabled             disabled
               IPv6 routing   disabled             disabled
            IPv4 forwarding   disabled              disabled
            IPv6 forwarding   disabled             disabled

           Routing services   "route:default ripng:default"

Routing daemons:

                      STATE   FMRI
                   disabled   svc:/network/routing/route:default
                   disabled   svc:/network/routing/rdisc:default
                   disabled   svc:/network/routing/zebra:quagga
                   disabled   svc:/network/routing/rip:quagga
                   disabled   svc:/network/routing/ripng:default
                   disabled   svc:/network/routing/ripng:quagga
                   disabled   svc:/network/routing/ospf:quagga
                   disabled   svc:/network/routing/ospf6:quagga
                   disabled   svc:/network/routing/bgp:quagga
                   disabled   svc:/network/routing/legacy-routing:ipv4
                   disabled   svc:/network/routing/legacy-routing:ipv6
                   disabled   svc:/network/routing/ndp:default
Para activarlo podemos utilizar las opciones de <-e {propiedad}> o, el FMRI de SMF <svc:/network/ipv4-forwarding:default>, por ejemplo:
# routeadm -e ipv4-forwarding
O utilizando <svcadm>
# svcadm enable ipv4-forwarding
Y podemos comprobar que está activado, utilizando <routeadm> o <svcs>

# routeadm
              Configuration   Current              Current
                     Option   Configuration        System State
---------------------------------------------------------------
               IPv4 routing   disabled             disabled
               IPv6 routing   disabled             disabled
            IPv4 forwarding   enabled              enabled
            IPv6 forwarding   disabled             disabled

           Routing services   "route:default ripng:default"

Routing daemons:

                      STATE   FMRI
                   disabled   svc:/network/routing/route:default
                   disabled   svc:/network/routing/rdisc:default
                   disabled   svc:/network/routing/zebra:quagga
                   disabled   svc:/network/routing/rip:quagga
                   disabled   svc:/network/routing/ripng:default
                   disabled   svc:/network/routing/ripng:quagga
                   disabled   svc:/network/routing/ospf:quagga
                   disabled   svc:/network/routing/ospf6:quagga
                   disabled   svc:/network/routing/bgp:quagga
                   disabled   svc:/network/routing/legacy-routing:ipv4
                   disabled   svc:/network/routing/legacy-routing:ipv6
                   disabled   svc:/network/routing/ndp:default
# svcs ipv4-forwarding
STATE          STIME    FMRI
online         22:12:10 svc:/network/ipv4-forwarding:default

Referencias

viernes, 12 de marzo de 2010

Cómo Cambiar MaxSize de un Datafile con AutoExtend On

Introducción
Ya hemos visto antes Cómo Redimensionar un Datafile en Caliente, pero en esta ocasión, vamos a ver cómo podemos cambiar el valor de MAXSIZE de nuestro Datafile.

En nuestro ejemplo, vamos a cambiar el tamaño máximo <MAXSIZE> del datafile <undotbs01.dbf> de 2Gb a 3Gb

SQL> SELECT FILE_NAME, BYTES, MAXBYTES FROM DBA_DATA_FILES WHERE TABLESPACE_NAME='UNDOTBS1';

FILE_NAME
--------------------------------------------------------------------------------
     BYTES   MAXBYTES
---------- ----------
/u08/oradata/TEST/undotbs01.dbf
2516582400 2147483648


SQL> ALTER DATABASE DATAFILE '/u08/oradata/TEST/undotbs01.dbf' AUTOEXTEND ON MAXSIZE 3072M;
Database altered.

SQL> SELECT FILE_NAME, BYTES, MAXBYTES FROM DBA_DATA_FILES WHERE TABLESPACE_NAME='UNDOTBS1';

FILE_NAME
--------------------------------------------------------------------------------
     BYTES   MAXBYTES
---------- ----------
/u08/oradata/TEST/undotbs01.dbf
2516582400 3221225472

Conclusiones
Como siempre, debemos tener en cuenta que antes de realizar tareas de administración, debemos asegurarnos de tener una copia de seguridad, y por supuesto realizar los cambios antes en Test

Cambiar de tamaño incrementándolo no supone mayor problema, cuando lo que deseamos es disminuir aquí ya tenemos que tener más cuidado y tener en cuenta otras variables, por ejemplo, la ubicación máxima de la extensión en el Datafile, aka <WaterMark> pero eso lo contaremos en otro post

Referencias

miércoles, 10 de marzo de 2010

ORA-01031 Al Conectar con Oracle con sqlplus / as sysdba

Introducción
Puede que nos pasa que al intentar conectarnos a nuestra Oracle con "sqlplus / as sysdba", nos responda con el error ORA-01031: Insufficient privileges y nos pida el usuario y contraseña de nuevo.

Este problema se debe principalmente a problemas con los propietarios de los archivos de Oracle y/o sus grupos, me explico, si instalamos Oracle RDBMS con el usuario oracle y grupo dba pero por cualquier motivo cambiamos el grupo del usuario oracle a otro, entonces Oracle -el motor- no autenticará al usuario del sistema oracle porque no pertecene al grupo que él tiene almacenado -dba-

Para solucionarlo, primero debemos verificar los permisos de los archivos: listener.ora, sqlnet.ora y tnsnames.ora que se encuentran en <TNS_ADMIN> que pertenezcan al usuario que debe ejecutar Oracle RDMS

$ id -p
uid=2011(oracle) gid=2010(dba) projid=106(group.dba)
$ ls -l $ORACLE_HOME/network/admin/*.ora
-rw-------   1 oracle   dba         1690 ago 18  2009 /u01/app/oracle/10.2/db/network/admin/listener.ora
-rw-r-----   1 oracle   dba           91 ago 12  2009 /u01/app/oracle/10.2/db/network/admin/sqlnet.ora
-rw-r-----   1 oracle   dba         8391 nov 17 16:56 /u01/app/oracle/10.2/db/network/admin/tnsnames.ora
A continuación, debemos verificar que en nuestro $TNS_ADMIN/sqlnet.ora tenemos correctamente la búsqueda de nombre -en mi caso sólo files-

$ cat $ORACLE_HOME/network/admin/sqlnet.ora
sqlnet.expire_time = 2
sqlnet.inbound_connect_timeout = 90
names.directory_path=(TNSNAMES)
Por último, el más importante, con qué usuario y grupo se linkaron los binarios de Oracle RDBMS en la instalación, para ello, debemos buscar en el archivo <config.s> la entrada 0x0008    15 donde se muestra que grupo tiene Oracle RDBMS asignado

$ cat $ORACLE_HOME/rdbms/lib/config.s |grep "0x0008"
/* 0x0008         26 */         .type   ss_dba_grp,#object
/* 0x0008         27 */         .size   ss_dba_grp,16
/* 0x0008         13 */         .align  8
/* 0x0008         15 */         .ascii  "dba\0"
Llegados a este punto, si nuestro valor es diferente -que era nuestro caso de ejemplo- tenemos que asignar el grupo <dba> a nuestro usuario <oracle> o, hacer un relink de Oracle -esto lo veremos en otro post-.

Para modificar nuestro usuario <oracle> y añadir como grupo <dba>, simplemente utilizaremos el comando <usermod> con la opción -G para añadirlos
# usermod -G dba,oinstall oracle
Conclusión
Las instalaciones de Oracle tienen muchas configuraciones y parámetros unidos al usuario y al nombre del host, por ello, como recomendación, hacer los cambios antes de instalar los productos de Oracle, os ahorrará muchos disgustos

Referencias

lunes, 8 de marzo de 2010

Cómo saber las variables de entorno de un proceso

Introducción
Puede que en algún momento necesitemos saber cuáles son las variables de entorno que tiene asignadas un proceso en ejecución -principalemente para comprobar que todo va bien- y para ello, tenemos el comando <pargs> que nos ofrece las siguientes opciones:
  • -a, nos muestra los argumentos del proces
  • -e, nos muestra las variables de entorno
  • -l, nos muestra la linea de ejecución completa
Veamos unos ejemplos, 
# pargs -e 5971
5971:   /usr/jdk/instances/jdk1.5.0/bin/sparcv9/java -Xms512m -Xmx512m -jar /opt/www/jm
envp[0]: XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt
envp[1]: NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat
envp[2]: LD_LIBRARY_PATH=/usr/jdk/instances/jdk1.5.0/jre/lib/sparcv9/server:/usr/jdk/instances/jdk1.5.0/jre/lib/sparcv9:/usr/jdk/instances/jdk1.5.0/jre/../lib/sparcv9
envp[3]: LC_COLLATE=es_ES.ISO8859-15
envp[4]: LC_CTYPE=es_ES.ISO8859-15
envp[5]: LC_MESSAGES=es
envp[6]: LC_MONETARY=es_ES.ISO8859-15
envp[7]: LC_NUMERIC=es_ES.ISO8859-15
envp[8]: LC_TIME=es_ES.ISO8859-15
envp[9]: PATH=/opt/www/jmemcached/bin:/usr/sbin:/usr/bin:/usr/ccs/bin:/usr/ucb
envp[10]: SMF_FMRI=svc:/application/cache/jmemcached:jmemcached_main
envp[11]: SMF_METHOD=/lib/svc/method/jmemcached start
envp[12]: SMF_RESTARTER=svc:/system/svc/restarter:default
envp[13]: TZ=Europe/Madrid
# pargs -a 5971
5971:   /usr/jdk/instances/jdk1.5.0/bin/sparcv9/java -Xms512m -Xmx512m -jar /opt/www/jm
argv[0]: /usr/jdk/instances/jdk1.5.0/bin/sparcv9/java
argv[1]: -Xms512m
argv[2]: -Xmx512m
argv[3]: -jar
argv[4]: /opt/www/jmemcached/jmemcached-cli-0.8-main.jar
argv[5]: -p11212
argv[6]: -m256M
# pargs -l 5971
/usr/jdk/instances/jdk1.5.0/bin/sparcv9/java -Xms512m -Xmx512m -jar /opt/www/jmemcached/jmemcached-cli-0.8-main.jar -p11212 -m256M 

 Referencias

viernes, 5 de marzo de 2010

Cómo saber en que RunLevel estamos y Último Boot

Introducción
El comando <who> nos permite además de saber quién está conectado, ver en qué Run Level nos encontramos, cuándo se ha modificado la fecha del sistema y cuando fue el último reboot, entre otras. A continuación vamos a ver algunos ejemplos de este interesante comando:

Saber el Último Reboot, opción <-b>
# who -b
   .       system boot  nov 25 13:30
Saber el RunLevel actual, opción <-r>
# who -r
   .       run-level 3  nov 25 13:32     3      0  S
Saber los cambios a la fecha del sistema, opción <-t>
En este ejemplo, vamos a cambiar la fecha, primero a las 11:55:00 y luego a 11:55:10. Con esta opción, veremos sólo los cambios producidos con el comando <date>, no las sincronizaciones de Reloj
# date 1155.00
jueves  4 de marzo de 2010 11H55'00" CET
# date 1155.10
jueves  4 de marzo de 2010 11H55'10" CET
# who -t
   .       old time     mar  4 11:55
   .       new time     mar  4 11:55
Referencias

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

lunes, 1 de marzo de 2010

Instalar Apache HTTP server con Gestión Dinámica de Recursos

Introducción
En post anteriores hemos visto como podemos Gestionar Dinámicamente Procesos usando Projects, sin embargo, cuando hablamos de Instalar Apache HTTP Server tenemos que realizar algunos cambios para poder utilizarlos.

El problema viene por la forma de ejecutarse de Apache HTTP Server. Éste realiza un setuid al usuario configurado en la propiedad <User> y <Group> del archivo $APACHE_HOME/conf/httpd.conf y por lo tanto, no se produce un nuevo proceso <newtask>, así que los parámetros de configuración dinámica se heredan del proceso padre, en nuestro caso es <root>.

Veamos un ejemplo para explicarlo mejor -asumimos que tenemos instalado nuestro Apache HTTP en /opt/www/apache-1.3.41 tiene configurado como User y Group www. Vamos a crear un nuevo project para el usuario www y veremos qué sucede

# vi /opt/www/apache-1.3.41/conf/httpd.conf
  ...
  Port 80
  User www
  Group www
  ...

# projadd -G www -c 'Apache 1.3.x HTTP Server' user.www
# /opt/www/apache-1.3.41/bin/apachectl stop
/opt/www/apache-1.3.41/bin/apachectl stop: httpd stopped
# /opt/www/apache-1.3.41/bin/apachectl start
/opt/www/apache-1.3.41/bin/apachectl start: httpd started
# ps -u www -o project,comm
 PROJECT COMMAND
user.root /opt/www/apache-1.3.41/bin/httpd
user.root /opt/www/apache-1.3.41/bin/httpd
user.root /opt/www/apache-1.3.41/bin/httpd
user.root /opt/www/apache-1.3.41/bin/httpd
user.root /opt/www/apache-1.3.41/bin/httpd
Como podemos ver, nuestro servidor está utilizando el project <user.root> en vez del que nosotros queremos que es <user.www>, para solucionarlo, deberemos editar el archivo $APACHE_HOME/bin/apachectl y modificar la forma de inicio de nuestro servidor.

Deberemos incluir el siguiente bloque de código justo antes de <for ARG in $@ $ARGS> de forma que quede así
# vi /opt/www/apache-1.3.41/bin/apachectl
...
...
## Project Name
PROJNAME="user.www"
NEWTASKBIN=`which newtask`
PROJEXITS=`cat /etc/project |grep $PROJNAME`

if [ "x$PROJEXITS" != "x" ] ; then
        ## Support for Custom Project
        HTTPD="$NEWTASKBIN -p $PROJNAME $HTTPD"
fi


for ARG in $@ $ARGS
do
    # check for pidfile
    if [ -f $PIDFILE ] ; then
        PID=`cat $PIDFILE` 
...
...
...
Y con este cambio, reiniciamos nuestro Apache HTTP Server y comprobamos que project tiene asignado ahora.

# /opt/www/apache-1.3.41/bin/apachectl stop
/opt/www/apache-1.3.41/bin/apachectl stop: httpd stopped
# /opt/www/apache-1.3.41/bin/apachectl start
/opt/www/apache-1.3.41/bin/apachectl start: httpd started
# ps -u www -o project,comm
 PROJECT COMMAND
user.www /opt/www/apache-1.3.41/bin/httpd
user.www /opt/www/apache-1.3.41/bin/httpd
user.www /opt/www/apache-1.3.41/bin/httpd
user.www /opt/www/apache-1.3.41/bin/httpd
user.www /opt/www/apache-1.3.41/bin/httpd
Ahora, ya podemos asignar los parámetros dinámicos como deseemos, por ejemplo, Número máximo de descriptores abiertos

# projmod -sK 'process.max-file-descriptor=(priv,2048,deny)' user.www
Conclusión
Teniendo en cuenta la forma de trabajo de la gestión dinámica de recursos, podemos con unos mínimos cambios, obtener este beneficio en prácticamente todas nuestras aplicaciones, con la potencia y simplicidad que esto supone

Referencias