martes, 28 de mayo de 2013

Problemas de bloqueo en Drupal con Load Balancer de Amazon

La versión 7 de Drupal, trae como característica el bloqueo de ataques de fuerza bruta, es decir, cuando una IP falla el login, Drupal mete la IP en la tabla ‘flood’ de MySQL; cuando se llega a X intentos, Drupal bloquea el acceso a dicha IP y no podrá volver a hacer login en X tiempo (todo esto es configurable en settings.php).


Dicha característica está muy bien cuando el frontal web está de cara al público y no se encuentra tras un Proxy o Balanceador, en este último caso, dicha “feature” se puede convertir en un infierno, ya que los intentos fallidos para Drupal, se muestran con la IP interna del Proxy o Balanceador y esto puede provocar, que si hay un bloqueo por intentos fallidos, absolutamente tooooodos los usuarios de Drupal, estén donde estén, sean bloqueados y no puedan hacer login en la aplicación.


La ñapa de esto, es hacer un ‘TRUNCATE’ de la tabla flood, al vaciarla, se volverá a acceder.


La solución a esto, es utilizar la variable X-FORWARDED-FOR para que Drupal vea exactamente la ip origen del cliente y bloquee correctamente las IPs (toda la info de esta variable se encuentra en el settings.php).


Ahora demos una vuelta de tuerca más, si la web está tras un Proxy o un Balanceador, tendremos todas sus IPs y será fácil de configurar, pero que pasa, si nuestro Drupal está en una instancia tras un Load Balancer de Amazon.


Pues que tenemos un problema.


Amazon es muy divertido y bonito para muchas cosas, pero como esas cosas son suyas, hay elementos a los que les cambia la IP como le apetece y cuando le apetece.


Por otro lado, todos podemos conocer la IP pública de un Balanceador de Amazon, sin embargo, no podemos saber realmente la IP interna de dicho Balanceador, eso si, nos aparecerá en todos los logs de acceso de las aplicaciones que tengamos y en la tabla ‘flood’ de Drupal, también. XD


Si echáis un vistazo a la configuración de X-FORWARDED-FOR en el settings.php, veréis que nos pide una IP fija, pero no la tenemos.


Gracias al IRC de #drupal-es y a NITEMAN en especial que me atendió y me dio muchísima información, pude sacar la solución.


Esta solución se basa en este link:




Y un poco modificado, hizo que las IPs de origen, fueran realmente las de los clientes, provocando así un bloqueo real de las IPs.


Mi configuración final en el settings.php de Drupal, ha sido la siguiente:


*/Hay que descomentar esta línea y marcarla como TRUE para que active este modo.


$conf['reverse_proxy'] = TRUE;


/**
* Specify every reverse proxy IP address in your environment.
* This setting is required if $conf['reverse_proxy'] is TRUE.
*/
#Se agregan estas líneas para que Drupal no bloquee todos los accesos, ya que solo verificaba la IP interna del balanceador
#Esta línea captura la IP interna del balanceador.


$conf['reverse_proxy_addresses'] = array_map('gethostbyname', array_map('gethostbyaddr', gethostbynamel($_SERVER['REMOTE_ADDR'])));


/**
* Set this value if your proxy server sends the client IP in a header
* other than X-Forwarded-For.
*/
#Esta línea, cambia la IP interna del balanceador por la IP origen del cliente.


$conf['reverse_proxy_header'] = 'HTTP_X_FORWARDED_FOR';


#Información adicional sobre las variables utilizadas:
#Tanto REMOTE_ADDR como HTTP_X_FORWARDED_FOR se ha sacado del acceso a Drupal, en la siguiente ruta
#Informes -> Informe de estado -> PHP ** clikar en "mas información"
#se abrirá el PHPINFO de Drupal y en Apache Environment, tendremos estas variables.
#REMOTE_ADDR tendrá que indicarnos la IP interna del Balanceador
#HTTP_X_FORWARDED_FOR tiene que darnos la IP origen del cliente.


Con estos cambios que hemos realizado, al hacer un login fallido, en la tabla ‘flood’ de Drupal, deberían aparecer las IP origen del cliente.

Espero que os sirva a esos que estáis empezando a implementar Drupal en Amazon con Balanceadores!!

Un saludo a todos.


ACTUALIZACIÓN: Es muy importante, que si utilizáis esto verifiquéis, que el acceso a esta web, solamente se puede hacer a través del balanceador. Si un usuario malintencionado averigua la IP real de la máquina y tiene acceso vía web, puede enviar cabeceras modificadas y hacer cositas con nuestra web.


viernes, 17 de mayo de 2013

Configurar Apache como "proxy" de Tomcat.



