Apache: Balanceo de Tomcats con mod_proxy_ajp

Desde Apache 2.2 disponemos de un módulo nativo (mod_proxy_ajp) para implementar proxies inversos con AJP, desarrollado por el propio Apache. Esto hasta ahora lo habíamos venido realizando con mod_jk, que se distribuía con el propio Tomcat. Os dejo un ejemplo que usé para balancear una aplicacion hacia tres tomcats.

<VirtualHost *:80>
ServerName archivo.prueba.es
ServerAlias archivo


CustomLog /var/log/httpd/archivo.log combined

# Preservar las cabeceras anteriores, y
# evitar que el proxy las modifique
ProxyPreserveHost On

# Montar URLs hacia el cluster
ProxyPass /archivo balancer://archidoc_cluster/archivo tickysession=JSESSIONID nofailover=On

# Definir el proxy hacia los Tomcats
<Proxy balancer://archidoc_cluster>
BalancerMember ajp://tomcat1:8509
BalancerMember ajp://tomcat2:8509
BalancerMember ajp://tomcat3:8509
</Proxy>


# Redireccion para que vaya directamente al Tomcat
RewriteEngine on
RewriteRule ^$ /archivo/ [R,L]
RewriteRule ^/$ /archivo/ [R,L]

AddDefaultCharset ISO-8859-1
</VirtualHost>

La verdad que tampoco está muy claro cuando es recomendable usar uno u otro: Yo sólo lo he usado cuando he tenido problemas con alguna aplicación y mod_jk, que siempre es mi primera elección, simplemente por madurez del proyecto.

La foto la he sacado del album de Darny en flickr

SmbWebClient

SmbWebClient es un cliente Samba implementado en un único PHP, que permite colocar nuestros Shares de Samba accedibles vía Web. Esto permite que nuestros usuarios puedan acceder a los ficheros de sus unidades de Intranet a través de Internet.

La instalación es muy sencilla, basta con descomprimir el fichero en una carpeta de nuestro servidor Web que tenga instalado PHP y el cliente de Samba. Si tiene algún incoveniente esta herramienta, es su simplicidad y que modificarla resulta tedioso porque todo lo que usa (iconos y plantillas thtml) están embebidos en BASE64 dentro del propio código. Así, cosas sencillas como cambiar el icono de las carpetas o personalizar el HTML, nos obliga a andar descodificando y codificando en Base64 todo.

Auditoría en OpenLDAP

Desde hace tiempo vengo implantando OpenLDAP para poner en marcha proyectos de gestión de la identidad en organizaciones. La principal ventaja que nos aporta el uso de software libre para estos proyectos, es la posibilidad de retocar el código fuente y desarrollar overlays que nos permitan extender las funcionalidades que traen de serie, pudiendo adaptar así la solución a las necesidades del cliente y generar una solución óptima para él a un precio adsequible.

Estos proyectos, casi siempre se centran en la provisión de cuentas de acceso centralizada y automatizada: Desde OpenLDAP hacia otros sistemas como eDirectory, Active Directory, Oracle, Linux, etc. Para ello se suelen relajar las políticas de cuenta, dado que no siempre se tienen las mismas posibilidades de configuración en los distintos sistemas ni se implementan de la misma manera. Al final, esto degenera en que las contraseñas de las cuentas de usuario no poseen ninguna complejidad y las conservan por los tiempos de los tiempos.

Esta situación se puede corregir con el uso de políticas en OpenLDAP a partir de la versión 2.3. Para acctivarlas tendremos que editar el fichero de configuración de nuestro servidor OpenLDAP y aplicar los siguientes cambios:

  1. Incluir el esquema de definición de políticas
    include       /etc/openldap/schema/ppolicy.schema
  2. Añadir el módulo:
    modulepath    /usr/lib64/openldap
    moduleload ppolicy.la
  3. Indicar el objeto que contendrá la política de nuestro directorio, justo después de la definición del backend de la base de datos que usaremos.
    overlay         ppolicy
    ppolicy_default "cn=defaultpwpolicy,dc=DOMINIO

Reiniciar el servicio para aplicar los cambios. Crear un fichero LDIF con el siguiente contenido que será nuestra política de seguridad:
dn: cn=defaultpwpolicy,dc=DOMINIO
cn: defaultpwpolicy
objectClass: top
objectClass: device
objectClass: pwdPolicy
pwdAttribute: userPassword
pwdAllowUserChange: TRUE
pwdMustChange: FALSE

La añadiremos al directorio...
ldapadd -x -h localhost -D "cn=admin,dc=DOMINIO" -w CLAVE -f politica.ldif

Esta política es muy sencillita y permisiva: Solo nos sirve para mantener en el campo pwdChangedTime cuándo se cambió por última vez la contraseña (userPassword) el usuario en LDAP. Podemos encontrar todas las opciones en la página man de salpo-ppolicy, y añadir complejidad a las contraseñas, duración, bloqueo después de intentos fallidos, etc.
La foto la he sacado del album de treevis en flickr

Réplicas OpenLDAP con SyncRepl

