29 de Diciembre, 2004

Filtrando correo con sendmail, bogofilter y un milter

Pensaba poner la coletilla MFG (ya comenté que es una de las utilidades de centralizar correo), pero no sé en realidad de cuantos artículos se trataría la serie, así que en un principio iré escribiendo las cosas como se presenten.

Voy a explicar un poco como he montado bogofilter, un excelente filtro Bayesiano, para trabajar con sendmail, el servidor de correo, y además en OpenBSD. Si también tenemos en cuenta que esta no es la única forma de hacer las cosas, y que ni siquiera será la mejor :P, al menos que esta anotación me sirva como referencia personal de cómo hice las cosas.

Empezamos instalando bogofilter. Ya que mi prueba salió bien, voy a seguir jugando con los ports, imagino que hasta que rompa algo :D.

Para tener la última versión del paquete, sincronizamos con los ports de CURRENT (ante la duda, aquí lo explico), pero solo bogofilter. Esto es porque trabajo con 3.6 STABLE y me gustaría poder instalar todo lo posible desde paquetes binarios. Es decir, quiero un bogofilter a la última, aunque no me importa tanto en alguna de las dependencias.

La sincronización se hace con acceso anónimo al CVS de OpenBSD:

# cd /usr
# export CVSROOT=anoncvs@anoncvs3.usa.openbsd.org:/cvs
# export CVS_RSH=/usr/bin/ssh
# cvs checkout -P ports/mail/bogofilter

Y ahora sus dependencias. Vamos a usar DB4, por una cuestión de rendimiento y porque así lo recomiendan los desarrolladores:

# cvs checkout -P ports/databases/db

Aunque necesitamos solo db4, tenemos que bajar todo el port de db.

Como ya pasó en mi anterior experimento, hay un problema al usar el db4 de CURRENT con:

@conflict db->=4,<5

Se puede eliminar esa linea sin problemas (en 3.6 STABLE no existe ese conflicto, aunque tendremos que llevar cuidado con esto para no acabar rompiendo algo, por ejemplo si nos pasamos a CURRENT: ojo).

Eso sí, queremos el paquete db4 sin soporte TCL:

# cd /usr/ports/databases/db/v4
# env FLAVOR="no_tcl" make package
# pkg_add /usr/ports/packages/i386/all/db-4.2.52p1.tgz

Ahora creamos el paquete de bogofilter:

# cd /usr/ports/mail/bogofilter/
# env FLAVOR="db4" make package
# pkf_add /usr/ports/packages/i386/all/bogofilter-0.92.8-db4.tgz

Bien, ya tenemos bogofilter instalado. Un factor interesante de los filtros Bayesianos es que no hay que actualizar el programa para que se adapte a nuevo spam, así que si no hay nuevas características interesantes o correcciones de seguridad, puede que no tengamos que reinstalar el paquete.

Ahora ponemos a punto la configuración de bogofilter. Copiamos el ejemplo desde /usr/local/share/examples/bogofilter/bogofilter.cf.example a /etc/bofogilter.cf y ajustamos la configuración. Yo me he limitado a descomentar una linea:

bogofilter_dir=/var/spool/bogofilter

De forma que se use la misma bbdd para todo el sistema. Pros y contras de esta decisión en otra anotación :).

Creamos la bbdd de bogofilter. Para ello necesitamos un número razonable de correos basura y de correos ham (legítimos; o no spam) en formato mbox, y que además sea representativo del correo que se recibe en todo el sistema.

Como basura empleo 785 mensajes que he ido acumulando en una semana, y como correo ham empleo anuncios de seguridad, el archivo de una lista de correo, y otros correos sin clasificar. De esta forma bogofilter tiene dos conjuntos más o menos significativos para comenzar a trabajar desde un punto más o menos eficiente.

Entrenar a bogofilter es muy sencillo:

# mkdir /var/spool/bogofilter
# bogofilter -s < mbox.basura
# bogofilter -n < mbox.ok

Ahora necesitamos que nuestro MTA (sendmail) procese cada correo entrante con bogofilter.

Para ello empleamos el interfaz milter que posee sendmail. Se trata de una especie de sistema de plugins bastante interesante que permite pasar a un programa externo al MTA cada uno de los datos de entrada que se dan en la sesión SMTP.

Miramos si nuestro sendmail lo tiene habiltado:

# sendmail -d0.1 -bv root | grep MILTER
 Compiled with: DNSMAP LOG MAP_REGEX MATCHGECOS MILTER MIME7TO8 MIME8TO7

Si no apareciera MILTER en la respuesta, tendríamos que seguir las instrucciones de nuestro distribuidor para compilar sendmail con soporte para libmilter. Compilar sendmail asusta un poco al principio, pero no es para tanto. Desde sendmail 8.13 (creo), el soporte milter viene por defecto activado.

Hay un milter escrito en Perl para bogofilter, pero no me gusta. Necesita un par de módulos, además de Perl con soporte de threads (experimental), y necesitaría ser modificado para usar una sola bbdd para todo el sistema (este emplea una bbdd por usuario).

Así que me he programado yo un milter en C siguiendo la documentación. Es muy sencillito, ojo. Tanto que solo espera a que se acabe de recibir el mensaje, se lo pasa a bogofilter, y añade la cabecera con el restultado del trabajo del filtro o, dependiendo del modo de ejecución, descarta o rechaza el mensaje en caso de que bogofilter lo clasifique como spam. Bueno, según vaya teniendo ratos igual llega a hacer más cosas ;).

Tampoco voy a recomendar a nadie que use mi milter :D, ni que se haga el suyo, pero ahí queda; lo que tiene que hacer, lo hace. Siempre se puede recurrir al milter en Perl, aunque me hubiera gustado tener más opciones para integrar bogofilter con sendmail vía milter. Eso es lo que me ha motivado a escribir el mío propio.

Se descomprime bogom, y puede que haya que editar el Makefile para ajustar alguna cosa (no me he calentado mucho la cabeza). Con PREFIX podemos decidir dónde se instalan los ficheros (por defecto en /usr/local).

En OpenBSD no tendremos que tocar nada. Hacemos:

$ make
$ su
# make install

En la página de manual que se instala (man bogom) podemos consultar la documentación del programa.

Añadimos el milter a la configuración de sendmail editando nuestro fichero mc:

INPUT_MAIL_FILTER(`bogom',\
`S=unix:/var/spool/bogofilter/milter.sock, T=S:30s;R:1m')

He puesto 30 segundos para que el filtro reciba el mail y 1 minuto para dar su respuesta, ambos valores máximos (si tarda menos, mejor). Puede que esos valores necesiten algún ajuste según el tipo y cantidad de tráfico que manejemos. Si el milter no está presente, los correos se entregan normalmente.

El modo de conexión es mediante socket UNIX, tal y como emplea bogom por defecto.

Regeneramos el cf como se indique en nuestro sistema. Al menos en los sistemas BSD esto no suele ser complicado, en algunos sistemas Linux no incluyen la infraestructura M4 para regenerar el cf, lo cual es malo y requerirá algún trabajo extra.

Creamos un usuario para correr el milter. Como planeo tener más filtros, creo un usuario y un grupo llamados 'milter' (en lugar del usuario bogofilter que recomienda bogom):

# groupadd milter
# useradd -g milter -c 'sendmail milter' -d /nonexistent\
 -s /sbin/nologin milter

Damos los premisos adecuados al directorio donde va a trabajar bogom:

# chown -R milter:milter /var/spool/bogofilter
# chmod 700 /var/spool/bogofilter
# chmod 600 /var/spool/bogofilter/wordlist.db

Ahora arrancamos el milter:

# /usr/local/sbin/bogom -u milter

Podemos comprobar que todo está correcto fácilmente:

# tail -1 /var/log/daemon
Dec 25 18:44:29 blackshell bogom[30519]: started: $Id: milter.c,v 1.2\
 2004/12/25 15:16:49 reidrac Exp reidrac $
# ls /var/spool/bogofilter/*.sock
/var/spool/bogofilter/milter.sock

Bien, solo falta hacer que sendmail recargue la nueva configuración:

# kill -HUP `head -1 /var/run/sendmail.pid`

Con esto tenemos ya a bogofilter fitrando nuestros correos y, gracias a bogom, añadiendo la cabecera X-Bogosity indicando si un mensaje es spam o no.

En un principio está ya es una buena configuración, aunque podemos emplear las opciones -R y -D para que los mensajes considerados spam se rechacen o descarten, respectivamente, o hacer que bogofilter aprenda solo.

Pero para eso ya recomiendo ojear la página del manual de bogom, para que este artículo no se alargue demasiado. Espero que la miga del asunto haya quedado más o menos clara.

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.