Actualmente, cuando instalamos un tomcat, queremos ponerle un apache como “proxy”, el apache recibe las peticiones en el puerto 80 y las redirige a tomcat.

Para ello, instalaremos un apache y un tomcat, y haremos sus configuraciones independientes para que funcionen * y como siempre utilizar las guías básicas de bastionado para que sean seguras.

Una vez hecho eso, habilitaremos los siguientes módulos en apache:

proxy_ajp.load
proxy.conf
proxy.load

Para ello, primero revisaremos que no están ya habilitados.
En la ruta /etc/apache2/ tenemos 2 directorios llamados:

mods-available
mods-enabled

En mods-enabled se encuentran los módulos ya habilitados, si no están los nuestros, iremos al directorio mods-available y los habilitaremos, el comando a utilizar es:

a2enmod [nombre_módulo]

Cada vez que lo habilitemos, nos pedirá reiniciar el apache para activarlos, por lo que cuando finalicemos con todos los módulos, reiniciaremos el apache.

Una vez reiniciado, verificamos en mods-enabled que están nuestros módulos.

Ahora pasaremos a la configuración de la “conexión” entre apache y tomcat, para ello, simplemente en el directorio /etc/apache2/sites-available crearemos el fichero del proyecto que necesitemos y le añadiremos la siguiente información:

       ServerName moni.mandarina.com
       ProxyPass /  ajp://localhost:8009/
       ProxyPassReverse / ajp://localhost:8009/
       ErrorLog ${APACHE_LOG_DIR}/monimandarina_error.log
       LogLevel warn
       CustomLog ${APACHE_LOG_DIR}/monimandarina_access.log combined

Hemos creado un vhost con la url a la que debe responder el servicio, con las líneas ProxyPass y ProxyPassReverse, le estamos indicando que “dirija” la información a tomcat.
Haremos un link simbolico desde sites-enabled hacía el vhost que acabamos de crear.

Ahora recargaremos la información del apache

#/etc/init.d/apache2 reload

Si todo está OK y tenemos nuestras configuraciones bien hechas, deberían funcionar correctamente las aplicaciones de tomcat sobre el puerto 80 y a través de Apache.


PD: Estoy aprendiendo a usar Apache, es posible que me falte algo en la configuración, pero juraría que no.

jueves, 16 de mayo de 2013

Chuleta: Al reiniciar Mysql se queda pensando...


Tenemos que reiniciar el mysql y se queda "cuajado" (como yo digo), vamos al log, y nos encontramos este "error"/"warning":

kernel: [23231693.108005] type=1400 audit(1368692432.585:69): apparmor="STATUS" operation="profile_replace" name="/usr/sbin/mysqld" pid=3703 comm="apparmor_parser"
init: mysql main process (3707) terminated with status 1
init: mysql main process ended, respawning
init: mysql post-start process (3708) terminated with status 1

y sueltas un....mecagoentu****madre la que me has liado!

Que nooo...que no es culpa de MySQL, que es culpa tuya!!

Revisa el fichero /etc/mysql/my.cnf y comprueba que el apartado bind-address no tiene ninguna ip extraña.

Debería tener o 0.0.0.0, localhost, 127.0.0.1, su ip.

Si no es así, pon lo que mas te convenga.

En caso de que esta, no sea tu solución, revisa otros posts como https://www.google.es/search?q=init%3A+mysql+post-start+process+(3708)+terminated+with+status+1&aq=f&oq=init%3A+mysql+post-start+process+(3708)+terminated+with+status+1&aqs=chrome.0.57j58.257j0&sourceid=chrome&ie=UTF-8

miércoles, 15 de mayo de 2013

Configurar Sudo con LDAP y PHPLdapAdmin.


Necesitamos permitir, que los usuarios que accedan por LDAP a los clientes, puedan hacer sudo su en las máquinas.


Para ello, hay 2 formas, o agregamos el usuario al fichero /etc/sudoers de cada máquina cliente o lo hacemos a través del LDAP.


Nosotros lo haremos vía LDAP para tenerlo centralizado.


En primer lugar, accederemos al servidor de LDAP y crearemos el “schema” SUDOers para LDAP en la siguiente ruta:


cd /etc/openldap/schema/
#vi sudo.schema


Agregaremos la siguiente información:


######################################################
###Se crea sudo.schema para que sea el LDAP el que ###
###permita hacer sudo en los hosts del LDAP.        ###
######################################################

