AntiSPAM con SpamAssassin : Configuración multiusuario

Como vimos en la primera parte de la guía, todos los parámetros de SpamAssasin son para todo el sistema, así que si un usuario quiere por ejemplo, bajar la puntuación mínima para que un mensaje sea catalogado como spam, no podrá.

Vamos a generar mucha información, y la almacenaremos en nuestra base de datos MySQL, lo primero será crear una nueva base de datos y dar privilegios a un nuevo usuario con contraseña generada:

$ pwgen # To generate a password
$ mysql -u root -p*********** localhost
mysql> CREATE SCHEMA SpamAssassin;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON SpamAssassin.* TO 'spamassassin'@'localhost' IDENTIFIED BY '4ubnIt5Jn16U'; 
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE `SpamAssassin`.`userpref` (
  `id` int(8) unsigned NOT NULL auto_increment,
  `username` VARCHAR(255) NOT NULL default '',
  `preference` VARCHAR(64) NOT NULL default '',
  `value` VARCHAR(128) default NULL,
  `description` VARCHAR(255) DEFAULT NULL,
  `created` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `author` VARCHAR(128) NULL,
  `modified` TIMESTAMP NULL,
  UNIQUE KEY `id` (`id`),
  KEY `type` (`preference`),
  KEY `author` (`author`),
  KEY `preference` (`preference`),
  KEY `username` (`username`)
) ENGINE=MyISAM COMMENT='Spamassassin Preferences';

Ahora, antes de instalar la base de datos para los datos bayesianos, el SQL de la versión 3.3.2 de SpamAssassin (la que se usa para esta guía), no es compatible con MySQL 5.5.2 (usa TYPE=MyISAM en lugar de ENGINE=MyISAM), por lo tanto, tenemos que convertirlo, una forma fácil para hacerlo es la siguiente:

$ sed 's/TYPE=MyISAM/ENGINE=MyISAM/' /usr/share/doc/spamassassin/sql/bayes_mysql.sql > bayes_mysql_tmp.sql

O descarga el archivo desde aquí (en formato sql.gz) Ahora, ejecutamos ese fichero en MySQL:

$ mysql -uroot -p****** SpamAssassin < bayes_mysql_tmp.sql

Ahora, lo que tenemos que hacer es decirle a SpamAssassin que utiliza la base de datos MySQL. Además, nuestros usuarios son usuarios de sasl y no del sistema; además, cada dirección de correo corresponde a un usuario diferente, por lo tanto tenemos que hacer que SpamAssasin coja los usuarios correctamente antes de sacar la información de la base de datos.

Para configurar MySQL, creamos /etc/spamassassin/sql.cf, y escribimos lo siguiente:

user_scores_dsn                  DBI:mysql:SpamAssassin:localhost:3306
user_scores_sql_username         spamassassin
user_scores_sql_password         4ubnIt5Jn16U
user_scores_sql_custom_query     SELECT preference, value FROM _TABLE_ WHERE username = _USERNAME_ OR username = '$GLOBAL' OR username = CONCAT('%',_DOMAIN_) ORDE$

bayes_store_module               Mail::SpamAssassin::BayesStore::SQL
bayes_sql_dsn                    DBI:mysql:SpamAssassin:localhost:3306
bayes_sql_username               spamassassin
bayes_sql_password               4ubnIt5Jn16U

Aquí estamos configurando la base de datos de puntuaciones de usuarios (user_scores) y la de datos bayesianos. La información de conexión se encuentra en el campo ***_dsn, cuyo formato es:

DBI:[motor, para nosotros, mysql]:[base de datos, en este caso, SpamAssasin]:[host, en el ejemplo, localhost]:[puerto, 3306]

Ahora, rellenaremos el nombre de usuario, contraseña y en user_scores_sql_custom_query especificamos la consulta MySQL que debe realizarse para traer la configuración de MySQL para el usuario que se esté consultando. En este caso, traeremos tres tipos de preferencias:

  • $GLOBAL : Vale para todos los usuarios, es la configuración por defecto
  • %dominio.ext : Configuración para todos los usuarios del dominio
  • usuario@dominio.ext : Configuración específica para ese usuario

El resto de los campos serán de uso interno, para tener cierto control sobre el cambio de las variables de configuración (siempre me gusta saber cuándo se creó un dato, cuándo se modificó, quién lo hizo y si es posible tener una descripción o un motivo del cambio, mejor)

