24 de Noviembre, 2004

Rotar los logs de Apache en un chroot

Esto es muy complicado, mucho más de lo que parece.

Los logs son los registros de la actividad del servidor, que para evitar que crezcan de forma incontrolada, se rotan.

Cuando ha pasado un tamaño de fichero (o tiempo) especificado, el fichero de registro se renombra y se comprime para que no ocupe tanto espacio. Además hay un número máximo de ficheros a guardar. Por ejemplo, los logs del servicio de correo de blackshell son:

$ ls -l /var/log/maillog*
-rw-------  1 root  wheel  22605 Nov 24 16:49 /var/log/maillog
-rw-------  1 root  wheel   7192 Nov 24 00:00 /var/log/maillog.0.gz
-rw-------  1 root  wheel   9973 Nov 23 00:00 /var/log/maillog.1.gz
-rw-------  1 root  wheel   3571 Nov 22 00:00 /var/log/maillog.2.gz
-rw-------  1 root  wheel   1852 Nov 20 23:59 /var/log/maillog.3.gz
-rw-------  1 root  wheel   1177 Nov 20 00:00 /var/log/maillog.4.gz
-rw-------  1 root  wheel   1353 Nov 19 00:00 /var/log/maillog.5.gz
-rw-------  1 root  wheel   1760 Nov 18 00:00 /var/log/maillog.6.gz
-rw-------  1 root  wheel   1997 Nov 17 00:00 /var/log/maillog.7.gz

Mirando las fechas podemos entender cómo van rotando. Se desplazan todos los ficheros cuando el que está en uso (maillog en el ejemplo) pasa el tamaño especificado, de forma que el contenido del registro más viejo se pierde.

Una vez sabemos más o menos qué es esto de rotar los logs, veamos qué pasa cuando intentamos hacerlo con Apache en un entorno chroot.

La finalidad de correr Apache bajo chroot es minimizar las posibles consecuencias de un ataque que acabe con la apropiación del proceso de httpd por parte de un intruso.

El proceso de Apache cambia su raíz a /var/www (de forma que no puede acceder al resto del disco) y deja sus privilegios pasando a ser www:www (usuario:grupo), para entonces crear varios procesos hijo para administrar el trabajo.

Para que esto sea efectivo tenemos que:

  • Minimizar los binarios dentro del chroot.
  • No permitir escritura de ficheros para el usuario www o el grupo www dentro del chroot.

Creo que ambas condiciones son razonables.

Pues son un verdadero dolor de cabeza para rotar los logs del servidor :'(.

Los logs están bajo posesión de root:daemon (en mi caso, puede ser root:wheel). El proceso de httpd abre estos ficheros como root y luego deja sus privilegios. Por eso funciona sin problemas cuando lo arrancamos.

En primer lugar queda claro que hay que descartar rotatelogs, la herramienta específica para esta tarea. Este programa emplea las propiedades de Apache para pasar los registros por un pipe. Es decir, en lugar de guardar él las entradas, las pasa por un proceso que se encarga de ello y además rota los logs cuando le indicamos. Pero una vez Apache ha hecho chroot no puede acceder a él (whereis rotatelogs, indica que queda fuera).

La otra opción menos documentada es emplear newsyslog, que está muy bien y tal para rotar cualquier tipo de logs ejecutándolo desde un cron, pero tampoco funciona :(.

De hecho me parece cruel que el /etc/newsyslog.conf de OpenBSD (al menos en mi versión) contenga las siguientes lineas:

# Uncomment to rotate apache logs
#
#/var/www/logs/access_log 644 7 250 * Z /var/www/logs/httpd.pid SIGUSR1
#/var/www/logs/error_log 644 7 250 * Z /var/www/logs/httpd.pid SIGUSR1

No por nada, sino porque nos hacemos ilusiones y luego no funciona :D. Y no lo hace por dos razones. La primera ya la conocemos: no hay permisos para que una vez newsyslog ha rotado los ficheros Apache vuelva a abrirlos para escribir en ellos.

La segunda es, si cabe, más insalvable aun. Aunque newsyslog nos permite enviar una señal a httpd cuando ha terminado su trabajo, es muy habitual tener módulos cargados en nuestro Apache, ¿no? ¿Y dónde quedan esos módulos? En /usr/lib/apache/modules/. Vaya, eso está fuera del chroot :P. Así que si usamos módulos no hay otra manera: hay que parar el servidor y volverlo a arrancar, para que cargue los módulos antes del cambio de raíz, y no es suficiente con la señal que envía newsyslog.

Esto está feo, la verdad. Pero parece que no hay otra forma de mantener un nivel alto de seguridad sin dejar que los logs se nos desmadren en tamaño.

Todo este tiempo llevo usando el chroot porque yo lo valgo ;), pero lo de los logs es una verdadera puñeta.

Actualización (25-Nov): rotatelogs no funciona porque queda fuera del chroot (parece), más que debido a problemas de privilegios. Esto tiene varias consecuencias y he rectificado los errores consiguientes en el artículo.

Anotación por Juan J. Martínez.

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.