attributetype ( 1.3.6.1.4.1.15953.9.1.1
 NAME 'sudoUser'
 DESC 'User(s) who may  run sudo'
 EQUALITY caseExactIA5Match
 SUBSTR caseExactIA5SubstringsMatch
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.2
 NAME 'sudoHost'
 DESC 'Host(s) who may run sudo'
 EQUALITY caseExactIA5Match
 SUBSTR caseExactIA5SubstringsMatch
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.3
 NAME 'sudoCommand'
 DESC 'Command(s) to be executed by sudo'
 EQUALITY caseExactIA5Match
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.4
 NAME 'sudoRunAs'
 DESC 'User(s) impersonated by sudo'
 EQUALITY caseExactIA5Match
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.5
 NAME 'sudoOption'
 DESC 'Options(s) followed by sudo'
 EQUALITY caseExactIA5Match
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.6
 NAME 'sudoRunAsUser'
 DESC 'User(s) impersonated by sudo'
 EQUALITY caseExactIA5Match
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.7
 NAME 'sudoRunAsGroup'
 DESC 'Group(s) impersonated by sudo'
 EQUALITY caseExactIA5Match
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )

attributetype ( 1.3.6.1.4.1.15953.9.1.8
 NAME 'sudoNotBefore'
 DESC 'Start of time interval for which the entry is valid'
 EQUALITY generalizedTimeMatch
 ORDERING generalizedTimeOrderingMatch
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )

attributetype ( 1.3.6.1.4.1.15953.9.1.9
NAME 'sudoNotAfter'
 DESC 'End of time interval for which the entry is valid'
 EQUALITY generalizedTimeMatch
 ORDERING generalizedTimeOrderingMatch
 SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )

attributeTypes ( 1.3.6.1.4.1.15953.9.1.10
  NAME 'sudoOrder'
  DESC 'an integer to order the sudoRole entries'
  EQUALITY integerMatch
  ORDERING integerOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )

objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top AUXILIARY
 DESC 'Sudoer Entries'
 MUST ( cn )
 MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAs $ sudoRunAsUser $ sudoRunAsGroup $ sudoOption $ sudoNotBefore $ sudoNotAfter $ sudoOrder $ description )
      )



Esta información define el esquema del rol SUDOers, si comenzamos desde arriba, veremos todos los atributos de los que disponemos, las últimas líneas, pertenecen al Objeto SudoRole, si os fijáis he puesto AUXILIARY, si buscáis mas info sobre este esquema, encontraréis que pone ESTRUCTURAL, con ambos funciona, pero si usáis PHPLdapAdmin, os recomiendo que pongáis AUXILIARY, ya que si no, hay posibilidades de que el ROL no aparezca para elegirlo, pero si aparecerá en la estructura.


Una vez guardado el fichero, le indicaremos al LDAP su existencia:


#vi /etc/openldap/slapd.conf

include         /etc/openldap/schema/sudo.schema


Reiniciamos el servicio de LDAP:


#/etc/init.d/ldap restart


Aquí es donde si no tenéis PHPLdapAdmin, tendréis que pasaros a otra guía, ya sabéis que no me gusta subir cosas que no he probado.


Pero sólo podrán hacer “sudo su” los usuarios que se encuentren en el grupo SUDOers del LDAP.


Para ello, abriremos el PHPLdapAdmin y crearemos la OU “SUDOers”, una vez creado, agregaremos un nuevo ObjectClass, este será SudoRole, que con los cambios realizados anteriormente, debería aparecer.


Al agregarlo, nos obligará a identificar un CN, este CN sería el nombre del grupo, por decirlo de algún modo.


Ahora podremos agregar los atributos que necesitamos:


sudoCommand
sudoHost
sudoUser
sudoOption


En sudoCommand, pondremos ALL para poder ejecutar cualquier comando, se pueden poner comandos específicos o ![comando] para denegar la ejecución de un comando específico.


En sudoHost, podemos poner ALL para cualquier PC o la ip o nombre del host.


En sudoUser pondremos los nombres de los usuarios que puedan acceder.


En sudoOption podemos indicar que o hace falta password al hacer “sudo su” con un NOPASSWD.




Ya tenemos finalizada la configuración del servidor, ahora pasemos a la de los clientes.


En el cliente, editamos el siguiente fichero:


#vi /etc/ldap.conf


Y agregamos estas líneas al final:


sudoers_base ou=SUDOers,dc=dominio,dc=raíz
#sudoers_debug 2


Con esto, indicamos la ruta de búsqueda de los usuarios que pueden realizar un “sudo su”. La línea de sudoers, la descomentaremos, si tenemos algún problema al realizar el sudo y que nos muestre si la conexión se está realizando correctamente o donde puede estar el fallo.

Con esto se finaliza la configuración de Sudo desde LDAP.

martes, 14 de mayo de 2013

Conf. cliente para usar LDAP.


