Archivo de la etiqueta: logs

No pierdas el correo de tus servidores

Históricamente los servidores GNU/Linux han contando con un servidor de correo en sus instalaciones más básicas, aunque sólo fuese para uso propio/interno. Por ello hay aplicaciones como cron, at, logcheck, smartmontools, etc. que dan por hecho que este servicio está presente y bien configurado y lo usan para enviar avisos, algunos de máxima importancia. Por este motivo es importante asegurarse de que nuestra máquina hará llegar los posibles correos que se envíen desde ella a una dirección de correo que sea comprobada de forma periódica. Por ejemplo a nuestra propia dirección de correo.

Como alternativa podríamos entrar en la máquina y mirar el correo en ella (por ejemplo con el comando mail del paquete «mailx» o similares). El problema de esta solución es que hay que tener la disciplina de hacerlo frecuentemente y no escala en el momento que gestionemos varios servidores.

Acciones a realizar para asegurarse de que el correo llegará correctamente a una cuenta externa:

  • El servidor tiene un nombre válido de DNS (servidor.example.net) o pone uno a los correos que salgan de él.
  • El servidor tiene que tener acceso a Internet (para sacar el correo) o al menos a un servidor de correo que usemos como relay.
  • El servidor tiene que ser capaz de resolver entradas DNS (tener un servidor DNS alcanzable en el /etc/resolv.conf), salvo que lo entregue por un servidor de relay.
  • Las cuentas de los usuarios deben apuntar a la cuenta de correo real a la que queremos que llegue el correo.
  • Siempre realizar pruebas (por ejemplo con el comando mail) para comprobar el correcto comportamiento.

No voy a entrar en la configuración de red (salida a Internet y DNS) en este post, porque debería ser trivial. Si entraré en detalle en los otros puntos.

Nombre válido del servidor

La mayoría de los servidores de correo en Internet rechazarán correo proveniente de una dirección no válida, por ejemplo: root@mi_servidor, root@mi_servidor.local o root@mi_servidor.dominio_que_no_exite.com. Por ello debemos asegurarnos de que el nombre completo (FQDN) de nuestra máquina puede ser resuelto por el sistema DNS, o configurar el servidor local de correo para que use un dominio válido (por ejemplo cuando el nombre de nuestro servidor sólo es válido en su red local). En el caso de Postfix podemos usar la variable myorigin para indicarlo:

# En /etc/postfix/main.cf
# En el caso de Debian el valor de la variable está en el fichero mailname
# Podemos cambiarlo ejecutando: echo servidor.example.net > /etc/mailname
# Ejecutar "postfix reload" después de hacer los cambios
myorigin = /etc/mailname
# También podríamos especificarlo directamente
#myorigin = servidor.example.net

Servidor relay

Si nuestra máquina no está conectada directamente a Internet, porque presta un servicio local, lo ideal es que haga llegar todo su correo a un servidor que pueda realizar esta labor. Por ejemplo el servidor de correo que usemos normalmente. Llegados a este punto existen dos posibilidades: que nuestra máquina pueda ser identificada por su IP en el servidor de correo (y por tanto este último acepte su correo directamente) o que esto no sea posible y por tanto nuestra máquina tenga que identificarse con un usuario y contraseña SMTP en el servidor (como lo haría cualquier cliente de correo). Como fan de Postfix, pondré los ejemplos de configuración para dicho software. Esta sería la configuración para que un servidor (con Postfix instalado) use a otro (relay) para sacar su correo interno:

# El correo se envía a 10.20.30.40 para que éste lo envíe al destinatario final
# También podemos usar el nombre del servidor de correo en vez de su IP
relayhost = 10.20.30.40
# En caso de necesitar autenticación en el servidor relay,
# descomentar las siguientes líneas y crear el fichero indicado
#smtp_sasl_auth_enable = yes
#smtp_sasl_password_maps = hash:/etc/postfix/passwords

En el caso de necesitar autenticación, crearíamos el fichero passwords con el siguiente contenido y posteriormente ejecutaremos el comando «postmap /etc/postfix/passwords» como root:

# Contenido del fichero /etc/postfix/passwords
# Servidor          usuario_smtp:clave_smtp
10.20.30.40         fulanito@example.com:s3cr3t0s
# El campo servidor debe coincidir exactamente
# con el indicado en la opción relayhost

Dirigir el correo de los usuarios locales a una cuenta externa

Por defecto el correo para usuarios locales (root, logcheck, tu propio usuario) se quedará en la propia máquina. Para que llegue a nuestro correo tenemos varias opciones. Mi preferida es mandar todos los correos de usuarios de sistema a root, y el de éste a mi usuario local:

# /etc/aliases
logcheck: root
nagios: root
www-data: root
# [ los que ya vengan por defecto]
root: agi