Todos los que hemos usado OpenLDAP desde hace tiempo como software para desplegar nuestros servicios de directorio, hemos venido sufriendo el problema de las réplicas en los esclavos para mantener la alta disponibilidad. La solución con la que contábamos era el uso de SLURPD, un pequeño demonio que se ejecutaba en el servidor con el LDAP maestro. Cada operación que se realizaba en el directorio se anotaba en un fichero de texto plano junto a la hora, y el demonio iba aplicando los cambios del fichero en cada una de las réplicas. Este proceso era bastante inestable, porque asumía siempre que la replica estaba en un estado determinado, y a partir de él aplicaba cambios. Esto no siempre era así, porque podíamos haber parado la réplica o haberla recuperado de un backup, y al final teníamos que nunca estábamos completamente seguros del estado de nuestras réplicas hasta que parábamos todo el directorio, y copiábamos a mano la base de datos del maestro en cada una de las réplicas. Teníamos demasiadas paradas en un servicio siempre importante, y el proceso SLAPD solía estar siempre en la cima del top comiendo toda la CPU que podía, sin contar las veces que el demonio SLURPD moría por causas desconocidas.

Por suerte con la versión 2.3 de OpenLDAP aparece un nuevo mecanismo de sincronización del directorio basado en un overlay y llamado SyncRepl. Este mecanismo lo que hace es escribir en cada modificación un timestamp con la hora a la que se realizó y se guarda en la propia base de datos dentro de los atributos del objeto modificado, y además mantiene un timestamp global que contiene el valor para la última modificación. Las réplicas ahora, no esperan a que el maestro les envíe las modificaciones sino, que se conectan contínuamente al maestro y le preguntan por el valor globlal: Lo comparan con el que ellas tienen anotado y solicitan todos los objetos comprendidos entres estos dos timestamp para modificarlos en la base de datos local. Este mecanismo en mucho más robusto, y aporta tranquilidad a la vida de los administradores de OpenLDAP.

Para configurarlo tendremos que:

  1. Editar la configuración del maestro y añadir la configuración de SyncRepl a justo después de la definición de nuestro backend
    overlay     syncprov
    syncprov-checkpoint 100 10
    syncprov-sessionlog 100
    lastmod on
  2. Editar la configuración del esclavo y añadir la configuración de SyncRepl a justo después de la definición de nuestro backend, como hicimos para el maestro, y además añadir al final cómo conectar con el LDAP que hace de maestro:
    # Configurar el proveedor... (nuestro master)
    syncrepl rid=001
    provider=ldap://__IP_MAESTRO_LDAP__:389
    type=refreshAndPersist
    retry="60 +"
    searchbase="dc=DOMINIO"
    filter="(objectClass=*)"
    scope=sub
    attrs="*,+"
    schemachecking=off
    bindmethod=simple
    binddn="cn=admin,dc=DOMINIO"
    credentials=CLAVE_DEL_ADMIN

    updateref ldap://__IP_MAESTRO_LDAP__:389
  3. Añadir índices para los campos entryCSN y entryUUID, en la sección de índices del fichero de configuración de los LDAPs. Estos campos es donde SyncRepl va anotando las modificaciones.
    index entryCSN,entryUUID        eq

Después de aplicar estos cambios, tendremos que reconstruir la base de datos del maestro, con el fin de que se creen todos los objetos con estos campos reservados. Luego regenerar los índices de la base de datos con slapindex, y copiarla a los nodos esclavos para que arranquen en un estado sincronizado.

La foto la he sacado del album de Michael Dawes en flickr

OSSEC

OSSEC es un detector de intrusos basado en nodo (HIDS, Host-based Intrusion Detection System) open source que lleva a cabo las siguientes funciones: análisis de registros, comprobación de integridad, detección de rootkits, alertas basadas en secuencias temporales y respuesta activa , capaz de ejecutarse en cliente/servidor y que funciona en Windows, Linux, MacOs. Es una especie de evolución de Tripwire. Otra de las ventajas que presenta OSSEC es que la base de datos de firmas MD5 no se almacena en el equipo cliente, sino que se lleva a un servidor centralizado, por lo que si un cliente queda comprometido, las firmas no quedan comprometidas.

Para configurar los equipos linux con el Agente de OSSEC se seguirán la siguiente secuencia de pasos:

  1. Conectarse por SSH al servidor OSSEC de la sonda donde conectaremos el cliente, como root.
  2. Desde la consola del servidor OSSEC, ejecutaremos el comando /var/ossec/bin/manage_agents, y luego nos aparecerá un menú de opciones, donde lo que tenemos que hacer es dar de alta un nuevo agente (A) y luego extraer la clave para él (E). Pasa salir(Q). Cuando nos muestre la clave la copiaremos en un fichero, para poder importarla en el cliente:
    ****************************************
    * OSSEC HIDS v2.1 Agent manager.
    *
    * The following options are available: *
    ****************************************
    (A)dd an agent (A).
    (E)xtract key for an agent (E).
    (L)ist already added agents (L).
    (R)emove an agent (R).
    (Q)uit.
  3. De vuelta a la consola del servidor, reiniciaremos el servicio...
    /etc/init.d/ossec restart

