# rm-rf.es | Administración de sistemas

Bitácora personal de un SysAdmin Gnu/Linux, Windows, BSD...

Instalar y utilizar Apache JMeter sin GUI


Apache jmeterHoy vamos a ver los pasos necesarios (muy sencillos) para instalar y utilizar Apache JMeter sin GUI (entorno gráfico) en sistemas Red Hat, CentOS, etc.

JMeter es un proyecto de Apache Jakarta que puede ser utilizado como una herramienta de prueba de carga para analizar y medir el desempeño de una variedad de servicios, con énfasis en aplicaciones web.

Wikipedia

Lo primero es conocer las dependencias de JMeter, en este caso tenemos que instalar JDK, ya que funciona a través de java. Lo hacemos instalando la versión disponible desde yum o si queremos alguna concreta bajandola desde el sitio web de java:

# yum install java-1.6.0-openjdk.x86_64

Una vez instalado java, verificamos la versión y que es compatible (libre de bugs) con la versión de JMeter que vamos a utilizar:

# java -version
java version "1.6.0_22"
OpenJDK Runtime Environment (IcedTea6 1.10.6) (rhel-1.43.1.10.6.el6_2-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b11, mixed mode)

Pasamos entonces a bajar JMeter, en lugar de compilarlo, podemos bajar directamente los binarios precompilados, de modo que únicamente tengamos que descomprimirlo y tunear un poco algún parámetro para poder empezar a utilizarlo:

# wget http://apache.rediris.es//jmeter/binaries/apache-jmeter-2.6.tgz
# wget http://apache.rediris.es//jmeter/binaries/apache-jmeter-2.6.tgz.asc
# wget http://www.apache.org/dist/jmeter/KEYS

Importamos las keys de Apache para verificar la integridad del archivo descargado:

# gpg --import KEYS
# gpg --verify apache-jmeter-2.6.tgz.asc

Y ya podemos descomprimir y utilizar JMeter:

# tar -xzvf apache-jmeter-2.6.tgz
# mv apache-jmeter-2.6 /usr/local/jmeter
# cd /usr/local/jmeter/

Para un uso básico, simplemente especificamos que no vamos a utilizar GUI (-n), el plan a ejecutar (-t) y el log donde almacenar los resultados (-l):

# /bin/jmeter -n -t plans/miplandepruebas.jmx -l plans/registro_pruebas.log

Un problema común es tener problemas de memoria al ejecutar el plan, ya que los recursos asignados son insuficientes. Para modificarlo, editamos el fichero jmeter y aumentamos los límites de memoria en la variable HEAP, siempre en relación a los recursos de los que dispongamos:

# vi bin/jmeter
# This is the base heap size -- you may increase or decrease it to fit your
# system's memory availablity:
#HEAP="-Xms512m -Xmx512m"
HEAP="-Xms4096m -Xmx4096m"

Otro problema común es el de los límites de ficheros abiertos (open files) especificados en ulimit, sobre todo para pruebas de estrés importantes, deberemos adecuarlo según necesidades igualmente para la sesión en la que ejecutamos las pruebas:

# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 95066
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Apache: permitir acceso a un directorio con autenticación para una IP / CIDR


ApacheEn su día, en el artículo de trucos sobre .htaccess vimos como configurar la autenticación (solicitando usuario y password) para un directorio dentro de un website (o para el website completo). En este caso lo que vamos a hacer es proteger un directorio pero excluir una IP o rango CIDR para que pueda acceder al mismo saltando esta protección.

Partimos de la base de que tenemos configurado en nuestro website, dentro del fichero .htaccess (o a nivel de virtualhost) la autenticación para todos los usuarios:

AuthType Basic
AuthName “Prompt”
AuthUserFile /var/webs/test.com/.htpasswd
Require valid-user

Ahora queremos que todos los visitantes se autentiquen excepto los que provengan de la IP 192.168.1.128:

AuthType Basic
AuthName “Prompt”
AuthUserFile /var/webs/test.com/.htpasswd
Require valid-user
Order allow,deny
allow from 192.168.1.128
satisfy any

La directiva satisfy any permite, tanto para la autenticación como el acceso, que en el momento que se cumpla uno de los requerimientos se permita la petición, haciendo así bypass de la autenticación. Si por el contrario, se quisiera que se cumplieran todos los requerimientos para acceder usaríamos satisfy all.

Podríamos tambien permitir rangos completos, denegar a IPs o CIDR, etc

allow from 192.168.1
allow from 192.168.1.0/24
...

