miércoles, 19 de septiembre de 2012
Enviar errores 500 cuando el php detecta errores
Hola amiguitos, despues de unos meses de inactividad bloguera vuelvo a vosotros para escribir sobre una problematica con la que seguro más de uno, se ha encontrado.
Esta no es ni más ni menos que el control de los status code que php devuelve ante un error y el cacheo de los mismos cuando no lo deseamos.
Sin más preambulos, al turrón:
Tenemos que distinguir entre dos tipos de errores, los "parser errors", que son los errores detectados en tiempo de compilación por el interprete antes de ser ejecutado el script, como por ejemplo un syntax error y los "fatal error", son errores detectados en tiempo de ejecución, como por ejemplo una funcion que no existe o el include de un fichero que no existe.
Un parser error siempre escupe un 500 Internal Server Error, en cambio un fatar error depende del valor de la variable display_errors. Si display_errors está desacitvada, la valor del script sera un error 500, por el contrario si está activada el error es pintado por pantalla y un 200 Ok es devuelto por el servidor.
Cuando tienes un sistema de caches por delante es bastante importante que esos errores no se cacheen por lo que seria interesante el que el status code cuando un error es detectado sea un 500, ya que el comportamiento normal de un sistemas de caches es no cachear esos codigos.
Para conseguir esto y puesto que no puedes garantizar siempre que a algún desarrollador se le haya colado un display_errors a On en alguna parte del código, lo que proponemos es lo siguiente.
En el php.ini existe la directiva auto_prepend_file, en esta directiva le puedes pasar un script php para ser ejecutado antes del php principal.
Para este proposito vamos a configurar esta directiva asi:
auto_prepend_file = /etc/php5/apache2/prepend.php
En contenido de /etc/php5/apache2/prepend.php es el siguiente:
<?php
function my_error_handler_manda_500()
{
$error=error_get_last();
if (!empty($error)) {
header('HTTP/1.1 500 Internal Server Error');
die();
}
}
register_shutdown_function("my_error_handler_manda_500");
?>
Como podemos ver aqui, lo que estamos haciendo es crear una funcion que nos pinta un error 500 en caso de que se haya generado algún error por el php principal. Esta funcion es lanzada desde la funcion de php register_shutdown_function que se ejecuta siempre al finaliar un script.
Para que esto funcione la directiva output_buffering debe estar activada (*) ya que las cabeceras deben ser sobreescritas.
(*) El activar el output_buffering podria llegar a causar al usuario una sensacion inicial de lentitud en la carga de la página ya que lo que hace es almacenar en el buffer todo la pñagina hasta que esta preparada para ser pintada.
domingo, 25 de marzo de 2012
Cassandra cluster, facil facil!!
La verdad que como con todas las cosas, eres libres de complicarlas tanto como quieras, pero en este caso complicar la instalación y configuración de un cluster en cassandra es dificil ;).
Para este escenario vamos a suponer que tenemos tres nodos de cassandra:
test01 (192.168.30.21)
test02 (192.168.30.22)
test03 (192.168.30.23)
Es una buena idea que metas estas lineas en el /etc/hosts con todos tus nodos de cassandra ya que a cassandra no le termina de gustar los nombres FQDN:
192.168.30.21 test01
192.168.30.25 test02
192.168.30.26 test03
El siguente paso, como no instalar cassandra, para ello vamos a instalarlo de paqueteria de debian, pero instalar de fuentes es igualmente facil, como requisito necesitas tener instalado java.
Metemos la siguiente linea en el fichero /etc/apt/sources.list:
deb http://www.apache.org/dist/cassandra/debian 10x main
deb-src http://www.apache.org/dist/cassandra/debian 10x main
Ahora al hacer un apt-get update te saltara un error de este tipo:
1 #! /usr/bin/python
2 import sys
3 if (len(sys.argv) > 1):
4 num=int(sys.argv[1])
5 else:
6 num=int(raw_input("How many nodes are in your cluster? "))
7 for i in range(0, num):
8 print 'token %d: %d' % (i, (i*(2**127)/num))
En definitiva en el fichero principal de configuracion /etc/cassandra/cassandra.yaml hay que cambiar la configuracion de las siguientes entradas:
test01:
test02:
test03:
Para este escenario vamos a suponer que tenemos tres nodos de cassandra:
test01 (192.168.30.21)
test02 (192.168.30.22)
test03 (192.168.30.23)
Es una buena idea que metas estas lineas en el /etc/hosts con todos tus nodos de cassandra ya que a cassandra no le termina de gustar los nombres FQDN:
192.168.30.21 test01
192.168.30.25 test02
192.168.30.26 test03
El siguente paso, como no instalar cassandra, para ello vamos a instalarlo de paqueteria de debian, pero instalar de fuentes es igualmente facil, como requisito necesitas tener instalado java.
Metemos la siguiente linea en el fichero /etc/apt/sources.list:
deb http://www.apache.org/dist/cassandra/debian 10x main
deb-src http://www.apache.org/dist/cassandra/debian 10x main
Ahora al hacer un apt-get update te saltara un error de este tipo:
GPG error: http://www.apache.org unstable Release: The following signatures couldn't
be verified because the public key is not available: NO_PUBKEY F758CE318D77295D
Pues bien, apunta la clave publica y lanzas:
gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D gpg --export --armor F758CE318D77295D | apt-key add -
Y:
gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00 gpg --export --armor 2B5C1B00 | apt-key add -
Esta segunda es tal cual te la pego aqui.
Ahora si, hacemos un apt-get update y luego el apt-get install cassandra y ya lo tienes instalado.
Pues bien, ahora para poner en marcha el cluster tenemos que asignar un token a cada uno de los nodos, yo que usado un script en python que te lo calcula en funcion del numero de nodos que le pases, el script son apenas 10 lineas:
1 #! /usr/bin/python
2 import sys
3 if (len(sys.argv) > 1):
4 num=int(sys.argv[1])
5 else:
6 num=int(raw_input("How many nodes are in your cluster? "))
7 for i in range(0, num):
8 print 'token %d: %d' % (i, (i*(2**127)/num))
En definitiva en el fichero principal de configuracion /etc/cassandra/cassandra.yaml hay que cambiar la configuracion de las siguientes entradas:
test01:
cluster_name: 'MyDemoCluster' initial_token: 0 seed_provider: - class_name: org.apache.cassandra.locator.SimpleSeedProvider parameters: - seeds: test01 listen_address: test01 rpc_address: 0.0.0.0 endpoint_snitch: org.apache.cassandra.locator.RackInferringSnitch
test02:
cluster_name: 'MyDemoCluster' initial_token: 56713727820156410577229101238628035242 seed_provider: - class_name: org.apache.cassandra.locator.SimpleSeedProvider parameters: - seeds: test01 listen_address: test02 rpc_address: 0.0.0.0 endpoint_snitch: org.apache.cassandra.locator.RackInferringSnitch
test03:
cluster_name: 'MyDemoCluster' initial_token: 113427455640312821154458202477256070485 seed_provider: - class_name: org.apache.cassandra.locator.SimpleSeedProvider parameters: - seeds: test01 listen_address: test03 rpc_address: 0.0.0.0 endpoint_snitch: org.apache.cassandra.locator.RackInferringSnitch
Como nota decir que la directiva endpoint_snitch se usa para que cassandra conozca
como está la topologia de red y puede ser SimpleSnitch, RackInferringSnitch o
PropertyFileSnitch.
Apuntar tambien que el seed server es en este caso test01, esto no es ni mas ni menos
el servidor al cual se conectaran los nuevos nodos que añadamos al cluster para actualizar
sus datos en primera instancia, el seed server no es un punto de fallo para el funcionamiento
cotidiano del cluster.
Ahora solo queda jugar!!!
viernes, 16 de marzo de 2012
Problemas de acceso a disco con vmware y debian 6
Hola a todos, despues de casi 11 meses sin escribir ninguna entrada, hoy me he levantado con ganas ... ;)
Ultimamente me ha tocado pelearme mucho (bueno y a mis compañeros también) con herramientas de stress para optimizar el rendimiento del sistema operativo, en nuestro caso el pauperrimo acceso a disco que da la debian 6 cuando está montada sobre un ESX (4.1 o 5).
En nuestro caso en particular hemos usado sysbench. Hay muchas herramientas de este tipo, pero más allá de entrar en debate de cual es mejor o peor, lo importante es realizar los test con de manera homogenea para que los resultados sean lo más reveladores posible.
Bueno, poniendo un poco al personal en antecedentes, nuestra problematica como he dicho anteriormente viene tras detectar el pobre acceso a disco (a los discos locales) que estabamos teniendo en nuestra plataforma, todo en debian 6 sobre ESX 4.1 de VMWARE.
Para realizar el test de disco hemos hecho un script que al final llama al sysbech y nos saca la tasa de transferencia de las operaciones a disco realizadas:
#!/bin/sh
for i in 1 2 8 16 32
do
echo "hilos $i"
for j in 1
do
echo " intento $j"
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 prepare > /dev/null
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 run | grep transferred
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 cleanup > /dev/null
done
echo "___________________"
done
El script como vereis hace 5 veces con 1, 2, 8, 16 y 32 thread simultaneos. Lo normal cuando lanzas el test sobre un disco es que te de menos tasa de transferecia con 1 hilo y que la cosa vaya subiendo a medida que le metes hilos hasta que se estabiliza.
Pues bien la primera cosa que vimos fue que la tasa de transferecia era lineal, es decir, daba aproximadamente la misma tasa de transfercia con 1 hilo que con 32, raro, raro, raro....
La segunda cosa que vimos fue como podeis ver mas abajo que la tasa de transferecia era bajisima, apenas 9MB/s para estar montadas las imagenes de vmware montadas sobre una bandeja de discos en fiber channel de un almacenamiento EMC.
Si quereis saber las IOPS que son 9MBps la formula es facil:
IOPS = (MBps Throughput / KB per IO) * 1024
Aqui KB por IO es 16K que es tamaño de bloque que sysbench usa por defecto en una operacion de entrada/salida
En nuestro caso y siguiendo esa formula son 575 IOPS.
Aqui os pego el test con los resultados:
root@pre1 ~/kk $ /root/bin/benchmark_disk.sh
hilos 1
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.9316Mb/sec)
___________________
hilos 2
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.2897Mb/sec)
___________________
hilos 8
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.8921Mb/sec)
___________________
hilos 16
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.4219Mb/sec)
___________________
hilos 32
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.2804Mb/sec)
Como podeis apreciar, bastante bajo y lineal.
Pues bien, despues de estar persiguiendo este problema con el fabricante, leer mucho al respecto y hacer 1001 pruebas, a uno de nuestros compis se le encendio la bombilla y como por arte de magia cambiando un parametro todo empezo a funcionar a toda velocidad.
Que? Ya os creiais que os iba a dejar asi, sin contaros la solución verdad? ;)
La clave del asunto esta en el scheduler de las colas de acceso al disco. Y os preguntareis que es esto del scheduler, bueno, pues para los que no lo sepais, sin exterme mucho y entrar en demasiados detalles es la forma que tiene el sistema operativo de gestionar de una manera optima las operaciones enviadas al disco.
Esto se hace através de una cola, en debian 6 hay cuatro diferentes (noop, cfq, anticipatory y deadline) , cada una gestiona los accesos al disco de una manera distinta pero como dato deciros que por defecto se suele usar la cfg.
Esta cola lo que hace a groso modo es reorganizar las operaciones de IO en le van llegando de una manera optima para que los movimientos mecanicos del disco sean los menos posibles.
Algunos (los que no se hayan dormido ya) habrán llegado a la conclusión por si solos de que hay determinadas ocasiones en las que no tiene mucho sentido este tipo de comportamiento, como podria ser con discos SSD que no tienen parte mecanica o cuando el acceso al disco se esta gestionando desde otra capa como es en nuestro caso VMWARE.
Pues bien para esto esta la cola de tipo noop, que es la cola más sencilla de las cuatro, es de tipo FIFO y todo lo que entra sale al disco sin ningun tipo de orden que no sea el de prioridad de entrada.
Este parametro lo encontrais aqui:
root@pre1 ~/kk $ cat /sys/block/sdb/queue/scheduler
noop anticipatory deadline [cfq]
Para cambiarlo basta con ejecutar este comando y vereis que el scheduler cambia a noop:
root@pre1 ~/kk $ echo noop > /sys/block/sda/queue/scheduler
root@pre1 ~/kk $ cat /sys/block/sdb/queue/scheduler
[noop] anticipatory deadline cfq
Una vez echo esto repetimos las pruebas con asombrosos resultados:
root@pre1 ~/kk $ /root/bin/benchmark_disk.sh
hilos 1
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.5274Mb/sec)
___________________
hilos 2
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (17.948Mb/sec)
___________________
hilos 8
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (36.151Mb/sec)
___________________
hilos 16
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (39.358Mb/sec)
___________________
hilos 32
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (64.089Mb/sec)
Ahora si que si, la curva crece a medida que le metes hilos y la tasa de transferecia es mucho mayor, llegando a 64MBps (aunque el sysbench ponga Mb en realidad son MB) con unas IOPS de 4096.
Bueno espero con esto arrojar luz sobre este tema que tanto tiempo nos ha hecho perder, mejor dicho invertir, ya que ahora sabemos un poquito más que ayer...
Ciao!!
P.D. Gracias a todo mi equipo que son unos fieras, Oscar, Dani, Rober y Fermin.
Ultimamente me ha tocado pelearme mucho (bueno y a mis compañeros también) con herramientas de stress para optimizar el rendimiento del sistema operativo, en nuestro caso el pauperrimo acceso a disco que da la debian 6 cuando está montada sobre un ESX (4.1 o 5).
En nuestro caso en particular hemos usado sysbench. Hay muchas herramientas de este tipo, pero más allá de entrar en debate de cual es mejor o peor, lo importante es realizar los test con de manera homogenea para que los resultados sean lo más reveladores posible.
Bueno, poniendo un poco al personal en antecedentes, nuestra problematica como he dicho anteriormente viene tras detectar el pobre acceso a disco (a los discos locales) que estabamos teniendo en nuestra plataforma, todo en debian 6 sobre ESX 4.1 de VMWARE.
Para realizar el test de disco hemos hecho un script que al final llama al sysbech y nos saca la tasa de transferencia de las operaciones a disco realizadas:
#!/bin/sh
for i in 1 2 8 16 32
do
echo "hilos $i"
for j in 1
do
echo " intento $j"
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 prepare > /dev/null
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 run | grep transferred
sysbench --num-threads=$i --test=fileio --file-test-mode=rndrd --file-extra-flags=direct --max-requests=10000 cleanup > /dev/null
done
echo "___________________"
done
El script como vereis hace 5 veces con 1, 2, 8, 16 y 32 thread simultaneos. Lo normal cuando lanzas el test sobre un disco es que te de menos tasa de transferecia con 1 hilo y que la cosa vaya subiendo a medida que le metes hilos hasta que se estabiliza.
Pues bien la primera cosa que vimos fue que la tasa de transferecia era lineal, es decir, daba aproximadamente la misma tasa de transfercia con 1 hilo que con 32, raro, raro, raro....
La segunda cosa que vimos fue como podeis ver mas abajo que la tasa de transferecia era bajisima, apenas 9MB/s para estar montadas las imagenes de vmware montadas sobre una bandeja de discos en fiber channel de un almacenamiento EMC.
Si quereis saber las IOPS que son 9MBps la formula es facil:
IOPS = (MBps Throughput / KB per IO) * 1024
Aqui KB por IO es 16K que es tamaño de bloque que sysbench usa por defecto en una operacion de entrada/salida
En nuestro caso y siguiendo esa formula son 575 IOPS.
Aqui os pego el test con los resultados:
root@pre1 ~/kk $ /root/bin/benchmark_disk.sh
hilos 1
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.9316Mb/sec)
___________________
hilos 2
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.2897Mb/sec)
___________________
hilos 8
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.8921Mb/sec)
___________________
hilos 16
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.4219Mb/sec)
___________________
hilos 32
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (9.2804Mb/sec)
Como podeis apreciar, bastante bajo y lineal.
Pues bien, despues de estar persiguiendo este problema con el fabricante, leer mucho al respecto y hacer 1001 pruebas, a uno de nuestros compis se le encendio la bombilla y como por arte de magia cambiando un parametro todo empezo a funcionar a toda velocidad.
Que? Ya os creiais que os iba a dejar asi, sin contaros la solución verdad? ;)
La clave del asunto esta en el scheduler de las colas de acceso al disco. Y os preguntareis que es esto del scheduler, bueno, pues para los que no lo sepais, sin exterme mucho y entrar en demasiados detalles es la forma que tiene el sistema operativo de gestionar de una manera optima las operaciones enviadas al disco.
Esto se hace através de una cola, en debian 6 hay cuatro diferentes (noop, cfq, anticipatory y deadline) , cada una gestiona los accesos al disco de una manera distinta pero como dato deciros que por defecto se suele usar la cfg.
Esta cola lo que hace a groso modo es reorganizar las operaciones de IO en le van llegando de una manera optima para que los movimientos mecanicos del disco sean los menos posibles.
Algunos (los que no se hayan dormido ya) habrán llegado a la conclusión por si solos de que hay determinadas ocasiones en las que no tiene mucho sentido este tipo de comportamiento, como podria ser con discos SSD que no tienen parte mecanica o cuando el acceso al disco se esta gestionando desde otra capa como es en nuestro caso VMWARE.
Pues bien para esto esta la cola de tipo noop, que es la cola más sencilla de las cuatro, es de tipo FIFO y todo lo que entra sale al disco sin ningun tipo de orden que no sea el de prioridad de entrada.
Este parametro lo encontrais aqui:
root@pre1 ~/kk $ cat /sys/block/sdb/queue/scheduler
noop anticipatory deadline [cfq]
Para cambiarlo basta con ejecutar este comando y vereis que el scheduler cambia a noop:
root@pre1 ~/kk $ echo noop > /sys/block/sda/queue/scheduler
root@pre1 ~/kk $ cat /sys/block/sdb/queue/scheduler
[noop] anticipatory deadline cfq
Una vez echo esto repetimos las pruebas con asombrosos resultados:
root@pre1 ~/kk $ /root/bin/benchmark_disk.sh
hilos 1
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (8.5274Mb/sec)
___________________
hilos 2
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (17.948Mb/sec)
___________________
hilos 8
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (36.151Mb/sec)
___________________
hilos 16
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (39.358Mb/sec)
___________________
hilos 32
intento 1
Read 156.25Mb Written 0b Total transferred 156.25Mb (64.089Mb/sec)
Ahora si que si, la curva crece a medida que le metes hilos y la tasa de transferecia es mucho mayor, llegando a 64MBps (aunque el sysbench ponga Mb en realidad son MB) con unas IOPS de 4096.
Bueno espero con esto arrojar luz sobre este tema que tanto tiempo nos ha hecho perder, mejor dicho invertir, ya que ahora sabemos un poquito más que ayer...
Ciao!!
P.D. Gracias a todo mi equipo que son unos fieras, Oscar, Dani, Rober y Fermin.
lunes, 11 de abril de 2011
Cache Multisite
La finalidad de este howto es la dotar a nuestros sites de un sistema
de caches para ahorrar ancho de banda en origen, aumentar el rendimiento
de los sites y protegernos de posibles fallas en los servidores origen,
para ello vamos a utilizar varnish para todo el tema de cacheo de
estaticos y nginx para gestionar el tema de multisite de una manera más
sencilla y eficiente de la que podriamos hacerlo con varnish.
El punto de entrada de la solución es varnish quien atiende al puerto 80 como si del servidor principal se tratara. En el puerto 81 estará corriendo nginx quien redireccionará todas las request que varnish no tenga en cache al servidor origen correcto, mediante proxy_pass.
Primero el fichero de configuración de varnish.
Como se ve en las primeras lineas del fichero de configuración defaul.vcl estamos poniendo como backend el nginx que corre en el puerto 81.
Ahora el fichero de configuración del nginx:
Por último solo nos queda probar que todo funciona como debe.
El punto de entrada de la solución es varnish quien atiende al puerto 80 como si del servidor principal se tratara. En el puerto 81 estará corriendo nginx quien redireccionará todas las request que varnish no tenga en cache al servidor origen correcto, mediante proxy_pass.
Primero el fichero de configuración de varnish.
# Backends backend default { .host = "127.0.0.1"; .port = "81"; } # ACL Purge acl limpia { "localhost"; "10.90.90.0"/24; "10.90.40.0"/24; "10.90.55.0"/24; } sub vcl_recv { # Metemos el X-Forwarder-for set req.http.X-Forwarded-For = client.ip; # Si el backend tarda mucho en generar la pagina sirve el objeto expirado. set req.grace = 2m; # Si el metodo no es el esperado no lo permitimos if (req.request != "GET" && req.request != "HEAD" && req.request != "POST" && req.request != "PURGE") { error 405 "Method Not Allowed"; } # Dejamos pasar el POST sin cachear if (req.request == "POST") { return (pass); } # Filtro de purgado if (req.request == "PURGE") { if (!client.ip ~ limpia) { error 405 "Method Not Allowed"; } return(lookup); } # La autenticacion la dejamos pasar hasta el backend sin cachear if (req.http.Authorization) { /* Not cacheable by default */ return (pass); } # Si la peticion tiene cookie la cacheamos igualmente. if (req.request == "GET" && req.http.cookie) { return(lookup); } return (lookup); } sub vcl_hit { if (!obj.cacheable) { return (pass); } if (req.request == "PURGE") { set obj.ttl = 0s; error 200 "Purged."; } return (deliver); } sub vcl_hash { if (req.http.Accept-Encoding ~ "gzip") { set req.hash += "gzip"; } else if (req.http.Accept-Encoding ~ "deflate") { set req.hash += "deflate"; } } sub vcl_miss { if (req.request == "PURGE") { error 404 "Not in cache."; } } sub vcl_fetch { # Si el backend tarda mucho en generar la pagina sirve el objeto expirado. set beresp.grace = 2m; if (beresp.http.Set-Cookie) { return (deliver); } # No cachear si tenemos autorizacion if (req.http.Authorization) { return(pass); } # No cachear si lo dice cache-control if( beresp.http.Pragma ~ "no-cache" || beresp.http.Cache-Control ~ "no-cache" || beresp.http.Cache-Control ~ "private" || beresp.http.Cache-Control ~ "max-age=0" || beresp.http.Cache-Control ~ "must-revalidate" || beresp.http.Cache-Control ~ "no-store" || beresp.http.Cache-Control ~ "private" ) { return(pass); } return (deliver); } sub vcl_deliver { if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; } else { set resp.http.X-Cache = "MISS"; } return (deliver); } sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; synthetic {" <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>"} obj.status " " obj.response {"</title> </head> <body> <h1>Error "} obj.status " " obj.response {"</h1> <p>"} obj.response {"</p> <h3>Guru Meditation:</h3> <p>XID: "} req.xid {"</p> <hr> <p>Varnish cache server</p> </body> </html> "}; return (deliver);}
Como se ve en las primeras lineas del fichero de configuración defaul.vcl estamos poniendo como backend el nginx que corre en el puerto 81.
Ahora el fichero de configuración del nginx:
user nobody nogroup; worker_processes 1; error_log logs/error.log; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream origen1 { server origen.prueba.com:80; } upstream origen2 { server origen2.example.com:80; } server { listen 81; server_name www.prueba.com; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://origen1; } } server { listen 81; server_name www.example.com; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://origen2; } } }En la configuración del nginx estamos definiendo varios servidores origen en funcion de la request que le esté pasando el varnish.
Por último solo nos queda probar que todo funciona como debe.
miércoles, 6 de abril de 2011
Controlar la actividad de los usuarios con snoopy
A todo Administrador, alguna vez le ha surgido la necesidad de saber quien ha borrado el fichero de turno, si hay algún usuario más listo de la cuenta o por que no, por que mola saberlo.
Pues bien, mediante esta fácil solución podemos conocer los comandos que ha ejecutado un usuario en todo momento.
Para ello necesitamos instalar la librería de snoopy.
Una vez en este punto creamos el script /bin/snoopy_bash con el siguiente contenido y le damos permisos de ejecución (755):
apt-get install snoopyCuando instalas por defecto te mete en /etc/ld.so.preload la linea /lib/snoopy.so, debemos comentarla si no queremos que nuestro sistema este logando sin parar la actividad de todos los usuarios del sistema y cuando digo todos, digo todos, daemon, www-data, tomcat, etc (que en algún caso también podría resultarnos de gran utilidad, pero no es el caso).
Una vez en este punto creamos el script /bin/snoopy_bash con el siguiente contenido y le damos permisos de ejecución (755):
#!/bin/bash # Bash que loga la actividad de los usuario export LD_PRELOAD=/lib/snoopy.so /bin/bash
chmod 755 /bin/snoopy_bashSolo nos queda cambiar el bash por defecto que use el usuario que queremos controlar en el fichero /etc/passwd y ver como todos los comandos que este usuario ejecuta se van quedando en el /var/log/auth.log
pruebas:x:1012:1002::/home/pruebas:/bin/snoopy_bash
domingo, 27 de febrero de 2011
Autenticar Apache contra ldap
1. Tenemos que compilar apache con las siguientes opciones en el configure:
##### Usuario ########
dn: cn=jroman,ou=Usuarios,dc=casa,dc=loc
cn: jroman
sn: Roman
uid: jroman
userPassword: {MD5}/gz+58AqfPH5ekA==
objectClass: inetOrgPerson
objectClass: shadowAccount
objectClass: top
objectClass: posixAccount
gidNumber: 10000
homeDirectory: /home/jroman
uidNumber: 10000
###### Grupo ########
dn: cn=Manager,ou=Grupos,dc=casa,dc=loc
cn: Manager
gidNumber: 10000
objectClass: posixGroup
objectClass: top
3. Ahora vamos a crear un site al cual vamos a acceder autenticando contra el ldap. La autenticacion se va a hacer por grupo, es decir van a poder entrar al site todos los usuarios que tengan como grupo el elegido por el site. Aqui vamos a usar el atributo ldap-attribute.
######## Alias documentacion O'Reilly #######
4. Ahora autenticamos por la pertenencia a una Unidad Organizativa.
######## Alias documentacion O'Reilly #######
5. Si lo que queremos es autenticar por pertenencia a un grupo determinado, creamos un grupo que tenga el objectclass groupOfUniqueNames:
Ahora le decimos al apache que autentique contra ldap y busque los usuario que pertenecen al grupo web:
####### Alias proxy #######
- --enable-authnz-ldap
- --with-ldap
- --enable-ldap
##### Usuario ########
dn: cn=jroman,ou=Usuarios,dc=casa,dc=loc
cn: jroman
sn: Roman
uid: jroman
userPassword: {MD5}/gz+58AqfPH5ekA==
objectClass: inetOrgPerson
objectClass: shadowAccount
objectClass: top
objectClass: posixAccount
gidNumber: 10000
homeDirectory: /home/jroman
uidNumber: 10000
###### Grupo ########
dn: cn=Manager,ou=Grupos,dc=casa,dc=loc
cn: Manager
gidNumber: 10000
objectClass: posixGroup
objectClass: top
3. Ahora vamos a crear un site al cual vamos a acceder autenticando contra el ldap. La autenticacion se va a hacer por grupo, es decir van a poder entrar al site todos los usuarios que tengan como grupo el elegido por el site. Aqui vamos a usar el atributo ldap-attribute.
######## Alias documentacion O'Reilly #######
Alias /libreria "/DATA/proyects/libreria" <Directory "/DATA/proyects/libreria"> Options -Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all AuthType Basic AuthName "Secure Area" AuthBasicProvider "ldap" AuthzLDAPAuthoritative Off AuthLDAPURL "ldap://localhost:389/ou=Usuarios,dc=casa,dc=loc?uid" Require ldap-attribute gidNumber=10000 </Directory>
4. Ahora autenticamos por la pertenencia a una Unidad Organizativa.
######## Alias documentacion O'Reilly #######
Alias /libreria "/DATA/proyects/libreria" <Directory "/DATA/proyects/libreria"> Options -Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all AuthType Basic AuthName "Secure Area" AuthBasicProvider "ldap" AuthzLDAPAuthoritative Off AuthLDAPURL "ldap://localhost:389/ou=Usuarios,dc=casa,dc=loc?uid" Require valid-user </Directory>
5. Si lo que queremos es autenticar por pertenencia a un grupo determinado, creamos un grupo que tenga el objectclass groupOfUniqueNames:
dn: cn=web,ou=Grupos,dc=casa,dc=loc objectClass: groupOfUniqueNames uniqueMember: cn=jroman,ou=Usuarios,dc=casa,dc=loc uniqueMember: cn=admin,ou=Usuarios,dc=casa,dc=loc
Ahora le decimos al apache que autentique contra ldap y busque los usuario que pertenecen al grupo web:
####### Alias proxy #######
Alias /proxy "/DATA/proyects/proxy" <Directory "/DATA/proyects/proxy"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order allow,deny Allow from all AuthType Basic AuthName "Secure Area" AuthBasicProvider "ldap" AuthzLDAPAuthoritative Off AuthLDAPURL "ldap://localhost:389/dc=casa,dc=loc?uid" Require ldap-group cn=web,ou=Grupos,dc=casa,dc=loc </Directory>############################################
viernes, 11 de febrero de 2011
OpenVPN con certificados
Introducción
Para crear las vpn de cliente, necesitamos tener una entidad
certificadora para generar los certificados de cliente y servidor, que
en nuestro caso estará en Server1 y el software openvpn instalado en las
máquinas. Los certificados para la vpn estarán en /opt/certificados/keys.
Para las vpn de los clientes generaremos un certificado por cada uno de ellos, debido a que necesitamos poder asignar IPs fijas a cada cliente, y esto se consigue mediante un certificado único por cliente.
Para las vpn de los clientes generaremos un certificado por cada uno de ellos, debido a que necesitamos poder asignar IPs fijas a cada cliente, y esto se consigue mediante un certificado único por cliente.
Creación de la entidad cerificadora
- Para la creación de la entidad certificadora, en el directorio /opt/certificados de la máquina que hara las veces de CA, copiamos el contenido de /usr/share/doc/openvpn/examples/easy-rsa/ a /opt/certificados.
- El siguiente paso es modificar el fichero vars con los datos correspondientes.
export KEY_COUNTRY=es export KEY_PROVINCE=Madrid export KEY_CITY=Madrid export KEY_ORG="Miempresa" export KEY_EMAIL="sistemas@miempresa.com"
- Cargamos las variables de entorno, lanzamos la limpieza de certificados y generamos la CA.
. ./vars ./clean-all ./build-ca
Generación de certificados y clave para el servidor
- Para la generación del certificado de servidor hay que lanzar el siguiente comando:
./build-key-server server
Generación de certificados de cliente
- En el caso de las vpn de los clientes tenemos que repetir este proceso por cada cliente, por que como hemos comentado arriba, las servoapp necesitan de una IP fija para su monitorización y el proceso de recuperación de datos del cliente.
./build-key cliente1 root@baco /opt/certificados $ ./build-key cliente1 Generating a 1024 bit RSA private key ......................++++++ ..........................................................++++++ writing new private key to 'cliente1.key' ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [es]: State or Province Name (full name) [Madrid]: Locality Name (eg, city) [Madrid]: Organization Name (eg, company) [Miempresa Cliente]: Organizational Unit Name (eg, section) []:sistemas Common Name (eg, your name or your server's hostname) []:cliente1 Email Address [sistemas@miempresa.com]: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Using configuration from /opt/certificados/openssl.cnf Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows countryName :PRINTABLE:'es' stateOrProvinceName :PRINTABLE:'Madrid' localityName :PRINTABLE:'Madrid' organizationName :PRINTABLE:'Miempresa Cliente' organizationalUnitName:PRINTABLE:'sistemas' **commonName :PRINTABLE:'cliente1'** emailAddress :IA5STRING:'sistemas@miempresa.com' Certificate is to be certified until Dec 6 11:27:35 2017 GMT (3650 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
- Es muy importante a la hora de generar el certificado de cliente el campo commonName ya que deberemos crear un fichero con ese mismo nombre dentro de /etc/openvpn/ccd para que openvpn asigne una IP fija a ese cliente.
Generación Diffie Hellman
./build-dh
Fichero de configuración
Un vez generados los certificados y la CA (/opt/certificados/keys),
debemos copiar al directorio /etc/openvpn/ del servidor, los siguientes ficheros:
Para la configuración de la vpn del lado del cliente , necesitaremos enviar los ficheros:
- ca.crt
- server.crt
- server.key
- dh1024.pem
port 1194 proto tcp dev tun ca server/ca.crt cert server/server.crt key server/server.key dh server/dh1024.pem server 10.0.0.0 255.255.255.0 ifconfig-pool-persist ipp.txt client-config-dir ccd keepalive 10 120 comp-lzo user nobody group nogroup persist-key persist-tun status openvpn-status.log verb 3
- En la directiva “client-config-dir ccd” espeficicamos a openvpn que lea cualquier fichero contenido en este directorio que coincida con el commonName del certificado de cliente. Por ejemplo, hemos creado un fichero llamado cliente1 que contiene la linea:
ifconfig-push 10.0.0.250 10.0.0.1De esta manera le decimos a openvpn que reserve esta IP para el certificado de cliente cliente1, siendo 10.0.0.250 la IP asignada al cliente y 10.0.0.1 la IP que tiene el servidor.
Para la configuración de la vpn del lado del cliente , necesitaremos enviar los ficheros:
- ca.crt
- cliente1.crt
- cliente1.key
client dev tun proto tcp remote 80.25.33.194 1194 resolv-retry infinite nobind persist-key persist-tun ca servotic_cliente/ca.crt cert servotic_cliente/cliente1.crt key servotic_cliente/cliente1.key comp-lzo verb 3
Suscribirse a:
Entradas (Atom)