***Actualmente esta guía es para toda la versión 5 de CentOS***


Necesitamos configurar nuestros equipos clientes y servidores para que el login se realice vía LDAP, ya disponemos del LDAP, por lo que simplemente realizaremos los siguientes cambios en la configuración de los equipos:


Si es posible, se recomienda instalar estos paquetes, para evitar problemas y tener siempre la versión más actualizada (en caso de que no se pudiera, revisar al final del texto las compatibilidades):

#yum install openldap  openldap-clients nss_ldap

Modificaremos los siguientes ficheros:

#vi /etc/sysconfig/autofs

LDAP_URI=”ldap://URLoIPdelServidor”

SEARCH_BASE=”dc=dominio,dc=raiz”         (p.e: “dc=google,dc=com”)

Con esto indicamos la dirección del LDAP y la ruta donde ha de buscar los grupos y usuarios.

Continuamos modificando ficheros:

#vi /etc/pam.d/sshd

session    required     pam_mkhomedir.so skel=/etc/skel/  umask=0022


#vi /etc/pam.d/login

session    required     pam_mkhomedir.so skel=/etc/skel/  umask=0022

Esta modificación en ambos ficheros, permite que al hacer login con un usuario “nuevo”, se genere su home si esta no existe.

Ahora ejecutaremos el siguiente comando, que con la información que le demos, nos configurará automáticamente los ficheros /etc/ldap.conf y /etc/openldap/ldap.conf:

#authconfig-tui
- Marcaremos:
* Utilizar LDAP
* Utilizar contraseña MD5
* Utilizar contraseñas ocultas (shadow)
* Utilizar Autenticación LDAP
- Vamos a Siguiente:
* Servidor: ldap://URLoIPdelServidor
* DN base: dc=dominio,dc=raíz
Al finalizar, si revisamos los ficheros /etc/ldap.conf y /etc/openldap/ldap.conf podremos comprobar que se han añadido estas líneas.

Para ir finalizando, agregaremos el servicio nscd al inicio:

chkconfig --add nscd
chkconfig nscd on

# chkconfig --list |grep nscd
nscd            0:desactivado 1:desactivado 2:activo 3:activo 4:activo 5:activo 6:desactivado

Y reiniciaremos los siguientes servicios:

#/etc/init.d/autofs restart
#/etc/init.d/nscd restart

Si ahora intentamos logarnos con un usuario del LDAP, deberíamos poder acceder sin problemas.

Puede ser, que en alguna máquina nos muestre el siguiente error “This account is currently not available.”
Esto puede deberse a que en el local de la máquina esté nuestro usuario y esté configurado como /sbin/nologin, para ello, cambiaremos esto por un /bin/bash:

#usermod -s /bin/bash NombreUsuario

Como comentario final, indicar que esto es una guía básica, ya que vosotros deberíais tener el LDAP en modo seguro, eso implica que a los clientes tienes que copiarles los certificados del servidor LDAP e indicarlo en los ficheros /etc/ldap.conf y /etc/openldap/ldap.conf
Sobre esta configuración si que hay 200.000 guías, así que seguidlas, por que yo he juntado diferentes guías para montar estos posts.

viernes, 3 de mayo de 2013

Script para que otros puedan ver tus Snapshots.



Una de las cosas molonas que tiene Amazon, es que los snapshots que hagas, los puedes compartir, gráficamente haces click derecho sobre el snapshot -> Snapshots permissions  y añades el id de la cuenta de Amazon con la que quieres compartir este Snapshot.

Pero........
que pasa si tienes un script para que genere los snapshots automáticamente y quieres que se agreguen estos permisos automágicamente.....

Simplemente añadir estas líneas al script:

#Se agregan permisos de otro id de amazon a los 2 últimos snapshots creados.
SNAP_ID=`/opt/api-tools/bin/ec2-describe-snapshots | sort -k5 | (head -5 |tail -1) |awk '{printf $2}'`
/opt/api-tools/bin/ec2-modify-snapshot-attribute $SNAP_ID  -c --add id-cuenta-amazon


Lo que hace es, describir los snapshots que hay hechos, los ordena por fecha y coge el id del snapshot que se encuentra en la última línea, en mi caso suele haber 5 snapshots (head -5), en el caso de que tengáis mas o menos tendréis que modificar ese 5 por el número que os vaya mejor.

Ese id que ha cogido, lo mete en la variable SNAP_ID, que usamos en la siguiente línea, esto lo que hace es ejecutar el comando para agregar permisos, al id del snapshot correspondiente y da permisos al id de la cuenta de Amazon que queramos.

Si mejoro el script, automatizándolo mas todavía, lo actualizo.

Un saludo!!