Monitoreo de logs de IIS utilizando logwatch

NOTA: este artículo podría haberse llamado "logwatch para Windows" o "logwatch for Windows".

Una de las principales herramientas que utilizo en todos los servidores GNU/Linux (además de Nagios) es Logwatch. Logwatch es un sistema de monitoreo de logs personalizable. Su función es revisar los logs del sistema en un período de tiempo determinado y elaborar un resumen con el nivel de detalle que se desee. Luego es capaz de enviar el resumen por mail en forma de reporte. Es muy útil para monitorear la actividad de los servidores y detectar posibles abusos, intentos de intrusión, consumo de recursos, etc.

He dedicado varios artículos a esta gran herramienta, como por ejemplo Instalación de logwatch en Debian, Discriminar logs de Apache en logwatch según VirtualHost y Configurar logwatch en servidores prehistóricos.

Como sysadmin, además de administrar una amplia variedad de servidores GNU/Linux, debo administrar varios servidores Microsoft Windows. A pesar de que apoyo fervientemente el software libre y open source no me considero un fundamentalista. Me gusta aprender todo lo posible, y hacer experiencia trabajando con la mayor cantidad de sistemas y tecnologías a mi alcance (tengo la suerte de poder meter mano en servidores Novell y Unix; tecnologías de virtualización como VMware, KVM y Hyper-V; etc.)

Hace tiempo que llevo buscando sin éxito una buena herramienta "free" que realice el mismo trabajo que Logwatch (lamentablemente no hay una versión de Logwatch para Windows) con el objetivo de monitorear logs de servidores IIS (Internet Information Services).



Es por ello que decidí dejar de buscar e intentar una solución ad-hoc que consiste a grandes razgos en:

  • Copiar los archivos de log de IIS a un servidor GNU/Linux utilizando samba.
  • Crear una replica del servicio "http" en la configuración de logwatch del servidor GNU/Linux para monitorear estos archivos (utilizando la misma técnica que en el artículo Discriminar logs de Apache en logwatch según VirtualHost).

El principal inconveniente que me impedía implementar esta solución de forma sencilla es que los servidores IIS dentro de la organización están configurados para guardar los archivos de log utilizando el formato W3C Extended Log File Format. Logwatch es capaz de procesar archivos de log del servicio "httpd" en formato NCSA Common Log File Format, ya que es el formato que utiliza Apache por defecto.

IIS es capaz de guardar los archivos de log en diferentes formatos, entre los que se incluye el formato NCSA Common Log File Format. Pero ya a que otras aplicaciones en los servidores de la organización consumen los mismos logs en formato W3C, tuve que descartar inmediatamente la posibilidad de cambiar el formato de los archivos de log a Common Log File Format en los sitios que quería monitorear. Necesitaba entonces convertir los archivos de log desde el formato W3C Extended Log File Format al formato Common Log Format antes de que sean procesados por Logwatch.

Cuando estaba a punto de escribir un script Bash que realice esta tarea, descubrí que Microsoft incluye la herramienta convlog como parte de IIS. Esta herramienta se utiliza para convertir archivos de log de IIS al formato NCSA Common Log File Format:

D:\>convlog
Microsoft Internet Log Converter
Converts Microsoft Internet Information Services log files
to the NCSA Common LogFile format
Copyright (C) 1997-1999 Microsoft Corporation

Usage: convlog [options] LogFile
Options:
-i<i|n|e> = input logfile type
    i - MS Internet Standard Log File Format
    n - NCSA Common Log File format
    e - W3C Extended Log File Format
-t <ncsa[:GMTOffset] | none> default is ncsa
-o <output directory> default = current directory
-x save non-www entries to a .dmp logfile
-d = convert IP addresses to DNS
-l<0|1|2> = Date locale format for MS Internet Standard
    0 - MM/DD/YY (default e.g. US)
    1 - YY/MM/DD (e.g. Japan)
    2 - DD.MM.YY (e.g. Germany)
-c = continue even if incorrectly formatted line found

Examples:
convlog -ii in*.log -d -t ncsa:+0800
convlog -in ncsa*.log -d
convlog -ii jra*.log -t none

D:\>

En lugar de copiar los archivos de log al servidor GNU/Linux y luego convertirlos utilizando un script bash, decidí convertirlos en el servidor Windows antes de copiarlos, para aprovechar esta herramienta.

Manos a la obra...

La implementación se divide en dos partes, primero la configuración en el servidor Windows (en este caso un Windows Server 2003) y luego la configuración en el servidor GNU/Linux (en este caso un Debian 6).

Servidor Windows