Ahora el siguiente paso será instalar el cliente OSSEC en el equipo que queremos monitorizar, e importar esta clave, para que hable con nuestro servidor Ossec.
  1. Conectarse por SSH al cliente OSSEC como root.
  2. Descargar e instalar el agente en nuestro sistema
  3. Desde la consola del ejecutar el comando /var/ossec/bin/manage_agents, y luego nos aparecerá un menú de opciones, donde lo que tenemos que hacer es importar la clave(I). que habríamos copiado desde el servidor OSSEC. Para salir(Q).
  4. De vuelta a la consola del servidor, reiniciaremos el servicio...
    /etc/init.d/ossec restart

Podemos ver los logs entre el servidor y en el cliente con ejcutando el comando:
tail -f /var/ossec/logs/ossec.log

De vuelta a nuestro servidor, podemos instalar ossec-Web-UI, descargándolo de la Web y luego ejecutar los siguientes comandos para instalarlo:
cd /var/www
tar -xzvf /opt/ossec-wui-0.3.tar.gz
mv ossec-wui-0.3 ossec-wui
bash setup.sh

... cuando nos pregunte responder username=admin y contraseña=pokemon.
usermod -G ossec www-data
/etc/init.d/apache2 restart

Acceder desde el navegador a: http://NUESTRO_SERVIDOR/ossec-wui/

AutoIT

AutoIT es una pequeña utilidad que nos permite escribir scripts para Windows y automatizar ciertas tareas que con VBS o BAT nos costaría mucho trabajo. La síntaxis es similar a la de Visual Basic y lo más interesante es que se compila y genera un fichero .EXE que podemos ejecutar en cualquier equipo sin necesidad de tener AutoIT instalado.

Os dejo un script a modo de ejemplo, que desarrollé para migrar los documentos y carpetas del escritorio de un usuario a un directorio local y así evitar que el perfil móvil del usuario pese demasiado.

;
; Script AUTOIT para mover objetos del escritorio
; a "Mis documentos y crear acceso directorio en
;

; Establecer que si se producen errores fatales no salga del script
Opt("RunErrorsFatal", 0)

; Buscar los archivos del perfil...
$search = FileFindFirstFile(@DesktopDir & "\*")
; Comprobar que se encontró algo...
If $search = -1 Then
; No, no se ha encontrao nada ...:P
Exit
EndIf

; Flag para avisar que se le han movido archivos
$flag=0

; Por cada fichero que se encontró hacer el bucle...
While 1
; Obtener el nombre del fichero ...
$file = FileFindNextFile($search)
; Ver si hemos terminado el bucle
If @error Then ExitLoop
; Obtener los atributos del archivo
$attrs=FileGetAttrib(@DesktopDir & "\"& $file)
; Obtener la extension del archivo
$ext = stringRight( StringLower($file), 4)
; Por extension o en caso de que sea un directorio...
If (StringInStr($attrs, "D")) or ((NOT($ext == ".lnk")) and (NOT($ext == ".url")) ) Then
If (StringInStr($attrs, "D")) Then
; Tenemos que mover el archivo
DirMove ( @DesktopDir & "\"& $file, @MyDocumentsDir, 1 )
Else
; Tenemos que mover el archivo
FileMove ( @DesktopDir & "\"& $file, @MyDocumentsDir, 8 )
EndIf
; Crear acceso directo en el escritorio...
ShellExecute("\\SRV\NETLOGON\XXMKLINK.EXE",' "' & @DesktopDir & "\" & $file &'.lnk" "' & @MyDocumentsDir & '\' & $file & '"', @UserProfileDir)
$flag=1
EndIf
EndIf
WEnd


Este script se apoya en XXMKLINK que permite crear enlaces simbólicos de Windows.

Apache: Evitar redirecciones indeseadas

A menudo tenemos configurado en nuestros servidores Web Apache, VirtualHosts que usan mod_rewrite para modificar algunas peticiones y dirigirlas a otras URLs. Esto puede ser aprovechado por un atacante para evitar el baneo de la pertenencia a listas negras. Podemos hacer una comprobación sencilla ejecutando telnet NUESTRO_SERVIDOR 80 y luego escribir:

GET http://l25.member.re3.yahoo.com/config/login?login=a-jj&passwd=Monster HTTP/1.0


Si nuestro servidor Web devuelve una respuesta 302, podríamos ser candidatos a ataques mal intencionados. Lo correcto sería que nuestro servidor respondiera con un 403. Para ello, podemos añadir a la configuración de nuestro VirtualHost:
 # Para evitar que nos usen de Salto...
RewriteCond %{HTTP_HOST} !^NOMBREVIRTUALHST
RewriteRule ^(.+) http://NOMBREVIRTUALHST/fallo [F,L]

Donde NOMBREVIRTUALHST es el nombre de nuestro VirtualHost.

La imagen la he sacado del album de rbowen en flickr