SSLCertificateFile: file certificado.crt does not exist or empty


En caso de recibir este error tras realizar una instalación de un certificado SSL en un servidor web Apache debemos revisar (en RHEL, CentOS, Scientific Linux, Fedora…) el estado de SElinux. Si está activado, probablemente sea el origen del problema:

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /selinux
Current mode:                   enforcing
Mode from config file:          enforcing
Policy version:                 24
Policy from config file:        targeted

En el log de auditoría veremos los siguientes errores:

# tail -200 /var/log/audit/audit.log  | grep crt
type=AVC msg=audit(1330769968.611:22): avc:  denied  { getattr } for  pid=1657 comm="httpd" path="/etc/ssl/cert.crt" dev=dm-0 ino=22027 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
type=AVC msg=audit(1330770107.699:23): avc:  denied  { getattr } for  pid=1676 comm="httpd" path="/etc/ssl/cert.crt" dev=dm-0 ino=22034 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file
type=AVC msg=audit(1330770206.289:24): avc:  denied  { getattr } for  pid=1697 comm="httpd" path="/etc/ssl/cert.crt" dev=dm-0 ino=22034 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=unconfined_u:object_r:admin_home_t:s0 tclass=file

Se presupone además que hemos revisado que el path al certificado es correcto y no está vacío. Para solucionar el problema debemos aplicar (etiquetar) los atributos de SElinux correctos a los ficheros del certificado (certificado, private key, CA). Una forma sencilla es “copiar” estos atributos de un fichero de configuración Apache, que ya los tendrá asignados:

# chcon --reference=/etc/httpd/conf.d/ssl.conf cert.*

O aplicándolo especificando todos los atributos:

# chcon -u system_u -r object_r -t httpd_config_t cert.*

Si listamos ya tenemos etiquetados los ficheros y podemos reiniciar Apache sin recibir el error:

# ls -Z
-rw-r--r--. apache apache system_u:object_r:httpd_config_t:s0 cert.crt
-rw-r--r--. apache apache system_u:object_r:httpd_config_t:s0 cert.csr
-rw-r--r--. apache apache system_u:object_r:httpd_config_t:s0 cert.key

ReverseProxy en Apache con SSL


Hoy vamos a ver los pasos para activar soporte SSL en un proxy reverse de Apache. Algunos de los pasos ya los he comentado en otros artículos así que los citaré directamente.

Lo primero es Configurar Apache como Reverse Proxy (Proxy Inverso), pinchad en el enlace antes de seguir leyendo. Una vez realizado tenemos que tener un certificado SSL, podemos contratarlo en una entidad certificadora o generarlo nosotros mismos. Para ello revisar este enlace: generar un certificado SSL propio con openssl.

Ahora que tenemos Apache listo para ser usado como reverse proxy sólo nos queda realizar los pasos finales. Lo primero es habilitar soporte para mod_ssl instalando el módulo de Apache. Podemos hacer vía yum o apt, si Apache ha sido compilado a mano habrá que recompilar.

# yum install mod_ssl

Tenemos que modificar la configuración de mod_proxy para permitir el acceso vía SSL, para ello buscamos la configuración del módulo en el fichero de configuración de Apache httpd.conf. Podríamos configurar estas directivas únicamente en el Virtualhost que queramos si no se desea hacer para todo el servidor. Básicamente activamos SSLProxyEngine (lo hacemos en el virtualhost) y restringimos el acceso al proxy a la red 10.0.0.0/24 a nivel general.

<IfModule mod_proxy.c>
...
...
<Proxy *>
Order deny,allow
Deny from all
Allow from 10.0.0.0/24
</Proxy>
....
....
</IfModule>

Y el Virtualhost, veréis que activamos los Engine de SSL y de SSLProxy, especificamos las rutas al certificado SSL y su PrivateKey y que finalmente especificamos las directivas de proxy, en este caso al acceder a https://proxy.com/google nos llevará a https://google.com. He omitido configuraciones de log y demás en el vhost para hacerlo más sencillo:

<VirtualHost 0.0.0.0:443>
    ServerName proxy.com
    SSLEngine on
    SSLProxyEngine on
    SSLCertificateFile /etc/ssl/cert.crt
    SSLCertificateKeyFile /etc/ssl/cert.key
    ProxyPass /google/ https://google.es
    ProxyPassReverse /google/ https://google.es
</VirtualHost>

Cambiar el AP_DOC_ROOT en suEXEC instalado por RPM


suEXEC por seguridad trae los siguientes parámetros compilados y sin posibilidad de ser modificados:

