Archivo por meses: marzo 2014

¿Quién está usando mi swap?

El kernel Linux es muy propenso a mandar memoria de procesos a swap aunque «no estemos cortos» de memoria RAM. Simplemente por inactividad de un proceso durante cierto tiempo. Este comportamiento se puede controlar con un parámetro de sysctl (vm.swappiness). Os dejo como ejercicio leer un poco de él. 🙂

Hay ocasiones que la cantidad de swap usado nos hace preguntarnos ¿quién está ahí?. Desde la versión 2.6.32 (en distribuciones RedHat & cía.) y 2.6.34 en otras (en Debian eso es Wheezy o superior salvo que uses un kernel de backports) hay indicadores del uso de swap de cada proceso. Se trata de la entrada que empieza con VmSwap: en /proc/<PID>/status o las líneas Swap: en /proc/<PID>/smaps. Éstas últimas más detalladas pero inaccesibles a usuarios corrientes.

Basándome en esta información y trás días de desarrollo he creado este one-liner que nos mostrará (sin necesidad de root y ordenando por tamaño usado) los procesos que tienen parte de memoria en swap:

 for i in $( ls -d /proc/[0-9]* ) ; do SWAP=$(egrep --color '^VmSwap:[[:space:]]*[^0 ][0-9]* kB' "$i/status" 2>/dev/null ) && { cat "$i/cmdline" ; echo -n " (" $( basename $i ) ; echo -n "): " ; echo  $( echo $SWAP | tr -s ' ' | cut -d' ' -f2- ) ; } ; done | sort -t':' -k2 -n

Una versión más reducida, pero menos vistosa, sería esta otra:

find /proc/ -maxdepth 2 -name status -exec  grep -H VmSwap: {} \; | grep -v ' 0 kB'

La primera la podéis guardar en un alias o en un script llamado (p.e.) /usr/local/bin/whoswaps y así no tenéis que memorizarla. 😛

$ exit

Muerte a las claves por correo

Hace cosa de un mes empecé un pequeño proyecto para terminar con una práctica muy extendida, en mi profesión como administrador de sistemas y en general entre todo tipo de usuarios: enviar información sensible por correo.

Como todos sabemos el correo electrónico, por normal general, viaja por la red en claro. Es decir, alguien en el camino entre nuestro correo y su destinatario lo tiene muy fácil para ver su contenido. Una vez entregado el correo tampoco se suele almacenar cifrado. Así que si el ordenador en el que se almacena es infectado por un virus/troyano o robado, la información vuelve a correr peligro. Todos, en alguna ocasión, hemos recibido una clave por correo. Y allí quedó la clave para el resto de sus días. Yo me veo obligado a informar a clientes de claves de acceso o URLs que no deben ser públicas, y lo he hecho mal (por correo sin cifrar) mucho tiempo.

Onetimepaste es mi granito de arena para terminar con esta práctica. Una pequeña aplicación web donde puedes «pegar» la información sensible que deseas enviar  y a cambio te devolverá una URL para que sea accedida por el destinatario. En cuanto alguien visita la URL, la información almacenada se muestra Y se destruye. Es decir, sólo se puede ver una vez. Si la persona a la que envíes la URL para recuperar sus datos se encuentra con que ya no están cuando visite la dirección, sabréis que alguien lee vuestro correo, y que esa información ya ha sido comprometida. Todo esto se hace de forma segura y se basa en dos pilares muy importantes: un código muy sencillo (para un informático, claro) y la recomendación encarecida de instalarlo en un servidor de tu confianza. En la página del proyecto se dan más detalles y yo tengo una instalación que puedes usar libremente (si te fías de dejar datos en mi servidor).

Muerte a los adjuntos sin cifrar

Hoy he hecho pública la segunda versión de onetimepaste. Proporcionando la característica más solicitada desde su primera versión; la capacidad de enviar ficheros de forma segura. Siguiendo exactamente la misma lógica que con los mensajes, los ficheros se almacenan de forma segura hasta que alguien los solicita y posteriormente son eliminados del servidor. Un fichero Word con tu próximo libro para que lo revise tu editor, una foto que no debe circular mucho, un fichero de texto con claves, … sea lo que sea que no sea público 🙂

Debo dar las gracias a mis amigos Silvia y Dario por su gran ayuda con el PHP, cazando errores en el código y probando la aplicación como sólo Silvia sabe.

$ 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