Table des matières
SpamAssassin et apprentissage par les utilisateurs
Afin de soulager la vie de quelques usagés, on va mettre en place un système automatique pour apprendre a SpamAssassin a mieux reconnaitre les SPAMs, et a mieux reconnaitre les NON-SPAMs (les HAMs).
Pour que ça marche bien, il faut que les utilisateurs collaborent en soumettant eux-même ce qui est du “spam” ou du “ham”.
Il y a plusieurs méthodes, plus ou moins bien documentées (ou comprises !).
~~READMORE~~
la configuration Postfix sur laquelle repose ce blog-post est un peu ancienne mais est décrite par là |
Problèmes à résoudre
IMAP et POP3
D'abord, nos utilisateurs ne sont pas tous en IMAP: si c'était le cas, un simple script appliqué sur les répertoires “.Junk
” ou “.Spam
” pourrait être suffisant.
Non, quelques utilisateurs récalcitrants sont toujours en POP3 !
Frontaux
Sur notre mini-infrastructure, SpamAssassin
n'est pas en place sur le serveur final (mail.local.eez.fr
), mais sur des frontaux (mx0.local.eez.fr
et mx1.local.eez.fr
) .
Ainsi, tous les traitements lourds et nuisibles sont relégués loin des clients finaux.
Une solution
Vite dit
En fait, on va créer des comptes e-mails factices uniquement dédiés à la réception , en pièce jointes , des SPAMs ou des NON-SPAMs soumis par les utilisateurs.
Régulièrement, chaque frontal récupèrera les e-mails, via “fetchmail
” , et puis entrainera SpamAssassin
a ré-considérer les messages comme du SPAM ou du HAM.
Comptes e-mail SPAM et HAM
Il ne faut qu'ils soient accessibles par des vilains |
Serveur final
( le serveur qui livre les mails dans les comptes locaux )
Dans le fichier /etc/aliases
, on ajoute:
spam: /dev/null ham: /dev/null nospam: ham
“/dev/null
” est provisoire !
Pour l'instant, tout ce que reçoit “spam
” ou “ham
” va dans le trou noir du “/dev/null
”.
Ne pas oublier la mise à jour de la table aliases
:
# newaliases
Dans le fichier /etc/postfix/virtual
, on ajoute les adresses e-mail.
On peut préférer une variante en utilisant /etc/postfix/virtual.regexp
contenant:
/^spam@/ spam /^(ham|nospam)@/ ham
… ainsi, peut importe le domaine, ils ont tous les mêmes destinataire locaux.
Composer/modifier un fichier /etc/postfix/recipient_access.regexp
afin de limiter les accès aux boites.
# ========================================= # Limites sur le destinataire # (il faut faire de même sur tous les frontaux) # ========================================= # Limiter l'envoi a (spam|nospam|ham) /^spam(\+?.*)?@/i permit_mynetworks,reject /^nospam(\+?.*)?@/i permit_mynetworks,reject /^ham(\+?.*)?@/i permit_mynetworks,reject # --- misc ----- /^chamard@tjaouen.fr/ 550 Asshole close # ========================================= # EOF
Dans /etc/postfix/main.cf
, compléter l'instruction smtpd_recipient_restrictions
en ajoutant:
regexp:/etc/postfix/recipient_access.regexp
Ce qui donne pour moi (a titre d'informations) :
smtpd_recipient_restrictions = check_recipient_access regexp:/etc/postfix/recipient_restrictions.regexp permit_mynetworks permit_sasl_authenticated reject_unauth_destination regexp:/etc/postfix/recipient_access.regexp
(les autres options ne seront pas expliqués ici)
Et enfin:
# postfix reload
Faire de même sur les frontaux
Pour les frontaux, n'ajouter que les restrictions sur les adresses e-mails. C'est à dire:
- Composer le fichier
/etc/postfix/recipient_access.regexp
(voir ci-dessus) - Ajouter la restriction dans
/etc/postfix/main.cf
pour l'instructionsmtpd_recipient_restrictions
(voir ci-dessus)
Un bilan intermédiaire
A ce stade:
- Les mails a destination de “spam@xxx.xx” ou “ham@xxx.xx” ou “nospam@xxx.xx” sont livrés … a la poubelle.
- Il n'y a que les utilisateurs locaux (dans “mynetworks”) qui peuvent leurs envoyer des mails.
Comptes locaux (alias) SPAM et HAM des Frontaux
Retour sur le serveur “final” (celui qui détient les comptes mails).
Il s'agit uniquement de comptes locaux: personne n’envoie directement des mails dedans |
Créations
On va donc créer les comptes locaux dédiés à la collecte des SPAMs et des HAMs soumis par les utilisateurs.
Rappel: Dans notre cas, il s'agit de comptes “PAM”, et les commandes sont surement différentes pour d'autres configuration Postfix
.
Bref: 2 frontaux, et donc 4 comptes a créé: 2 SPAMs et 2 HAMs.
1er frontal nommé “mx0” :
# adduser mx0-spam # adduser mx0-ham
2ieme frontal nommé “mx1” :
# adduser mx1-spam # adduser mx1-ham
Aliases
Maintenant, on peut ajuster correctement le fichier /etc/aliases
:
spam : mx0-spam,mx1-spam ham : mx0-ham,mx1-ham nospam: ham
Recharger Postfix
avec la nouvelle configuration:
# newaliases # postfix reload
Test
A ce stade, ce qui est destiné à “spam@xxxx.xx” ou “ham@xxxx.xx” est dupliqué respectivement dans les comptes locaux, “mx0-spam” “mx1-spam” et “mx0-ham” “mx1-ham”.
( Dans notre configuration, les mails arrivent dans /home/<compte>/Maildir/new/
)
On en a terminé sur ce serveur.
: CRON pour vérifier que les mails sont bien relevés…
Les frontaux
Il reste a faire les choses suivantes, sur chaque frontal :
- Recuperation des mails
- Extraction des pièces jointes (qui sont des mails aussi)
- Re-apprentissage de
SpamAssassin
a partir de ces mails
Ce qui va suivre s'applique a chaque frontal.
On va expliquer uniquement comment faire pour le 1er, c'est à dire celui qu'on nomme “mx0”.
Introduction
Chaque frontal a déjà un compte local “debian-spamd
” dédié au traitement des SPAMs avec SpamAssassin
.
(Dans un précédent blog-post, ce compte était “spamc-nobody
”)
On va utiliser ce compte déjà existant pour faire le job.
Libre a vous d'en utiliser un autre (mais éviter “root” !).
Extraire les pièces jointes
Présentons d'abord le petit script pour extraire toutes les pièces jointes…
Le script
Le script Perl qui va extraire les pièces jointes est là:
- split-rfc822-attachment.pl ( ou son zip )
Il est inspiré de ce script: http://jmason.org/software/scripts/extract-rfc822-attachment.txt
Son fonctionnement:
$ split-rfc822-attachment.pl < message-mail /tmp/attachment
Dans cette exemple, toutes les pièces jointes du fichier “message-mail” sont alors extraites en multiples fichiers dans /tmp/attachment
.
Le but étant de récupéré les sources de chaque mail extrait, et non pas d'extraire et de reconstruire des documents.
il n'est surement pas parfait , mais il m'a semblé suffisant |
Mise en place
Scripts
On va le mettre , par exemple, dans /usr/local/bin
… donc:
# cp split-rfc822-attachment.pl /usr/local/bin/ # chmod a+x /usr/local/bin/split-rfc822-attachment.pl
Vérifier qu'il compile sans erreur:
# perl -c /usr/local/bin/split-rfc822-attachment.pl /usr/local/bin/split-rfc822-attachment.pl syntax OK
Répertoires
Ensuite, il faut choisir un endroit où on va déposer les pièces jointes “spam” et “ham”.
A la racine de l'utilisateur choisit (pour nous ce sera debian-spamd
), on aura:
- Pour le SPAM:
~/sa-retrain/spam
- Pour le HAM:
~/sa-retrain/ham
Créer et attribuer les “bons” droits a ces répertoires:
# su -s /bin/bash debian-spamd $ mkdir ~/sa-retrain $ mkdir ~/sa-retrain/{spam,ham}
Ceci fait, voyons la suite pour que les mails arrivent dans ces répertoires.
Récupération
La manière de récupérer des mails la plus évidente est simplement le protocole POP3
!
On va utiliser la commande fetchmail
pour récuperer les mails.
Problèmes
Mais il y a un petit hic:
Lorsque fetchmail
récupère un mail, il le livre au Postfix
local ! Ce qui a les conséquences suivantes:
- Des tags sont ajoutés aux mails
- Le mails est livré dans une
Maildir
oumbox
selon la configuration. SpamAssassin
va tagguer le mail !!!!
Il y a plusieurs manière de corriger cela, mais ça oblige a faire, encore et encore, des modifications dans Postfix
et SpamAssassin
.
Notre solution
Donc, on va faire plus simple: On va dire a fetchmail
de livrer a notre propre service de livraison, notre “MDA” à nous .
Rassurez-vous: Notre “MDA” sera un simple scripte (voir section suivant).
Notre "MDA"
Service rendu
En dehors d'être un faux (“fake”) “MDA” , il va:
- Extraire les pièces jointes en utilisant le script “
split-rfc822-attachment.pl
” Si il y a une erreur, envoi un mail d'information à l'envoyeur.: trouver autre chose.
Télécharger
Le script Bash de notre “MDA” est là:
- sa-retrain-fake-mda ( ou son zip )
Installation
On va le mettre , par exemple, dans /usr/local/bin
… donc:
# cp sa-retrain-fake-mda /usr/local/bin/ # chmod a+x /usr/local/bin/sa-retrain-fake-mda
Fetchmail
Installer
# aptitude update # aptitude install fetchmail
Note:
[warn] Not starting fetchmail daemon, disabled via /etc/default/fetchmail ... (warning).
On peut ignorer: Nous n'avons pas besoin d'activer le “daemon” pour que ça marche.
configurer
Retour en tant qu'utilisateur “debian-spamd
” (ou autres).
# su -s /bin/bash debian-spamd $
A la racine de la “HOME” :
$ cd ~
… on compose un fichier nommé .fetchmailrc
contenant:
# ---------------------- set postmaster root set no bouncemail #set syslog poll <HOST> protocol POP3 user mx0-spam there with password '<PASSWORD>' is debian-spamd here options ssl and wants mda "/usr/local/bin/sa-retrain-fake-mda spam %F %T" poll <HOST> protocol POP3 user mx0-ham there with password '<PASSWORD>' is debian-spamd here options ssl and wants mda "/usr/local/bin/sa-retrain-fake-mda ham %F %T" # ---------------------- # EOF
mx0-spam et mx0-ham | A adapter selon le compte e-mail associé au frontal |
<HOST> | Adresse du service “pop”. (Exemple: pop.local.eez.fr ) |
<PASSWORD> | Passe affecté au moment de la création du compte e-mail |
debian-spamd | … ou autre nom de compte (par exemple: spamc-nobody ) |
options ssl | Si on veut chiffrer les echanges. Voir configuration spécifique à SSL ici . |
Le fichier .fetchmailrec
contenant des mots de passe, il faut faire:
$ chmod 0700 .fetchmailrc
MDA: le script
L'instruction mda “sa-retrain-fake-mda spam %F %T”
dit:
- Utiliser ce script “
/usr/local/bin/sa-retrain-fake-mda
” (décrit plus haut) pour livrer les mails. - Passer les paramètres: “spam” ou “ham”, puis l'adresse de l'envoyeur, puis le compte du destinataire.
Comme dit plus haut, on force fetchmail
a utiliser “notre” propre “MDA”.
Tester
Maintenant, on doit avoir une chaine de transfert complète. (Reste juste une étape, voir juste après).
Pour tester:
Il suffit d'envoyer un e-mail avec un ou plusieurs e-mail en pièces jointes à l'adresse spam@…
ou ham@….
.
Par exemple, on envoi un mail avec 2 spams en pièces jointes.
Sur le serveur, on voit le mail:
Dans les logs:
Jul 18 06:05:21 mail clamsmtpd: 100174: from=<hidden>@<hidden>, to=spam@tjaouen.fr, status=CLEAN Jul 18 06:05:21 mail postfix/smtpd[25367]: disconnect from localhost[127.0.0.1] Jul 18 06:05:21 mail postfix/local[25373]: AC76454C4A: to=<mx0-spam@mail.local.eez.fr>, orig_to=<spam@tjaouen.fr>, relay=local, delay=0.26, delays=0.25/0.01/0/0.01, dsn=2.0.0, status=sent (delivered to maildir) Jul 18 06:05:21 mail postfix/local[25373]: AC76454C4A: to=<mx1-spam@mail.local.eez.fr>, orig_to=<spam@tjaouen.fr>, relay=local, delay=0.27, delays=0.25/0.01/0/0.01, dsn=2.0.0, status=sent (delivered to maildir) Jul 18 06:05:21 mail postfix/qmgr[23951]: AC76454C4A: removed
… mail qu'on retrouve dans chaque compte “spam” local:
# ls /home/mx{0,1}-spam/Maildir/new/ /home/mx0-spam/Maildir/new/: 1375020321.Vca02I408fM962049.mail /home/mx1-spam/Maildir/new/: 1375020321.Vca02I4090M967836.mail
Maintenant, on va sur l'un des frontals , et on récupère le mail en attente.
Sur le frontal:
Devenir l'utilisateur qui traite les SPAMs et les HAMs:
# su -s /bin/bash debian-spamd
Récupérer les mails en attente:
$ fetchmail 1 message pour mx0-spam dans pop.local.eez.fr (51924 octets). lecture du message mx0-spam@mail.local.eez.fr:1 parmi 1 (51924 octets) éliminé fetchmail: Aucun message pour mx0-ham dans pop.local.eez.fr
En vrai: fetchmail
râle parce que mon certificat “ssl” est auto-signé !
Voir solution ici.
On a bien récupéré le mail, mais il est où ?
Dans les logs on voit:
Jul 18 06:11:52 mx1 sa-retrain-fake-mda: spam From: <hidden>@<hidden> - OK
… le script “sa-retrain-fake-mda” a fait son boulot.
Les 2 pièces jointes sont bien extraites , et là:
$ ls ~/sa-retrain/spam/ -lart -rw------- 1 debian-spamd debian-spamd 26193 juil. 18 06:11 split-rfc822-0140259F035200DB7.2 -rw------- 1 debian-spamd debian-spamd 21896 juil. 18 06:11 split-rfc822-0140259F035200DB7.1
Reste a les faire apprendre à “sa-learn
”.
''sa-learn'' sur les mails
Enfin, il faut réaliser un script qui va traiter les “spam” ou les “ham” qui ont été précédement extraits des pièces jointe.
le script
Le script Bash qui va apprendre a partir des mails est là:
- sa-retrain-spamham ( ou son zip )
Ce qu'il fait:
- Regarde dans les répertoires
~/sa-retrain/{spam|ham}
- En fonction du nom du répertoire (“spam” ou “ham”), ré-apprend
SpamAssassin
que le mail est du “spam” ou du “ham”
Installer
# cp sa-retrain-spamham /usr/local/bin # chmod a+x /usr/local/bin
Tester
# su -s /bin/bash debian-spamd
Et puis:
$ sa-retrain-spamham sa-retrain-spamham: spam - /var/lib/spamassassin/sa-retrain/spam/split-rfc822-0140259F035200DB7.1 Learned tokens from 1 message(s) (1 message(s) examined) sa-retrain-spamham: spam - /var/lib/spamassassin/sa-retrain/spam/split-rfc822-0140259F035200DB7.2 Learned tokens from 1 message(s) (1 message(s) examined)
Dans les logs, on peut voir aussi:
Jul 18 06:31:58 mx1 sa-retrain-spamham: sa-learn - spam:2 ham:0
CRON
Maintenant que c'est fonctionnel, il suffit de démarrer tout ça dans un CRON.
# crontab -u debian-spamd -e
Et ajouter:
MAILTO=root */10 * * * * fetchmail >/dev/null ; sleep 1 ; /usr/local/bin/sa-retrain-spamham >/dev/null
Et ainsi, toutes les 10 minutes:
- Relève des mails et extractions des pièces jointes.
- Ré-apprentissage des SPAMs et des HAMs
sa-retrain-spamham peut être long. Un “lock” est présent pour écarter des accès concurrents |