Importante: Después de modificar el fichero /etc/aliases, debemos ejecutar el comando «newaliases» como root.

Llegados a este punto tenemos dos opciones. Una es meter la siguiente entrada en el /etc/aliases también:

agi: example@example.net

La otra es crear un fichero llamado «.forward» en nuestro $HOME con nuestra dirección de correo como único contenido:

echo "example@example.net" > ~/.forward

Esta última solución tiene como ventaja que no requiere del uso de root (o la ejecución de newaliases), por lo que es más útil para usuarios que no tengan dichos privilegios.

Prueba que funciona

Una vez todo configurado, queda probar que el correo llega a su destino. Para ello basta con ejecutar «ps ax | mail root» o «ls -l /etc | mail mi_usuario» o «cat /etc/hosts | mail logcheck» y comprobar que el correo llega a nuestra dirección de correo. En caso contrario habrá que empezar a revisar los logs de correo.

Es vital que se realice esta comprobación, incluso de vez en cuando de forma manual si la máquina no suele generar correo. El objetivo es evitar que el día que la herramienta de monitorización de discos (por poner un ejemplo), empieza a detectar errores y notificarnos por correo, nos enteremos inmediatamente y no pasados unos días cuando el disco esté completamente muerto.

$ exit

Vigilando los logs con logcheck (II)

Si después de leer mi primer post tienes interés en usar logcheck, en este intentaré explicar todo lo necesario para ello.

Instalación

El primer paso es instalar logcheck. En distribuciones basadas en Debian (sí, eso incluye Ubuntu) sólo necesitas ejecutar:

# apt-get install logcheck

y opcionalmente:

# apt-get install logcheck-database

En distribuciones RedHat/CentOS tendrás que añadir el repositorio EPEL, e instalar con:

# yum install logcheck

Configuración inicial

La configuración de logcheck se realiza en dos ficheros principales y unos directorios con reglas. El primer fichero que debemos revisar es /etc/logcheck/logcheck.logfiles. En él se incluyen los logs que serán procesados. En Debian vienen por defecto: /var/log/syslog y /var/log/auth.log. En RedHat sus equivalentes: /var/log/messages y /var/log/secure. Para empezar son buena elección y contienen el grueso de los logs de un sistema GNU/Linux. Si tenemos aplicaciones que tengan un log propio que queramos revisar, deberemos añadirlo a esta lista.

En el segundo fichero (logcheck.conf) hay dos opciones dignas de mención. REPORTLEVEL indica que directorio de reglas se usará. Por defecto viene «server», que es una buena elección para empezar. Hay un nivel más exigente con el contenido de los logs, paranoid, y otro preparado para estaciones de trabajo/portátiles que generan muchos mensajes de aplicaciones de usuario, workstation.

SENDMAILTO indica la dirección a la que se enviarán los informes. En importante recalcar que el sistema debe tener un servidor de correo correctamente configurado. Ya sea por si mismo o a través de otro servidor (relay), el servidor tiene que ser capaz de enviarnos correo. Dicho esto, en SENDMAILTO podemos poner nuestra dirección de correo, o usar el /etc/aliases para reenviar el correo del usuario logcheck (valor inicial de la opción) a nuestro correo. Recomiendo en este punto probar a enviar un correo desde el shell de la máquina, ya sea al usuario logcheck (para probar que el alias funciona) o a nuestra dirección de correo.

Desde este momento, cada hora (según /etc/cron.d/logcheck) recibiremos un correo con todas las líneas de log que no le hayamos indicado como aceptables. Aquí es donde empieza realmente nuestro trabajo. Si dejamos REPORTLEVEL=»server» en el fichero de configuración, trabajaremos sobre todo en el directorio /etc/logcheck/ignore.d.server. En RedHat, o si instalamos el paquete logcheck-database, dicho directorio ya contendrá una serie de ficheros de reglas. Se trata de ficheros que contienen una regla, expresada usando Expresiones Regulares, por línea. Cuando una línea de log coincide con alguna regla de estos ficheros, la línea se omitirá del informe horario. Es decir, estas reglas definen las entradas de log que son normales, que no nos interesan, y que no queremos en el correo. De esta forma sólo cuando una línea de log no coincide con ninguna regla será enviada por correo.

Entrenando a logcheck

Una vez llegue el primer correo de logcheck, éste contendrá varias líneas. Pongamos como ejemplo éstas:

Mar 23 12:23:49 foobar sshd[14830]: pam_unix(sshd:auth): check pass; user unknown
Mar 23 12:23:51 foobar sshd[14830]: Failed password for invalid user csilla from 198.211.3.42 port 55188 ssh2

Excluir líneas