Ahora, cambiaremos el contenido de /usr/local/bin/spamfilter.sh para pasar un usuario a spamc, aunque ahora surgen algunos problemas:

  • los argumentos que, tal y como dice /etc/postfix/master.cf se le pasan a /usr/local/bin/spamfilter.sh son: -f remitente@dominio.ext — dest1@dominio.ext dest2@dominio.ext dest3@dominio.ext …
  • algunos de los destinatarios puede que no sean usuarios de nuestro sistema (y no tendrán configuración en nuestro sistema). Si el mensaje tiene varios destinatarios, algunos pueden ser de nuestro sistema y otros no
  • debemos escoger sólo un destinatario perteneciente a nuestro sistema.

Para escoger la dirección de correo de la lista de argumentos (hay que recordar que debe ser la dirección de uno de nuestros usuarios). He creado un sencillo programa en C++ (podemos usar un script, pero creo que así será más rápido cuando tenemos mucho volumen de correo).

user_selector.cpp (lo puedes descargar aquí .cpp.gz):

#include <iostream>
#include <string>
#include <vector>
#include <fstream>

using namespace std;

typedef vector<string> Taddresses;

int readAddresses(Taddresses &addr)
{
        ifstream f;
        string tmp;

        f.open("/etc/postfix/vhosts", ifstream::in);
        if (!f.is_open())
                return 1;

        while (f>>tmp)
        {
                if (tmp!="")
                        addr.push_back(tmp);
        }
        return 0;
}

bool testAddr(Taddresses addrs, string addr)
{
        size_t atpos=addr.find_first_of("@");
        if (atpos==string::npos)
                return false;

        string domain = addr.substr(atpos+1);
        for (int i = 0; i<addrs.size(); i++)
        {
                if (addrs[i] == domain)
                        return true;
        }

        return false;
}

int main()
{
        bool start=false;
        string s;
        Taddresses addrs;
        readAddresses(addrs);

        while (cin >> s)
        {
                if ( (start) && (testAddr(addrs, s)) )
                {
                        cout <<s<<endl;
                        return 0;
                }
                if (s == "--")
                        start=true;

        }
        cout << "defaultUser"<<endl;
        return 1;
}

Lo compilamos:

$ g++ -o user_selector user_selector.cpp

Y lo colocamos en /usr/local/bin/user_selector

Ahora editamos /usr/local/bin/spamfilter.sh

#!/bin/bash
USER=`echo $@ | /usr/local/bin/user_selector`
/usr/bin/spamc -u "$USER" | /usr/sbin/sendmail -i "$@"
exit $?

Ahora tendremos configuración anti-spam por usuario, siendo el usuario uno de los tres especificados anteriormente ($GLOBAL, %dominio.ext, usuario@dominio.ext)

Aquí vemos algunas de las posibles preferencias que podremos especificar:

  • use_razor2 : Utilizar la base de datos razor2 (valores: 0, 1)
  • use_bayes : Utilizar el filtro bayesiano para este usuario (valores: 0,1)
  • use_pyzor : Usar la base de datos de pyzor (valores: 0,1)
  • skip_rbl_checks : No probamos en listas negras online (0, 1)
  • required_hits : Puntuación requerida para marcar un mensaje como no deseado
  • whitelist_from : Dirección de correo o máscara (usuario@dominio.ext o *@dominio.ext para marcar cualquier remitente dentro de ese dominio) que añadiremos a la lista blanca de usuarios de los que queremos recibir correo  (partirán de una puntación muy pequeña, o negativa)
  • blacklist_from : Igual que la lista blanca, pero para lista negra
  • rewrite_header : Reescribe el encabezado de los mensajes. Aquí podemos por ejemplo, cambiar el asunto del email.
  • score USER_IN_WHITELIST : Puntuación inicial para usuarios que están en la lista blanca.
  • score USER_IN_BLACKLIST : Puntuación inicial para usuarios que están en la lista negra.
  • score [TEST] : Establece la puntuación que da un determinado test de SpamAssassin.

Tenemos muchas más configuraciones para añadir, podrás encontrarlas en la documentación y los ficheros de configuración. Pero es fácil crear un interfaz web que haga que los usuarios cambien su configuración.

 

 

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *