Ceci est une ancienne révision du document !


Filtrer avec Amavis

Pour river leur clou aux virus et autres spams

Nous avons déjà pas mal protégé notre serveur, mais tout de même…

  • les virus peuvent encore passer ;
  • les blacklists ne suffisent pas à limiter le spam.

L'idéal serait de pouvoir connecter notre Postfix à des outils comme Clamav et Spamassassin, pour améliorer encore notre bien-être. Amavis est là pour répondre à cette question.

Connexion d'Amavis Amavis va servir de glue pour passer les messages entrants à des filtres comme Clamav et Spamassassin. Nous allons mettre CLamav à l'œuvre. Spamassassin.

Le module smtpd va se connecter à Amavis par une connexion TCP sur le port 10024 par défaut. Lorsqu'un message entrera sur smtpd, ce dernier le transmettra au service amavisd.

Celui-ci va filtrer le message en le passant à Clamav (et à Spamassassin s'il est en état de fonctionner).

Amavis va alors retransmettre un message à smtpd toujours par une connexion TCP, sur le port 10025 par défaut. Ce message retransmis pourra avoir plusieurs formes suivant le cas :

  1. le message est sain, il est retransmis tel quel.
  2. le message contient un virus. Dans ce cas, Amavis mettra le message en quarantaine, enverra une notification au destinataire pour l'avertir qu'un message vérolé lui a été envoyé et éventuellement une notification à l'envoyeur pour lui signaler que son message n'a pas été remis. L'administrateur du site pourra également être notifié.
  3. le message est supposé être un spam, il est alors marqué comme tel, puis remis dans la chaine de distribution. Il est en effet malvenu de détruire ce qui est supposé être un spam, la détection étant toujours approximative (faux positifs). Suivant le « score » que spamassassin aura attribué au message, l'attitude pourra tout de même évoluer. Ainsi un message recevant un score sans appel pourra être tout de même détruit.

Clamav et accessoires

Debian stable c'est bien, mais ça vieillit parfois assez mal. Ce n'est souvent pas très gênant, sauf pour des applications comme Clamav ou Spamassassin. Le dépôt « volatile » est là pour pallier cet inconvénient. Il y a toute une série de miroirs dans le monde, choisissez celui qui vous convient et ajoutez-le à votre source.list.

Il faut installer :

# aptitude search clamav | grep ^i
i   clamav                          - anti-virus utility for Unix - command-line
i A clamav-base                     - anti-virus utility for Unix - base package
i   clamav-daemon                   - anti-virus utility for Unix - scanner daem
i A clamav-freshclam                - anti-virus utility for Unix - virus databa
i   clamav-testfiles                - anti-virus utility for Unix - test files  
i A libclamav4                      - anti-virus utility for Unix - library     

Clamav-testfiles est optionnel, il fournit des fichiers de test.

Spamassassin

Spamassassin mériterait à lui seul tout un chapitre. Nous nous contenterons ici de la configuration par défaut, juste pour vérifier que notre montage fonctionne.

Amavisd-new

Passons à la glue :

~# aptitude install amavisd-new
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances... Fait
Lecture de l'information d'état étendu        
Initialisation de l'état des paquets... Fait
Lecture des descriptions de tâches... Fait  
Construction de la base de données des étiquettes... Fait
Les NOUVEAUX paquets suivants vont être automatiquement installés : 
  libarchive-tar-perl libarchive-zip-perl libberkeleydb-perl libcompress-zlib-perl libconvert-binhex-perl 
  libconvert-tnef-perl libconvert-uulib-perl libio-multiplex-perl libio-stringy-perl libio-zlib-perl 
  libmailtools-perl libmime-perl libnet-cidr-perl libnet-server-perl libtimedate-perl libunix-syslog-perl 
Les NOUVEAUX paquets suivants vont être installés : 
  amavisd-new libarchive-tar-perl libarchive-zip-perl libberkeleydb-perl libcompress-zlib-perl 
  libconvert-binhex-perl libconvert-tnef-perl libconvert-uulib-perl libio-multiplex-perl libio-stringy-perl 
  libio-zlib-perl libmailtools-perl libmime-perl libnet-cidr-perl libnet-server-perl libtimedate-perl 
  libunix-syslog-perl 
0 paquets mis à jour, 17 nouvellement installés, 0 à enlever et 0 non mis à jour.
Il est nécessaire de télécharger 1772ko d'archives. Après dépaquetage, 5468ko seront utilisés.
Voulez-vous continuer ? [Y/n/?] 
...

Ce n'est pas parce que c'est installé que ça va coller tout seul. Nous avons un /usr/share/doc/amavisd-new/README.postfix.gz qui va bien nous aider à l'interfacer avec Postfix.

Configuration d'Amavis

La configuration d'amavisd-new sur Debian est une chose finalement assez amusante à faire. Tout est dans /etc/amavis/conf.d

# ls -l /etc/amavis/conf.d/
total 56
-rw-r--r-- 1 root root  1458 2007-02-24 19:30 01-debian
-rw-r--r-- 1 root root   692 2007-02-24 19:30 05-domain_id
-rw-r--r-- 1 root root   235 2007-02-24 19:30 05-node_id
-rw-r--r-- 1 root root 13907 2007-02-24 19:30 15-av_scanners
-rw-r--r-- 1 root root   554 2007-02-24 19:30 15-content_filter_mode
-rw-r--r-- 1 root root  9187 2007-02-24 19:30 20-debian_defaults
-rw-r--r-- 1 root root   573 2007-02-24 19:30 25-amavis_helpers
-rw-r--r-- 1 root root  2130 2007-02-24 19:30 30-template_localization
-rw-r--r-- 1 root root  1223 2008-06-23 14:19 50-user

Bref, il y en a dans tous les coins, à nous de nous y retrouver.

Comme dans toute critique d'un bon roman à « suspense » ou d'un bon jeu d'action, il faut bien se garder de déflorer l'intrique, aussi vous laisserais-je le soin de vous y retrouver…

Juste un ou deux indices cependant, histoire de ne décourager personne :

  • tous les fichiers de configuration sont lus, les un après les autres, par ordre alphabétique ;
  • lorsqu'une directive de configuration est donnée plusieurs fois dans des fichiers différents, c'est la dernière lue qui a raison ;
  • le fichier 50-user est, en l'état, le dernier à être lu ;
  • tous les autres sont susceptibles d'être modifiés lors d'une mise à jour d'amavisd-new.

Tirez-en les conclusions qui s'imposent.

Antivirus et Antispam

En lisant le fichier /etc/amavis/conf.d/15-content_filter_mode, vous comprendrez probablement que pour activer l'appel de l'antivirus et de l'antispam :

use strict;

# You can modify this file to re-enable SPAM checking through spamassassin
# and to re-enable antivirus checking.

#
# Default antivirus checking mode
# Uncomment the two lines below to enable it back
#

#@bypass_virus_checks_maps = (
#   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);


#
# Default SPAM checking mode
# Uncomment the two lines below to enable it back
#

#@bypass_spam_checks_maps = (
#   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

1;  # insure a defined return

Nous allons bien nous garder de le faire, mais allons plutôt ajouter ces lignes dans 50-user :

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

Tags artistiques

Il y a un fichier bien intéressant à lire : /etc/amavis/conf.d/20-debian_defaults, car il contient bon nombre de paramètres de configuration d' Amavis. Dans les grandes lignes, mieux vaut garder cette configuration, sauf que :

  1. si vous désirez que les tags posés par spamassassin soient systématiquement ajoutés dans les en-têtes de messages, ça n'ira pas ;
  2. si vous voulez que les spams ne soient jamais éliminés, mais simplement marqués comme tels, ça n'ira pas non plus ;
  3. si par la suite, vous souhaitez, comme nous le ferons dans le chapitre suivant, utiliser des domaines « virtuels » vos tags risquent de ne jamais apparaître.

En effet, Amavisd-new ne retranscrit les tags de spamassassin que pour les messages à destination des domaines référencés dans la variable (liste) @local_domains_acl.

De plus, la variable $sa_kill_level_deflt définit le score à partir duquel nous sommes « surs » qu'un message est un spam, et la variable $final_spam_destiny indique quoi faire de ce message dans pareil cas.

Dans la configuration par défaut (allez fouiller dans /etc/amavis/conf.d/20-debian_defaults), vous constaterez que si un message obtient un score >= 100, il est « D_BOUNCE » ce qui veut dire qu'il est mis en quarantaine locale et que le destinataire ne reçoit rien. Certes, un score de 100 est assez significatif mais tout de même, peut-être souhaiterez-vous vous montrer plus libéral.

La variable @local_domains_acl telle qu'elle est configurée devrait faire l'affaire ici, mais n'ira pas dans le cas de domaines virtuels. Vérifiez tout de même, en cas de refus de tags de la part d'amavis, de vérifier que le problème ne vient pas de là. La configuration suivante :

@local_domains_acl = ( "." );

Permettra d'effectuer le marquage des tags antispam quel que soit le domaine de destination.

Enfin, les variables $sa_tag_level_deflt et $sa_tag2_level_deflt ont leur importance sur la façon dont le message est marqué, de même que $sa_spam_subject_tag a un effet direct sur l'esthétique du message remis.

Voici un exemple de 50-user

#
# Place your configuration directives here.  They will override those in
# earlier files.
#
# See /usr/share/doc/amavisd-new/ for documentation and examples of
# the directives you can use in this file
#
#@local_domains_acl = ( "." ); # éventuellement, en cas de soucis

@bypass_virus_checks_maps = (
   \%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);

@bypass_spam_checks_maps = (
   \%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);

$sa_tag_level_deflt = -9999;     # note minimale pour ajouter les tags X-Spam... à l'en-tête des emails
                                 # ici, nous sommes à peu près surs que le tag sera toujours présent
$sa_tag2_level_deflt = 5.0;      # note minimale pour ajouter le tag X-Spam-Flag: YES
                                 # et modifier l'objet
$sa_kill_level_deflt = 100;      # note à partir de laquelle les mails sont traités comme définis
                                 # par la variable $final_spam_destiny (ici ils sont acceptés)
$sa_spam_subject_tag = '[SPAM]'; # chaine ajoutée à l'objet de l'email
$final_spam_destiny       = D_PASS;

# Pour ne pas en dire trop sur les armes employées
$X_HEADER_LINE = "spam & virus filtering at $mydomain";


#------------ Do not modify anything below this line -------------
1;  # insure a defined return

Configuration de Postfix

Jusqu'à présent, nous avons pu éviter de toucher à master.cf. Maintenant, il va falloir y aller.

Ce fichier de configuration permet essentiellement de configurer les divers services fournis par Postfix, ainsi que des services annexes que l'on peut lui rattacher. En gros, c'est un outil pour faire de la chirurgie dans l'architecture de Postfix. Il est donc recommandé d'y aller avec précautions.

Nous allons juste faire ce qui est dit dans la documentation d'amavisd-new :

Dans master.cf

Il faut ajouter ceci à la fin du fichier :

#
# Amavisd-new 
#
smtp-amavis unix -      -       -     -       2  smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20

127.0.0.1:10025 inet n  -       -     -       -  smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o smtpd_data_restrictions=reject_unauth_pipelining
    -o smtpd_end_of_data_restrictions=
    -o mynetworks=127.0.0.0/8,,[::1]/128
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks

Ces deux paragraphes vont permettre la création des points d'accrochage entre le module smtpd de Postfix et le daemon Amavisd. De plus, il faudra modifier le fichier main.cf pour indiquer à Postfix que smtpd doit se connecter à Amavisd.

Les options (-o) indiquées ici surchargeront éventuellement celles qui seraient données dans main.cf pour les services en question, c'est à dire d'une part smtp-amavis et d'autre part le service smtpd attaché à amavis sur le port 10025.

Dans main.cf

Il y a juste une ligne à ajouter :

content_filter=smtp-amavis:[127.0.0.1]:10024

Enfin, comme le dit la documentation de Amavisd-new, il faut ajouter l'utilisateur clamav sous l'identité duquel le service de l'antivirus (clamd) tourne, au groupe amavis :

# usermod -a -G amavis clamav

Vérifications

Après avoir relancé amavis et forcé Postfix à relire sa configuration, vérifions que Amavisd-new tourne, Postfix (et Dovecot) aussi :

~# netstat -tap
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat        PID/Program name   
tcp        0      0 localhost:10024         *:*                     LISTEN     4280/amavisd (master) 
tcp        0      0 localhost:10025         *:*                     LISTEN     2532/master           
...
tcp        0      0 *:imap2                 *:*                     LISTEN     3536/dovecot        
tcp        0      0 *:smtp                  *:*                     LISTEN     2532/master         

Nous envoyons un message à test@nain-t.net et regardons l'en-tête du message reçu :

Return-Path: <machin@chose.truc>
Received: from cyrus.nain-t.net ([unix socket])
	 by cyrus.nain-t.net (Cyrus v2.2.13-Debian-2.2.13-10) with LMTPA;
	 Mon, 23 Jun 2008 14:20:47 +0200
X-Sieve: CMU Sieve 2.2
Received: from localhost (localhost [127.0.0.1])
	by cyrus.nain-t.net (Postfix) with ESMTP id B1DC080FF274
	for <test@nain-t.net>; Mon, 23 Jun 2008 14:20:47 +0200 (CEST)
X-Virus-Scanned: spam & virus filtering at cyrus.nain-t.net
X-Spam-Score: 0.644
X-Spam-Level: 
X-Spam-Status: No, score=0.644 tagged_above=-9999 required=5 tests=[AWL=0.644]
Received: from cyrus.nain-t.net ([127.0.0.1])
	by localhost (cyrus.nain-t.net [127.0.0.1]) (amavisd-new, port 10024)
	with ESMTP id D38UlkWl4ypt for <test@nain-t.net>;
	Mon, 23 Jun 2008 14:20:40 +0200 (CEST)
Received: from smtp20.orange.fr (smtp20.orange.fr [193.252.22.29])
	by cyrus.nain-t.net (Postfix) with ESMTP id 26C1880FF273
	for <test@nain-t.net>; Mon, 23 Jun 2008 14:20:39 +0200 (CEST)
Received: from me-wanadoo.net (localhost [127.0.0.1])
	by mwinf2018.orange.fr (SMTP Server) with ESMTP id 1DA561C00046
	for <test@nain-t.net>; Mon, 23 Jun 2008 14:20:37 +0200 (CEST)
Received: from jupiter.chose.truc (LSt-Amand-152-32-18-95.w82-127.abo.wanadoo.fr [82.127.57.95])
	by mwinf2018.orange.fr (SMTP Server) with ESMTP id F39901C000BA
	for <test@nain-t.net>; Mon, 23 Jun 2008 14:20:36 +0200 (CEST)
X-ME-UUID: 20080623122036997.F39901C000BA@mwinf2018.orange.fr
Received: from [172.16.129.245] (test-desktop.chose.truc [172.16.129.245])
	by jupiter.chose.truc (Postfix) with ESMTP id 8977EEA3
	for <test@nain-t.net>; Mon, 23 Jun 2008 14:20:36 +0200 (CEST)
Message-ID: <485F9514.4000807@eme-enseignement.fr>
Date: Mon, 23 Jun 2008 14:20:36 +0200
From: machin <machin@chose.truc>
User-Agent: Thunderbird 2.0.0.14 (X11/20080505)
MIME-Version: 1.0
To: test@nain-t.net
Subject: test des tags
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

ça taggue.

Si nous avions le temps, nous pourrions aussi envoyer un message identique à celui qui est fourni en exemple de spam avec spamassassin, pour constater que le travail est bien fait. De mêqme, nous pouvons aussi envoyer un exemple de virus fourni avec Clamav et constater qu'il est mis en quarantaine et non transmis au destinataire

Enfin, il faut s'assurer que le dossier de quarantaine ne va pas exploser. Peut-être faut-il écrire un script qui nettoie les messages trop vieux, ou même créer une poubelle sans fond (/dev/null) ?

Remarque

Il n'y a pas qu'Amavis qui permette l'interaction de Postfix avec des filtres de messages. Il y a aussi MailScanner. Sa méthode de rattachement à Postfix est bien plus simple (peut-être même un peu simpliste), mais pour ce que nous avons fait ici, MailScanner aurait pu suffire.