Lo primero que debemos decidir es que líneas no queremos volver a ver nunca. Aquellas que no ofrezcan ninguna información útil son un buen comienzo. La entrada de las 12:23:49 indica un fallo de autenticación en SSH. Pero ni indica la IP ni el usuario del intento fallido. Si tenemos un servidor SSH abierto a Internet (sin filtrar por firewall) tendremos decenas de mensajes como éste al día, y no nos aportarán nada.

Mi recomendación es que tus propias reglas estén en un fichero independiente (sin tocar las que vienen ya en el paquete). De esta forma facilitas la actualización del paquete y eres consciente de las reglas que añadiste tú. Yo sigo una nomenclatura sencilla: local-servicio. El prefijo indica que las reglas son propias (locales) y el sufijo servicio al que se refieren. En el ejemplo actual, crearíamos el fichero /etc/logcheck/ignore.d.server/local-ssh con la siguiente regla:

^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: pam_unix\(sshd:auth\): check pass; user unknown$

Para los que no sepan todavía sobre expresiones regulares esa línea no tendrá mucho sentido. No podemos hacer nada en logcheck sin expresiones regulares, así que tocará darlas un repaso. Algo importante que debemos hacer siempre después de añadir una regla, es probar que funciona. Es decir, que coincide con las líneas que esperamos. Para ello podemos usar el comando egrep o uno propio de logcheck: logcheck-test.

NOTA: -a indica que se busque en el fichero auth.log, -s en el syslog o podemos indicar el fichero deseado con -l NOMBRE_DE_FICHERO:

# logcheck-test -a '^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: pam_unix\(sshd:auth\): check pass; user unknown$'

Es lo mismo que:

# logcheck-test -l /var/log/auth.log '^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: pam_unix\(sshd:auth\): check pass; user unknown$'

O con egrep:
egrep '^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[[:digit:]]+\]: pam_unix\(sshd:auth\): check pass; user unknown$' /var/log/auth.log

Si los comandos anteriores no devuelven líneas del log (y están allí) habremos cometido un error en la expresión regular y deberemos corregirlo antes de la ejecución periódica de logcheck, ya que de otra forma podría fallar la ejecución de éste. Y quedarnos sin saber que pasa en nuestra máquina.

Excluir líneas, después de haber tomado medidas

Otro caso diferente es la entrada de las 12:23:51 (también relacionada con un acceso no válido por SSH). En ella si tenemos información de la máquina remota. Aunque también tendremos decenas de estas líneas todos los días, antes de decidir ignorarlas tal vez hay que aprovechar su información. En este caso usando algún software como fail2ban, que añadirá una regla de firewall cuando una máquina remota se dedica a «bombardear» nuestro SSH en busca de un usuario y clave válidos. No digo que añadiendo una regla en logcheck  fail2ban deje de funcionar. Digo que antes de olvidarnos de por vida (indicando a logcheck que no nos interesa) de «una anomalía» procuremos tomar las medidas necesarias para paliarla.

Excluir con precisión

Mar 23 06:36:10 foobar nrpe[4975]: Host 192.99.10.71 is not allowed to talk to us!
Mar 23 11:42:19 foobar sshd[20137]: Connection closed by 91.121.65.176 [preauth]

En estos dos ejemplos vemos información de conexiones «irregulares» a dos servicios. En el primer caso se trata de una máquina no autorizada a hablar con el nagios. Al igual que comentaba en el punto anterior habría que ver si tomamos medidas adicionales (firewall, fail2ban) para evitarlo, y posteriormente ignorar ese tipo de mensajes con una regla en la que la dirección IP no sea relevante (por ejemplo en /etc/logcheck/ignore.d.server/local-nrpe):

^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nrpe\[[0-9]+\]: Host [0-9.]+ is not allowed to talk to us.$

Sin embargo, la segunda línea se debe a una comprobación de Nagios sobre la disponibilidad del SSH de esta máquina. Otras líneas iguales, pero con diferente IP no tendrían por qué ser ignoradas. Así que afinamos más:

^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ sshd\[[0-9]+\]: Connection closed by 91.121.65.176 \[preauth\]$

También se puede dar el caso de líneas que sólo son aceptables a una hora determinada:

Mar 23 04:00:31 foobar kernel: [27011506.187248] EXT4-fs (dm-7): recovery complete

Un mensaje de «error» en un sistema de ficheros que está en un snapshot montado a la hora de hacer backup y que sólo debería aparecer entonces, la regla se limita a esa hora y ese dispositivo:

^\w{3}  ?[0-9]+ 04:00:[0-9]+ [._[:alnum:]-]+ kernel: \[[0-9.]+\] EXT4-fs \(dm-7\): recovery complete$

Resumen