En el servidor Windows se deben realizar las siguientes tareas:

  • Crear un directorio de trabajo para los archivos de log convertidos
  • Crear un script batch para convertir los archivos de log del día anterior de formato W3C a formato NCSA.
  • Crear una tarea programada para convertir los logs del día anterior una vez al día. Esta tarea debe ejecutarse a una hora específica que debe seleccionarse cuidadosamente (antes de que se ejecute logwatch en el servidor GNU/Linux).
  • Crear un usuario para que el servidor GNU/Linux pueda descargar los archivos de log a través del protocolo samba.
  • Crear una carpeta compartida donde se guardarán los archivos de log. Sólo el usuario creado en el paso anterior tendrá permisos de lectura y escritura.

En este ejemplo en particular, el servidor IIS posee dos sitios, llamados "sitioa" y "sitiob", los cuales guardan sus archivos de log en los directorios C:\WINDOWS\system32\LogFiles\W3SVC1649036221\ y C:\WINDOWS\system32\LogFiles\W3SVC894523\ respectivamente.

Directorio de trabajo

Para guardar temporalmente y compartir con el servidor GNU/Linux los archivos de log convertidos, es necesario crear un directorio de trabajo:

C:\>md D:\logwatch

C:\>md D:\logwatch\logs

El directorio D:\logwatch se utiliza para guardar el script batch que convierte y copia los archivos de log. El directorio D:\logwatch\logs se utiliza como destino de los archivos de log convertidos.

Script para convertir los archivos de log del día anterior

La tarea programada se va a ejecutar diariamente, entonces sólo es necesario copiar al servidor GNU/Linux los archivos de log del último día, para evitar procesar una y otra vez los archivos de log históricos (IIS genera un archivo de log separado para cada día). Por lo tanto necesito un script batch que convierta los archivos de log del día anterior de formato W3C a formato NCSA y los copie al directorio D:\logwatch\logs. La necesidad de convertir los archivos de log se debe a que (en mi situación en particular) me veo forzado a mantener el tipo de formato de los archivos de log en la configuración de los sitios hospedados en el servidor IIS. Si no se tiene esta limitación, es posible cambiar el formato de archivo de log a NCSA en la configuración de los sitios. Luego el script simplemente debe copiar los archvios de log del día anterior a una carpeta compartida.

Debido a que la consola de MS-DOS estándar no posee grandes funcionalidades (en cambio sí se puede hacer mucho con PowerShell) se complica el cálculo de la fecha del día anterior. El truco utilizado para superar esta limitación consiste en guardar la fecha del día actual en un archivo de texto (llamado "ayer.txt") para recuperarla el día siguiente y evitar el complejo cálculo.

Script log.bat:

@echo off
REM ==== Conversión de logs de IIS WINSERV ====

REM recuperar la fecha de ayer
set /p ayer=<ayer.txt
set ayer=%ayer: =%

REM obtener la fecha de hoy
set fecha=%date:~8,2%%date:~3,2%%date:~0,2%

REM guardar la fecha de hoy para recuperarla mañana
echo %fecha% > ayer.txt

REM cambiar al directorio donde se guardan los logs
cd D:\logwatch\logs

REM borrar logs viejos
del D:\logwatch\logs\*.ncsa

REM sitioa
convlog -ie C:\WINDOWS\system32\LogFiles\W3SVC1649036221\ex%ayer%.log
REM se ha generado el archivo ex%ayer%.log.ncsa
REM renombrar archivo
move ex%ayer%.log.ncsa sitioa%ayer%.ncsa

REM sitiob
convlog -ie C:\WINDOWS\system32\LogFiles\W3SVC894523\ex%ayer%.log
REM se ha generado el archivo ex%ayer%.log.ncsa
REM renombrar archivo
move ex%ayer%.log.ncsa sitiob%ayer%.ncsa

La siguiente captura muestra el contenido del directorio de trabajo D:\logwatch, que incluye la carpeta logs donde se guardan los archivos de log convertidos, el archivo "ayer.txt" que contiene la fecha del día de ayer (en formato "aammdd"), y el script log.bat:

Tarea programada

Luego de verificar el correcto funcionamiento del script es necesario crear una tarea programada que lo ejecute una vez al día. Desde el Panel de Control de Windows abrir Tareas programadas y ejecutar el wizard "Agregar tarea programada":

En el primer paso se debe seleccionar el programa a ejecutar:

Navegar hasta el directorio de trabajo y seleccionar el script log.bat:

Ingresar un nombre para la tarea programada y seleccionar el período de ejecución, en este caso a diario:

Especificar la hora a la que se debe ejecutar. Se debe seleccionar cuidadosamente la hora, debe ser antes de que se ejecute logwatch en el servidor GNU/Linux. Es posible determinar la hora a la que se ejecuta logwatch revisando la hora de ejecución de "cron.daily" en el archivo /etc/crontab (en el servidor GNU/Linux). Para tener un amplio margen utilizo la hora 01:00 a.m.:

Ingresar las credenciales de Administrator para ejecutar la tarea programada:

El último paso del wizard es un resumen de la configuración de la tarea programada:

Usuario para el cliente samba y carpeta compartida

Luego de automatizar la conversión y copia de archivos de log, es necesario crear un usuario y compartir la carpeta "D:\logwatch\logs" para que el servidor GNU/Linux pueda descargarlos a diario, antes de que se ejecute logwatch.

Desde Computer Management abrir System Tools y luego Local Users and Groups. Crear un nuevo usuario:

Especificar un nombre, descripción y contraseña (la contraseña no debe expirar y no debe poder modificarse):

Para compartir la carpeta "logs", desde Computer Management abrir System Tools y luego Shared Folders. Crear un nuevo share:

El wizard guía paso a paso la configuración:

Especificar la ruta a la carpeta compartida:

Ingresar un nombre y descripción para la carpeta compartida:

Utilizar permisos de acceso personalizados:

Eliminar el grupo Everyone:

Luego agregar al usuario "logwatch":

Debe tener permisos de sólo lectura:

NOTA: No olvidarse de otorgar permisos de lectura para el usuario "logwatch" en la carpeta D:\logwatch\logs.

El último paso del wizard es un resumen de la configuración de la carpeta compartida:

Servidor GNU/Linux

En el servidor GNU/Linux se deben realizar las siguientes tareas:

  • Crear un directorio para montar la carpeta compartida por el servidor Windows.
  • Crear un directorio dentro de /var/log para guardar los archivos de log.
  • Agregar un servicio para procesar los archivos de log de IIS (duplicando el servicio httpd).
  • Crear un script Bash para copiar los archivos desde el servidor Windows.
  • Agregar un cron job que ejecute el script anterior una vez al día. El timing aquí es crítico, los archivos se deben copiar antes de que se ejecute logwatch pero después de que el servidor Windows los haya convertido (de esto se desprende que ambos servidores deben tener sus relojes sincronizados contra el mismo servidor NTP).
Creación de directorios

Primero se deben crear los directorios para mover los archivos de log:

# mkdir /mnt/WINSERV
# mkdir /var/log/WINSERV
Prueba de conexión y copia remota a través de samba:

Antes de desarrollar el script bash y configurar un nuevo servicio en logwatch, es conveniente hacer una prueba de conexión y copia de archivos para verificar que todo funcione de la forma esperada:

# mount -t cifs //winserv.pepe.org/logs -o username=logwatch,password=************ /mnt/WINSERV
# ll /mnt/WINSERV/                                                                                   
total 37644                                                                                                              
-rwxr-xr-x 1 root root     1799 Mar 15 09:25 sitioa130314.ncsa
-rwxr-xr-x 1 root root 38542709 Mar 15 09:25 sitiob130314.ncsa
# cp /mnt/WINSERV/*.ncsa /var/log/WINSERV/                                                     
# ll /var/log/WINSERV/                                                                           
total 37644                                                                                                          
-rwxr-xr-x 1 root root     1799 Mar 15 10:18 sitioa130314.ncsa                                                  
-rwxr-xr-x 1 root root 38542709 Mar 15 10:18 sitiob130314.ncsa                                                          
# umount /mnt/WINSERV                                                                            

Todo funciona correctamente.

Configuración del servicio (logwatch)

El objetivo de convertir los logs a formato NCSA (el mismo formato que utiliza apache) era poder duplicar el servicio httpd para procesar los logs de IIS. De esta forma se evita tener que desarrollar un script perl que procese los logs.

# cd /etc/logwatch/
# cp /usr/share/logwatch/default.conf/logfiles/http.conf conf/logfiles/iiswinserv.conf
# cp /usr/share/logwatch/default.conf/services/http.conf conf/services/iiswinserv.conf
# cp /usr/share/logwatch/scripts/services/http scripts/services/iiswinserv

Para configurar el servicio "IIS WINSERV (web)" se deben realizar las mismas modificaciones que se detallan en el artículo Discriminar logs de Apache en logwatch según VirtualHost:

# nano conf/logfiles/iiswinserv.conf

Contenido del archivo /etc/logwatch/conf/logfiles/iiswinserv.conf:

########################################################
#   Define log file group for httpd
########################################################

# What actual file?  Defaults to LogPath if not absolute path....
LogFile = WINSERV/sitio*ncsa


# If the archives are searched, here is one or more line
# (optionally containing wildcards) that tell where they are...
#If you use a "-" in naming add that as well -mgt
Archive = WINSERV/sitio*gz


# Expand the repeats (actually just removes them now)
*ExpandRepeats


# Keep only the lines in the proper date range...
*ApplyhttpDate