# suexec -V
 -D AP_DOC_ROOT="/var/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

Si lo hemos instalado compilando a través de las sources, no hay problema, se recompila y ya está. Pero si lo hemos instalado por RPM requiere un trabajo distinto. Es necesario bajar las sources del RPM y editarlas con los parámetros que queramos, luego se compila el nuevo RPM y ya podemos instalarlo.

En este caso se trata un Apache con suEXEC en RHEL 6 e instalado por RPM así que nos bajamos las sources de Apache correspondientes:

# curl -O ftp://ftp.redhat.com/pub/redhat/linux/enterprise/6Server/en/os/SRPMS/httpd-2.2.15-15.el6_2.1.src.rpm

Desempaquetamos el RPM, Si el usuario mockbuild no existe veréis un montón de avisos y las sources se guardarán en la home de root en lugar de en src:

# rpm -Uvh httpd-2.2.15-15.el6_2.1.src.rpm

Ahora tenemos que editar el fichero httpd.spec:

# vi /root/rpmbuild/SPECS/httpd.spec

En nuestro caso queremos cambiar el AP_DOC_ROOT o contentdir, que es la ruta raíz en la que vamos a alojar el contenido de los websites:

%define contentdir /var/www

Modificamos a la ruta correcta:

%define contentdir /www

Para que al hacer el upgrade no nos diga que la versión ya está instalada, también podemos cambiar el número de versión:

Release: 15%{?dist}.3

Es necesario para volver a compilar el rpm el paquete rpm-build, también necesitaréis las sources de ciertas dependencias, lo veréis según vayáis haciendo el trabajo:

# yum install rpm-build
# yum install libselinux-devel openssl-devel

Recompilamos el RPM:

# rpmbuild -bb /root/rpmbuild/SPECS/httpd.spec

Una vez terminado ya tenemos los RPM listos para instalar en /root/rpmbuild/RPMS/x86_64:

-rw-r--r--. 1 root root 3229796 Feb 21 06:26 httpd-2.2.15-15.el6.1.x86_64.rpm
-rw-r--r--. 1 root root  156508 Feb 21 06:26 httpd-devel-2.2.15-15.el6.1.x86_64.rpm
-rw-r--r--. 1 root root  128945 Feb 21 06:26 httpd-tools-2.2.15-15.el6.1.x86_64.rpm
-rw-r--r--. 1 root root  403246 Feb 21 06:26 mod_ssl-2.2.15-15.el6.1.x86_64.rpm
# rpm -Uvh *rpm

Reiniciamos apache y:

# suexec -V
 -D AP_DOC_ROOT="/www"
 -D AP_GID_MIN=100
 -D AP_HTTPD_USER="apache"
 -D AP_LOG_EXEC="/var/log/httpd/suexec.log"
 -D AP_SAFE_PATH="/usr/local/bin:/usr/bin:/bin"
 -D AP_UID_MIN=500
 -D AP_USERDIR_SUFFIX="public_html"

Por supuesto podéis cambiar el resto de valores del mismo modo si fuera necesario.

Pasos para activar WebDAV en Apache (mod_dav)


Apache

El objetivo de WebDAV es hacer de la World Wide Web un medio legible y editable, en línea con la visión original de Tim Berners-Lee. Este protocolo proporciona funcionalidades para crear, cambiar y mover documentos en un servidor remoto (típicamente un servidor web). Esto se utiliza sobre todo para permitir la edición de los documentos que sirve un servidor web, pero puede también aplicarse a sistemas de almacenamiento generales basados en web, que pueden ser accedidos desde cualquier lugar. La mayoría de los sistemas operativos modernos proporcionan soporte para WebDAV, haciendo que los ficheros de un servidor WebDAV aparezcan como almacenados en un directorio local.

Definición de WebDAV en Wikipedia

Preparación/instalación

Vamos a ver los pasos (sencillos) para activar WebDAV en Apache. Lo primero que hay que verificar es que el módulo mod_dav está cargado, ya sea de forma estática o dinámica. Normalmente cuando instalamos Apache por gestor de paquetes viene cargado de forma dinámica en el fichero httpd.conf:

Loadmodule dav_module modules/libdav.so

Si por contra compilamos Apache manualmente podemos decidir si compilarlo estáticamente o dinámicamente (como hemos visto antes). Para hacerlo estáticamente añadiremos la directiva correspondiente a la línea de compilación y podremos ver si está cargado con el comando:

# httpd -l