logcheck es una herramienta simple y extremadamente útil, pero debemos usarla correctamente:

  • Asegúrate de que el correo puede salir correctamente de tu servidor y de actualizar la dirección de envío o usar el /etc/aliases.
  • Deja tus reglas en ficheros independientes a los que vienen de serie. Facilita actualización y localización de errores.
  • Prueba las reglas (con egrep o logcheck-test) antes de darlas por buenas. De otra forma podrías romper el funcionamiento de logcheck.
  • Procura tomar medidas (arreglar un error de configuración, cerrar el acceso a un servicio, monitorizar el rendimiento de un servidor) antes de ignorar un error/advertencia de por vida. Después de dejar de verlos no lo harás.
  • Sé preciso a la hora de ignorar errores. Una regla «demasiado generosa» (poco estricta) puede coincidir con líneas de log que no esperabas y perder esa información.

Y si tienes alguna otra sugerencia, no dudes en dejarla en los comentarios. 🙂

$ exit

Vigilando los logs con logcheck (I)

Todos los que conocen mi trabajo en administración de sistemas saben que soy un obseso de los logs (ficheros de bitácora, o ficheros de registro). Hoy empiezo un blog y lo haré hablando de ellos.

Aquellos que ignoran los logs suelen terminar poniendo cara de «¿cómo ha pasado esto?». Todo los servicios que corren en nuestros servidores pueden tener la necesidad de comunicarnos un problema, una incidencia o una información trivial. A falta de teléfono, oficina postal  o presencia de un servidor de correo correctamente configurado, la forma en la que la mayoría de estos servicios se comunican con «sus amos» es a través de los ficheros de log.

Su contenido no es siempre fácil de entender, entretenido o interesante. Pero ello no debe echarnos atrás. Tenemos que estar pendientes de ellos. Siempre cuento la anécdota de un amigo que se sentaba por la mañana con su café a leer los logs del día anterior. Es una  manera de hacerlo, aunque un tanto dura para mi gusto… 🙂

Para evitar esta tortura existen multitud de herramientas, más activas o más pasivas ante los eventos, más simples o más complejas de configurar, etc. Y en esto de la administración de sistemas cada maestrillo tiene su librillo. Posiblemente la solución ideal es la combinación de herramientas (logwatchswatchfwlogwatchlogstash, …), pero hoy sólo hablaré de mi preferida: logcheck.

Su funcionamiento es sencillo, algo clave en casi toda buena herramienta. Logcheck lee los logs que le indiques con cierta periodicidad, normalemente cada hora. Coge las líneas que no le hayas indicado anteriormente que son normales (en el próximo post daré los detalles) y te las manda en un correo. De esta forma «sólo» recibirás las entradas en los logs que tú no hayas «aceptado como normales».

Usar logcheck lleva un periodo de aprendidaze, para el propio logcheck. Nada más lo instales (en menos de una hora) enviará su primer «informe». Todas las líneas de log que no le hayas enseñado, un buen «pedazo de correo». Así que tendrás que empezar a decirle que líneas no quieres que te envíe. Para ayudarte en la tarea, en las distribuciones basadas en Debian encontrarás un paquete llamado logcheck-database que ya enseña a logcheck sobre las líneas más inofensivas de los servicios más comunes, ahorrándose un montón de trabajo. En las distribuciones basadas en RedHat/Fedora, el paquete de logcheck lleva ya incorporado las reglas de logcheck-database.

En cualquier caso los primeros correos de logcheck serán enormes y tus «lecciones» los irán reduciendo de tamaño. Con el paso del tiempo logcheck se limitará a enviarte esas líneas que nunca ha(s) visto y que bien deberás enseñarle o, y esto es la clave de logcheck, representan problemas o situaciones de las que debes estar informado. El mensaje que avisa de un fallo en la controladora de disco, de un intento de acceso a la máquina, de un error en la configuración de Apache, de un problema en el MySQL, etc…

En la práctica logcheck lee los logs como lo harías tú, ignorando los mensajes que no tienen importancia y dando importancia (al enviarlas por correo) a aquellos que no esperas. Con esta herramienta se cubre una parte muy importante de la vigilancia de logs, y por tanto de la administración de sistemas.

Como comentaba anteriormente, lo ideal es combinar herramientas. Hay un área importante que logcheck no cubre, el abuso. Yo puedo enseñar a logcheck que en mi servidor de correo son normales los mensajes que indican la entrada y salida de correo, y él ignorará dichos mensajes. Pero cuando un servidor de correo que mueve 3.000 mensajes al día, pasa a mover 3 millones, algo raro pasa y no será logcheck quien te avise, pues para él todo serán líneas que decidí debía ignorar. Otro tipo de herramientas, de resumen de logs, de gráficas de tráfico, de monitorización de actividad, deben cubrir ese hueco.

En mi siguiente post hablaré de su instalación y configuración, así como de algunos consejos de uso.

$ exit