# vi: shiftwidth=3 tabstop=3 et
# nano conf/services/iiswinserv.conf

Contenido del archivo /etc/logwatch/conf/services/iiswinserv.conf:

###########################################################################
# Configuration file for http filter                                       
###########################################################################

Title = "IIS WINSERV (web)"

# Which logfile group...
LogFile = iiswinserv  

# Define the log file format
#                           
# This is now the same as the LogFormat parameter in the configuration file
# for httpd.  Multiple instances of declared LogFormats in the httpd       
# configuration file can be declared here by concatenating them with the   
# '|' character.  The default, shown below, includes the Combined Log Format,
# the Common Log Format, and the default SSL log format.                     
#$LogFormat = "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"|%h %l %u %t \"%r\" %>s %b|%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"                                                                                                                    

# The following is supported for backwards compatibility, but deprecated:
# Define the log file format                                             
#                                                                        
#   the only currently supported fields are:                             
#                       client_ip                                        
#                       request                                          
#                       http_rc                                          
#                       bytes_transfered                                 
#                       agent                                            
#                                                                        
#$HTTP_FIELDS = "client_ip ident userid timestamp request http_rc bytes_transfered referrer agent"
#$HTTP_FORMAT = "space     space space    brace    quote   space        space       quote   quote" 
# Define the field formats                                                                         
#                                                                                                  
#   the only currently supported formats are:                                                      
#                       space = space delimited field                                              
#                       quote = quoted ("..") space delimited field                                
#                       brace = braced ([..]) space delimited field                                

# Flag to ignore 4xx and 5xx error messages as possible hack attempts
#                                                                    
# Set flag to 1 to enable ignore                                     
# or set to 0 to disable                                             
$HTTP_IGNORE_ERROR_HACKS = 0                                         

# Ignore requests
# Note - will not do ANY processing, counts, etc... just skip it and go to
# the next entry in the log file.                                         
# Examples:                                                               
# 1. Ignore all URLs starting with /model/ and ending with 1 to 10 digits 
#   $HTTP_IGNORE_URLS = ^/model/\d{1,10}$
#
# 2. Ignore all URLs starting with /model/ and ending with 1 to 10 digits and
#   all URLS starting with /photographer and ending with 1 to 10 digits
#   $HTTP_IGNORE_URLS = ^/model/\d{1,10}$|^/photographer/\d{1,10}$
#   or simply:
#   $HTTP_IGNORE_URLS = ^/(model|photographer)/\d{1,10}$

# To ignore a range of IP addresses completely from the log analysis,
# set $HTTP_IGNORE_IPS. For example, to ignore all local IP addresses:
#
#   $HTTP_IGNORE_IPS = ^10\.|^172\.(1[6-9]|2[0-9]|3[01])\.|^192\.168\.|^127\.
#

# The variable $HTTP_USER_DISPLAY defines which user accesses are displayed.
# The default is not to display user accesses:
$HTTP_USER_DISPLAY = 0
# To display access failures:
# $HTTP_USER_DISPLAY = "$field{http_rc} >= 400"
# To display all user accesses except "Unauthorized":
# $HTTP_USER_DISPLAY = "$field{http_rc} != 401"


# vi: shiftwidth=3 tabstop=3 et

Una vez configurado el servicio es posible realizar una prueba de ejecución:

# logwatch

Si todo sale bien se recibe el mail de logwatch que incluye una sección con el nuevo servicio.

Creación del script y cron job para copiar los archivos de log

Finalmente se crea el script Bash junto con el cron job para automatizar la tarea de copia remota de archivos de log:

# touch /scripts/logs_WINSERV.sh
# nano /scripts/logs_WINSERV.sh

El contenido del script es el siguiente:

#!/bin/sh

# Recuperar logs IIS en formato NCSA desde WINSERV

mount -t cifs //winserv.pepe.org/logs -o username=logwatch,password=************ /mnt/WINSERV

cp /mnt/WINSERV/*.ncsa /var/log/WINSERV/

umount /mnt/WINSERV

Se debe dar permiso de ejecución al script:

# chmod +x logs_WINSERV.sh

Finalmente se agrega un nuevo cron job para ejecutarlo una vez al día. Es necesario elegir cuidadosamente la hora, ya que debe ejecutarse luego de que se hayan convertido los logs del día anterior en el servidor Windows, pero antes de que se ejecute logwatch.

# nano /etc/cron.d/logs_WINSERV
# /etc/cron.d/logs_WINSERV: crontab para copiar logs IIS en formato NCSA desde WINSERV

0 5 * * * root /root/scripts/logs_WINSERV.sh >> /var/log/logs_WINSERV.log 2>&1

Y eso es todo... Pan comido!



Suscribirse

    Registrate para recibir las novedades y artículos por correo electrónico.

Linuxito en G+