Greylisting en Postfix y Debian 7

correoNadie se acuerda de Santa Bárbara hasta que truena, que dice el refrán. Yo tenía pendiente configurar un sistema de Greylisting (listas grises) en mi servidor de correo pero no lo he visto como urgente e inmediato hasta el aumento inusitado de actividad de los bots de spam de los últimos días.

El Greylisting es, hoy por hoy, uno de los métodos más efectivos a la hora de controlar el spam y su funcionamiento es sencillo y fácil de entender. Cuando un servidor de correo recibe un mensaje anota en una lista tres datos que lo identifican (la IP desde donde viene, el correo del remitente y el del receptor) y a continuación lo rechaza indicando al emisor que lo intente de nuevo más tarde. Esto se hace con un código 45x:

-> MAIL FROM: <sender@somedomain.com>
<- 250 2.1.0 Sender ok
-> RCPT TO: <recipient@otherdomain.com>
<- 451 4.7.1 Please try again later

Si el mensaje ha sido enviado por un servidor SMTP legítimo reconocerá el mensaje de rechazo y en un tiempo predefinido (típicamente de 300 segundos) reenviará de nuevo el correo que, en este caso, será aceptado por el servidor del destinatario. Un bot preparado para enviar spam no realizará el segundo envío. De esta forma, si el correo no es spam llegará al destinatario con 5 minutos de retraso. Salvo este detalle el emisor no se enterará de nada (todo el trabajo se hace entre los servidores de correo sin que los clientes intervengan). Si el receptor abre la cabecera del mensaje recibido verá una línea parecida a esta:

X-Greylist: delayed 300 seconds by postgrey-1.34 at invernalia; Thu, 19 Sep 2013 16:30:33 CEST

El sistema de control del spam mediante Greylisting fue originalmente ideado por Evan Harris en este whitepaper de 2003. El señor Harris mantiene, además, una lista de implementaciones de su método para diversos servidores de correo. Si quieres más información conceptual sobre esta técnica, esta página y la entrada correspondiente de la wikipedia también tienen información interesante.

Si ya tienes una Debian con un servidor de correo postfix funcionando la implementación en perl del Greylisting es muy, muy fácil de poner en marcha. Basta con instalar el paquete postgrey y añadir check_policy_service inet:127.0.0.1:10023 en la lista de restricciones del fichero main.cf de configuración de postfix en el directorio /etc/postfix:

smtpd_recipient_restrictions = reject_unknown_sender_domain, reject_unknown_recipient_domain, reject_unauth_pipelining, permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination, check_policy_service inet:127.0.0.1:10023

Por supuesto, una vez hechas ambas cosas debemos de reiniciar el servicio postfix. La instalación nos ha creado un nuevo servicio llamado postgrey que arranca como daemon y escucha en el puerto 10023 y que responde a los argumentos habituales: start, stop, restart, reload, force-reload y status. En el directorio /etc/postgrey tenemos dos ficheros denominados whitelist_clients y whitelist_recipients donde, respectivamente, se pueden especificar las direcciones de ciertos servidores smtp o direcciones de correo que no se someteran al procedimiento de rechazo temporal de los mensajes y que se aceptaran al primer intento. Tenemos, además, un fichero donde se encuentra la configuración principal del servicio llamado /etc/default/postgrey que veremos más adelante.

Si observamos ahora el log de nuestro postfix (/var/log/mail.log) podemos estudiar el funcionamiento y si este es correcto. Cuando recibimos cualquier correo (salvo uno ya identificado como válido en las whitelist) será inmediatamente registrado y rechazado:

Al cabo de cinco minutos si el correo es legítimo el servidor remitente volverá a intentarlo y ahora el correo si será aceptado:

Puede que el servidor emisor se impaciente y antes de que transcurran esos cinco minutos vuelva a intentarlo. En ese caso el correo volverá a ser rechazado:

Como puedes observar en los mensajes del log, aparte de la razón del rechazo el servidor enviará una dirección web personalizada donde se informa detalladamente de lo que está ocurriendo:

mensaje de información de postgrey en castellano

Postgrey crea, además, una base de datos en el directorio /var/lib/postgrey donde guarda información acerca de los mensajes recibidos. Después de aceptar cinco mensajes de un servidor, este será automáticamente incluido en una whitelist de tal forma que, a partir de este momento, ya no se le volverá a exigir el trámite de los reintentos. Podemos consultar en cualquier momento los servidores de esta lista ejecutando el siguiente script:

perl /usr/share/doc/postgrey/postgrey_clients_dump

Y una ejecución de ejemplo:

Servidores incluidos en la whitelist de greylist

Tenemos aún pendiente ver el fichero de configuración principal: /etc/default/postgrey. En el podemos modificar, por ejemplo, el texto que aparecerá en el mensaje de rechazo:

POSTGREY_TEXT="Si tu sevidor funciona como debiera debería de intentar enviarme de nuevo el mensaje en 5 minutillos de nada"

También podemos enviar al demonio cualquiera de los argumentos que tenemos disponibles para modificar su funcionamiento (ver man postgrey) mediante el parámetro POSTGREY_OPTS. Por ejemplo, en la siguiente línea se dice al demonio que escuche en el puerto 60000, subimos el retraso para aceptar el mensaje a 600 segundos y le indicamos que incluya las direcciones de los clientes en la whitelist después de aceptarles 3 envíos:

POSTGREY_OPTS="--inet=60000 --delay=600 --auto-whitelist-clients=3"

Para terminar, si quieres comprobar la configuración de tu servidor de correo electrónico para ver si es vulnerable de alguna forma y puede ser usado como un Open Relay, si el correo saliente que envía puede verse bloqueado de alguna forma, etc. existen muchas herramientas en línea pero las más cómodas y completas, a mi juicio, son las de mxtoolbox y el test de allaboutspam.

ACTUALIZACIÓN: Los servidores de Microsoft (outlook, hotmail…) dan problemas con este sistema desde hace un tiempo. Aquí tienes como resolverlos.

Analizando el arranque de tu Linux con bootchart

herramientas ¿Qué es lo que hace tu Linux durante el arranque?¿Hay alguna forma de ver exactamente que se ejecuta, cuales son los procesos dependientes que genera y cuanto tiempo se invierte en cada uno de ellos de forma que podamos, si es necesario, saber donde tenemos que tocar para conseguir un arranque más rápido?

Bootchart es una herramienta que obtiene y procesa fácilmente esta información y genera como resultado un gráfico fácilmente interpretable. Como muestra, aquí tenéis la gráfica resultado en un servidor VPS con Debian 7 (ya sabes, pulsa sobre la gráfica para verla con mejor resolución):

Gráfica de bootchart 0.9 en un servidor VPS con Debian 7

La instalación básica en una Debian estable requiere dos paquetes (y sus dependencias): bootchart y pybootchartgui. El primero es el que recopila los datos y el segundo el que genera el gráfico a partir de ellos. bootchard se instalará por defecto en el directorio /sbin y su archivo de configuración se llama bootchard.conf y se encuentra en el directorio /etc. pybootchartgui se encuentra en el directorio /usr/bin/. Aunque tenemos muchas opciones interesantes para explorar, vamos a limitarnos a ver el funcionamiento tal y como queda recién instalado y sin tocar nada.

Una vez instalados ambos, tenemos que hacer que el kernel de nuestro Linux ejecute el proceso que realiza la recogida de datos lo antes posible y esto lo hacemos introduciendo dicha llamada directamente en GRUB. Si estamos en un equipo desde el que tenemos acceso directo a teclado y monitor lo más fácil es introducir a mano la opción necesaria en el momento del arranque. Para ello, una vez que nos aparece el menú de GRUB pulsamos la letra “e” (de editar) e introducimos la opción init=/sbin/bootchartd. De esta forma el proceso sólo se llamará en este arranque puesto que la opción no queda salvada:

Editando la entrada de Grub para invocar a bootchar

Si no tenemos acceso al teclado de la máquina en el momento del arranque (en un Hosting VPS, por ejemplo) el método pasa por introducir esta opción en los archivos de configuración de GRUB. El método es diferente según que usemos GRUB o GRUB2. En GRUB basta con editar el archivo /boot/grub/menu.lst, buscar el bloque correspondiente al kernel con el que qeremos realizar el arranque e introducir la misma opción que hemos visto antes. Por ejemplo, así:

title           Debian GNU/Linux, kernel 3.2.0-4-amd64
root            (hd0,0)
kernel          /boot/vmlinuz-3.2.0-4-amd64 root=/dev/vda1 ro quiet no-kvmclock init=/sbin/bootchartd
initrd          /boot/initrd.img-3.2.0-4-amd64

En GRUB2 tenemos que editar el fichero /etc/default/grub, buscar la línea etiquetada como GRUB_CMDLINE_LINUX_DEFAULT e incluir al final de lo que allí aparezca la opción de carga de bootchartd. Así, por ejemplo:

GRUB_CMDLINE_LINUX_DEFAULT="resume=/dev/disk/by-uuid/35a07870-ac1a-489f-a19b-629
6dca46903 init=/sbin/bootchartd"

En este segundo caso, una vez editado el fichero tendremos que ejecutar el programa update-grub para que los cambios tomen efecto.

Un cuarto método, disponible si estamos usando un equipo de escritorio con un gestor de ventanas instalado, es usar uno de los muchos programas existentes para configurar grub de forma gráfica. Por ejemplo, grub-customizer:

Configurando el arranque de bootchartd con grub-customizer

Sea cual sea el método que hayamos usado, en el próximo arranque se ejecutará bootchartd, pero no olvides que, salvo en el primer caso, cuando ya no quieras usarlo tendrás que deshacer los cambios efectuados.

Bien. Tras reiniciar la máquina se invocará al proceso llamado bootchartd que recogerá la información necesaria y la guardará en un archivo llamado bootchart.tgz en el directorio /var/log. Para crear el gráfico basta con invocar a pybootchartgui:

Generando el gráfico de bootchart con pybootchartgui

Nota que se toma por defecto la ubicación y nombre del archivo original y que, por tratarse este de un nombre genérico, cada vez que reiniciemos y/o generemos un nuevo gráfico machararemos los datos del anterior a menos que los renombremos manualmente o le echemos un vistazo a la forma de modificarlos mediante los parámetros en línea y/o opciones de configuración adecuadas. Y listo. A continuación tenéis otro ejemplo correspondiente a un servidor más modesto que el anterior montado sobre VirtualBox:

Gráfica de bootchart 0.9 en una máquina de virtualbox con Debian 7

En la paquetería de Manjaro Linux (e, imagino, que ocurre igual con Arch) se usa otro programa similar también llamado bootchart pero que, en realidad, integra en un sólo servicio la recolección de datos y la generación del gráfico final. El gráfico resultante presenta, además, algunos aspectos diferenciadores. Podéis ver una muestra en la siguiente imagen que corresponde con el arranque de un PC de escritorio:

Gráfica de bootchart 1,2 en un PC de escritorio con Manjaro Linux

Para usarlo basta instalar el paquete llamado bootchart. El programa que tendremos que invocar se llamará igualmente bootchartd pero en este caso reside en el directorio /usr/bin. Podemos usar cualquiera de los métodos anteriormente vistos para invocarlo pero el parámetro a incluir en las opciones de carga del kernel será init=/usr/bin/bootchard. El archivo de configuración también es sensiblemente diferente y está en el directorio /etc/systemd. Cuando reiniciamos la máquina, el archivo que bootchart genera es ya directamente un gráfico en formato svg. El directorio destino del mismo es, igualmente, /var/log pero en este caso el nombre incluye una marca de tiempo (por ejemplo bootchart-20130916-0800.svg) de forma que si realizamos sucesivos reinicios tendremos disponible una colección de gráficos para su posterior estudio sin necesidad de ninguna intervención manual.

Existe aún, al menos, otro tercer sistema similar a estos denominado bootchart2 y que, por el momento, no he tenido ocasión de probar. Ahí queda el enlace por si alguien se anima…

NOTA: Desde hace ya unos meses estoy usando Manjaro Linux (con Openbox como window manager) como distribución de escritorio, tanto en mi ordenador de sobremesa como en mi portatil. Manjaro es una distribución rolling release, muy, muy ligera basada en Arch Linux que me está gustanado bastante, así que previsiblemente hablaremos bastante de ellas en lo sucesivo.

Plugins de memcached y bind9 para munin

herramientasEl otro día dejamos munin instalado y funcionando con los plugins más comunes que vienen de serie y se configuran de forma automática sin (casi) necesidad de manipulación extra alguna. El principal problema que vamos a encontrar con esta herramienta de monitorización es que cuando tratemos de instalar alguno de los centenares de plugins adicionales de que dispone nos encontraremos, según el caso, una información bastante irregular en cuanto a la forma en que tenemos que hacerlo: dependencias, configuración, etc. Hoy vamos a instalar un par de estos plugins adicionales de forma manual y así conoceremos un poco mejor sus tripas y veréis claramente a lo que me refiero.

La primera herramienta que debemos de conocer a la hora de añadir plugins adicionales es munin-node-configure, un script que nos ayuda a identificar que plugins nos pueden resultar útiles y ayudarnos a instalarlos. Como ya vimos, la instalación base de munin identifica muchos de los elementos que pueden resultarnos útiles y los configura e instala, pero si existe algún requisito o dependencia adicional para que funcionen no es capaz de resolverlo aunque si deja un mensaje informándonos de ello si usamos el parámetro --suggest. No suelen ser muy descriptivos y suele hacer falta hacer uso de Google para encontrar la solución (por ejemplo, si te falta la librería libcache-cache-perl para que funcione el plugin de MySQL el mensaje que aparece es “Missing dependency Cache::Cache”), pero bueno, algo es algo.

Para configurar el plugin de bind9 no necesitamos instalar nada adicional, pero si hacer algunos cambios en la configuración de nuestro servidor DNS. En el archivo named.conf.options (típicamente en el directorio /etc/bind) tenemos que introducir la siguiente línea dentro del bloque de options:

statistics-file "/var/cache/bind/named.stats";

Y añadir al final del fichero el siguiente bloque:

logging {
        channel b_query {
                file "/var/log/bind9/query.log" versions 2 size 1m;
                print-time yes;
                severity info;
        };
        category queries { b_query; };
};

A continuación creamos el directorio /var/log/bind9, le damos permisos de escritura al usuario bind, reiniciamos el demonio de nuestro servidor DNS y ejecutamos el comando rndc stats. Con esto el servicio dejará los logs detallados de estadísticas de consultas en ese directorio. A continuación tenemos que configurar el plugin de munin para que las lea y nos las muestre de forma gráfica. Para ello editamos el fichero /etc/munin/plugin-conf.d/munin-node y añadimos los siguientes bloques:

[bind9]
user root
env.logfile   /var/log/bind9/query.log

[bind9_rndc]
user root
env.querystats /var/cache/bind/named.stats

Por último, creamos un enlace a los plugins en el directorio de configuración como explicábamos el otro día:

ln -s /usr/share/munin/plugins/bind9 /etc/munin/plugins/bind9
ln -s /usr/share/munin/plugins/bind9_rndc /etc/munin/plugins/bind9_rndc 

Y ya sólo nos queda reiniciar el demonio munin-node. Casi inmediatamente tendremos una nueva categoría de gráficos dedicada a la monitorización de nuestro servicio de nombres:

Plugin de bind9 para munin

La configuración del plugin para memcached es bastante más sencilla. Lo primero que debemos de hacer es instalar el paquete libcache-memcached-perl (en una debian o derivada). A continuación añadimos el siguiente bloque en el archivo /etc/munin/plugin-conf.d/munin-node:

[memcached_*]  
env.host 127.0.0.1  
env.port 11211  
env.timescale 3

Creamos los enlaces:

ln -s /usr/share/munin/plugins/memcached_bytes /etc/munin/plugins/memcached_bytes
ln -s /usr/share/munin/plugins/memcached_counters /etc/munin/plugins/memcached_counters
ln -s /usr/share/munin/plugins/memcached_rates /etc/munin/plugins/memcached_rates

Reinciamos munin-node y ya:

Plugin de memcached para munin

NOTA: Tienes información bastante detallada acerca del fichero de configuración munin-node, las opciones que admite y su significado en este enlace.