Otra opción es instalar el paquete por yum/apt/pkg si el paquete está disponible en un repositorio.

Configuración

Lo primero que tenemos que hacer es activar el soporte para WebDAV a nivel general de Apache, para ello añadiremos la siguiente línea en el fichero httpd.conf. Podemos restringirlo a nivel de <Directory> o <Location>:

Dav On

Además de esto, debemos especificar la base de datos de bloqueos (Lock Database) en la sección global de la configuración del httpd.conf:

DavLockDB /etc/apache/var/DavLock

Este directorio debe tener permisos de escritura para el usuario y grupo que ejecuta el servidor Apache.

El resultado final sería el siguiente, en este ejemplo activamos WebDAV en una ubicación (/webdav) únicamente para usuarios autenticados (admin) configurados con htpasswd

DavLockDB /usr/local/apache2/var/DavLock
<Location /webdav>
   Dav On

   AuthType Basic
   AuthName DAV
   AuthUserFile user.passwd

   <LimitExcept GET OPTIONS>
     require user admin
   </LimitExcept>
</Location>

Estas mismas directivas (a excepción del DavLockDB) podríamos añadirlas dentro de un virtualhost.

Conectar al WebDAV

Muchos sistemas soportan acceso a WebDAV de forma nativa. No obstante, en Linux podéis usar cadaver sobre línea de comandos:

$ cadaver http://dav.test.com/webdav/
...
...
dav:/webdav/>

mod_fcgid: HTTP request length 132147(so far) exceeds MaxRequestLen (131072)


Si utilizas Apache + FastCGI y no has modificado los parámetros por defecto de configuración de fasctcgi es probable que si intentas hacer upload de ciertos ficheros cuyo tamaño no sea muy pequeño recibas un error como este en el log:

[Tue Aug 30 12:05:13 2011] [warn] [client XX.XX.XXX.XX] mod_fcgid: HTTP request length 132147 (so far) exceeds MaxRequestLen (131072)

FastCGI está bloqueando la subida del fichero debido a su tamaño. Los límites iniciales de la directiva MaxRequestLen son muy bajos por defecto (131072), así que conviene ampliarlos para evitar este tipo de errores, por ejemplo a 15MB. Esta directiva la añadimos dentro del fichero php.conf (en la carpeta conf/ de apache) y sino dentro del IfModule correspondiente a fastcgi:

<IfModule mod_fcgid.c>
MaxRequestLen 15728640
...
...
</IfModule>

Reiniciamos apache y listo. Hay que tener en cuenta que esto mismo puede suceder también en servidores con Lighttpd y FastCGI.

Apache: diferencia entre reiniciar con ‘restart’ y ‘graceful’


ApacheVamos a ver las principales diferencias a la hora de reiniciar un servidor web Apache mediante

/etc/init.d/httpd restart

y

/etc/init.d/httpd graceful

.

Reinicio con restart

# apachectl -k restart
# /etc/init.d/httpd restart

Esta forma de reiniciar el servidor web es lo mismo que enviar una señal HUP a los procesos httpd (enviar señales a un proceso). Básicamente lo que hace es:

  1. Solicitar la finalización de los procesos con la señal TERM a los procesos child (hijos) y eliminar el proceso padre
  2. Se vuelven a leer los ficheros de configuración y se abren los ficheros de log. Las estadísticas de mod_status se reinician
  3. Se genera el proceso padre y a partir de él los nuevos procesos hijos

Como podéis ver, hay parada de servicio. Puede llegar a ser mínima pero hay un momento en el que no hay ningún proceso httpd para servir peticiones web.

Reinicio con graceful

# apachectl -k graceful
# /etc/init.d/httpd graceful

Esta forma de reiniciar Apache hace que se envíe una señal

USR1

, lo cual hace que en lugar de reiniciar todos los procesos hijos de vez, el proceso padre permite que cada uno de los child termine de servir la petición web antes de morir. El proceso sería el siguiente:

  1. Enviamos la señal USR1 o graceful
  2. El proceso padre indica a los hijos que mueran una vez finalizada la petición que estén sirviendo
  3. El proceso padre vuelve a leer los ficheros de configuración y abrir los logs
  4. Los procesos hijos van terminando de servir las peticiones y el padre los va sustituyendo por nuevos (que ya tienen cargada la nueva configuración)

Cara a mod_status, módulo que sirve para controlar el estado del servidor web, Apache no habrá sido reiniciado, mantendrá todas sus estadísticas y mostrará con una G los threads que están sirviendo previos al reinicio graceful.