Home >> Spam >> Non-filtrage de Spam basé sur le Message-ID

Non-filtrage de Spam basé sur le Message-ID

Dernière modification : 9 octobre 2004.
Première publication : 1er décembre 2003.

Je n’ai encore trouvé aucune page web parlant de la reconnaissance du type (spam/non-spam) basé sur son Message-ID. Et pourtant, Dieu ce que c’est fiable ! ! !

Cela fait quelque temps que j'en parle, mais malheureusement j'ai la flemme de me répéter a ce sujet, aussi j'ai fait cette modeste page. Malheureusement comme j'ai pas trop le temps en ce moment c'est un peu brouillon, et ça s'adresse surtout a des gens qui connaissent déjà procmail et le fonctionnement du mail. Si ce n'est pas votre cas, je conseille d'aller faire un tour sur Linux-France, ou tout ça est expliqué. Si il y a quelque chose que vous comprenez pas (mais que vous comprenez grosso-modo le reste), n'hésitez pas a m'envoyer un mail ou à participer au forum; ma réponse sera l'occasion de compléter et d'éclaircir la page, faites de même si vous avez des infos complétant le sujet. Avec un peu de bol je trouve le temps de compléter, et cette page sera un jour complètement traduite en Français...
En fait la méthode que je vais vous présenter ne permet que de savoir de manière assez précise qu'un mail n'est pas un spam, mais ne permet pas de savoir si on a affaire à un Spam. Avec ce que vous allez lire, vous devriez diviser par 4 le nombre de mail a faire traiter a votre anti-spam (donc pas mal diminuer le temps de traitement moyen d'un mail), et par 2 les faux-positifs. C'est pour cela que je parle de "non-filtrage". Tout cela suppose que vous utilisez déjà SpamAssassin par exemple, et que vous l'appelez via procmail (ou vous adaptez ce que je raconte à maildrop ou votre MDA).
Enfin, autre intérêt de la chose : vous n'allez pas avoir les headers que rajoutent les anti-spams à ces mails, et donc économiser de la place disque, voire de la BP (vision "économie de bouts de chandelles de la chose").

Le principe

Rappel : le message-ID désigne de manière unique un mail. Lire la RFC 822 si vous voulez en savoir plus a son sujet.
Le principe a déjà été évoqué ici ou là, mais personne n'est jamais passé à l'acte : utiliser le champ "Reference" ou le champ "In-Reply-to" pour détecter les hams.
Ces champs sont utilisés par les bons MUAs pour faire du threading ; le premier contient tous les Messages-ID des mails qui le précèdent dans le thread, le second uniquement le Message-ID du mail auquel il réponds, et sont mis en place par les "bons" logiciels. Environ 95% des mails parvenus en réponse à un autre mail ont l'un des deux champs (voire les deux); parmis les logiciels qui n'en mettent pas on citera les célèbres Microsoft Exchange et Lotus Notes. Si votre MUA ne met pas en place de tels champs, je ne peux que vous conseiller de le mettre a la poubelle, et d'en changer si c'est possible. Pour plus d'informations au sujet de ces champs, vous pouvez aller voir sur la page de D. Bernstein (attention, certaines pages de son site sont un peu "faussés").
Revenons donc a ces champs : lorsque nous recevons un mail, nous pouvons parfaitement regarder si l'un de ces champs contient le Message-ID d'un ham que nous avons reçu ou envoyé précédemment. Comme nous savons qu'il est très difficile voire impossible pour le spammeur de deviner les Messages-ID des mails légitimes recus précedemment, il ne pourra pas tenter de forger ce champ. Tout au plus pourra-t-il y mettre quelque chose dedans, mais en aucun cas y mettre un Message-ID d'un de vos hams (car comment le connaitrait-il ??). Donc tous les mails dont le champ References ou In-Reply-To pointe vers un ham sera un ham !

Ainsi sur les mailing-lists auxquels vous êtes inscrits (enfin celles qui sont pas filtrés contre le spam de manière efficace), seul le premier message d'un thread aura besoin d'être filtré par votre couteux anti-spam actuel.
Sur vos courriers personnels cela arrivera moins souvent, mais si vous reconnaissiez les Message-IDs de vos mails ? Ou si vous trouviez un moyen de stocker quelque part les Message-IDs des mails que vous avez envoyé ? Et bien nous allons voir ça aussi.

Les spammeurs vont-ils réussir a contourner ça ?

Un spammeur pourra tenter de vous envoyer un mail anodin, sans HTML, sans parler de Viagra, attendre que le message-ID soit mémorisé comme ham (puisque nous allons mémoriser les Messages-ID automatiquement, hors de question de le faire a la main, ou de regarder tous les anciens mails a la recherche de ceux-ci).
Mais pour le moment, je n'ai jamais vu de tels mails, et puis s'ils se mettaient a en faire, ça doublerait le nombre de mails qu'ils vont devoir envoyer, donc divisera par 2 le nombre de spams qu'ils pourront envoyer. Et dans ce cas cette vérification pourrait être intégrée dans SpamAssassin, comme un simple règle, ou bien on pourra changer les règles de mémorisation du Message-ID...

Quand au spammeur qui parviendra a ré-utiliser les règles que vous utilisez pour reconnaitre les Messages-ID des mails que vous auriez envoyés, il sera balaise. En fait c'est même impossible si l'algorithme générateur de Messages-ID de votre MUA est compliqué, ou si vous créez la base de données de Message-IDs a partir des mails reçus ceux que vous avez employés.

Techniquement

Base de données des Messages-ID

Je parle d'une base de données des Messages-ID de hams, mais comment la créer ? Je n'utiliserait par Oracle, rassurez-vous : le format le plus simple c'est un simple fichier texte, contenant un Message-ID par ligne, et sans les caractères '<' et '>' que l'on retrouve dans tous les Message-ID.
Pourquoi un tel format ? Simplement parce que l'on va utiliser fgrep (ou grep -F).

Création d'une base de données (pour procmail)

La méthode la plus simple pour créer votre base de données, sera la règle procmail suivante, qui mémorisera les messages-ids des hams (à placer après l'anti-spam donc) :

# Mettre les spams dans une boite a part
:0:
* ^X-Spam-Status: Yes
spam

# si ce n'est pas un spam, sauver le message-id
:0E c :message-id.block
| echo `formail -x Message-ID: | tr -d '<>[:cntrl:]' ` >> $MAILDIR/.message-id

Avec ça votre fichier "$MAILDIR/.message-id" ne fera que grossir, de temps en temps vous pourrez supprimer les premières lignes de celui-ci.

A la porcho avec postfix

Cette solution consiste à parser les logs (récents) de postfix, et de stocker TOUS les Messages-ID qui y sont trouvés dans un fichier. Et bien sur, j'ai rien trouvé de mieux que de faire ça avec un script appelé toutes les 3 minutes par la crontab. Ah oui, c'est crade !! smiley
Avec ca tous les mails envoyés et reçus par les utilisateurs du serveur seront utilisés, donc aussi tous les Spams. Dès que les spammeurs essayeront de contourner, ce sera cuit. Par contre du coup cette cochonnerie reconnait tous les Messages-IDs des mails que vous avez envoyés, sans autre effort supplémentaire.
Voici donc le code :

#!/bin/bash
sed -ne '/message-id/!d;s/.*message-id= *<\(..*\)>.*/\1/p' /var/log/mail.log* | sort -u > /tmp/message-ID

Et pour votre crontab :

*/3  * * * *  /usr/local/bin/liste-MID

Et formail ?

Les connaisseurs se demandent pourquoi ne pas utilier formail. L'option permettant de reconnaitre les doublons de formail fait a peu près ce que faisait la solution procmail !! Malheureusement il n'utilise pas un format parsable par fgrep, mais avec quelques modifications il en serait effectivement capable. Et on pourrait même imaginer lui permettre de vérifier directement si les champs References ou In-Reply-to pointent sur un des mails contenus la-dedans en une opération. J'ai pas envie de m'amuser a le patcher pour ça (en fait surtout pas le temps), mais vu que c'est la méthode la plus propre, je vous encourage a le faire (si je décide pas de le faire moi-même dès que j'ai du temps) !

Vérifier l'existance d'un Message-ID dans notre base de données

Bon, maintenant que la base de données est faite proprement, il n'y a qu'a faire le code pour vérifier si les champs References ou In-Reply-To pointent sur un de ces mails. Alors pour ça (en procmail) :

# Checker si References et In-Reply-To pointent sur un message-ID connu
REF_OK=no
REFERENCES="`formail -c -x References -x In-Reply-To: | tr -d '<>[:cntrl:]'`"
:0
* REFERENCES ?? @
* ? (echo $REFERENCES | fgrep -i -w -f /tmp/message-ID)
{ REF_OK=yes }

# Sinon, passer les anti-spams
# Ici juste un Spam-Assassin
:O E fw
| spamassassin

Je stocke dans une variable le fait que le nouveau mail ne passe pas le test, mais il faut dire que mon .procmailrc est assez complexe, avec pleins d'anti-spams et d'expériences de détection de spams dans tous les sens... D'ailleurs là j'ai simplifié pas mal l'appel aux anti-spams.

Si la votre base de données est triée (ce qui est le cas avec le script de la crontab), il est possible de se servir de cette propriété pour gagner un peu de temps CPU en faisant de la sorte (non testé):

formail -c -x References -x In-Reply-To | xargs printf "%s\n" | cut -f1 | sort -u | join Message-ID - | head -1

TODO : Faire ça proprement

Pour faire la reconnaissance et la sauvegarde des Message-ID recus personnellement, j'en ai déjà parlé, ça passerait par patcher formail (ou faire un utilitaire spécialement pour ça).
Mais là ou ça pourrait devenir intéressant, ce serait d'avoir un serveur de mail qui logue les Messages-IDs de tous les mails sortants (autrement dit s'occupe de créer la base de données), et permet a tout le monde de les utiliser (enfin, tant que le "tout le monde" n'est pas trop nombreux)... Du coup tous les mails sortants que l'on enverrait seraient inscrits dans la base, et comme ça, pas la peine d'appliquer avec ce qui va suivre.

A vos éditeurs de texte pour modifiez le code source de votre MTA préféré donc !!

Reconnaitre ses Message-IDs (ou ceux de ses amis).

Il y a plusieurs solutions pour reconnaitre ses Messages-IDs, dont entre autres :

Un Exemple (partez pas, vous allez encore apprendre des trucs)

Prenons le cas de l'Efrei (mon école).
Je regarde les Message-ID qui me parviennent de mes camarades pour commencer (Pour faire ça facilement, vous prenez mutt, vous rajoutez 'color header green default "^Message-ID:"' dans votre .muttrc, et les Message-ID seront mis en valeur. Puis vous appuyez sur 'h' pour voir les header, et z'aurez qu'a vous déplacer avec les touches habituelles pour faire ça très vite. Ou alors vous affichez carrement le Message-ID dans l'index des mails...). De là on constate que :

Maintenant on va mixer tout ça :

Remerciements

Les personnes suivantes m'ont aidés a améliorer cette page :

Je viens de constater à l'instant que chez certains FAI les Messages-IDs sont réécris (merci EVC!).

PS: j'ai trouvé ça pour faire mumuse avec les expressions régulières : regex-coach. Ca peut vous être utile, même si le format des regex n'est pas vraiment celui de procmail. Enfin de toute façon je suppose que si vous arrivez a comprendre cet article, les regex vous connaissez déjà...

Répondre à cet article

> Non-filtrage de Spam basé sur le Message-ID
1er septembre 2005, par mess-mate
Cela fait une paire de mois que j’utilise ce dé-spammeur :) Par contre j’arrive toujours pas à comprendre ce que fait le fichier /tmp/message-ID dans l’affaire, puisqu’il enregistre TOUS les message-id du log que procure postfix. A quoi sert-il donc puisque ce n’est que le fichier des bons message-id qui est utilisé ?
> Non-filtrage de Spam basé sur le Message-ID
17 mai 2005, par mess-mate

Rebonjour, j’ai ce message dans mes logs : Non-zero exitcode (1) from " (echo $REFERENCES | fgrep -i -f $MAILDIR.authorized_hosts)"

il manque un exitcode ?

> Non-filtrage de Spam basé sur le Message-ID
24 mars 2005, par mess-mate
Bonjour, dans la sendhooks de mutt, j’ai donc ajouté la my_hdr..... comme indiqué mais le Message-ID ne termine pas comme j’ai voulu. Le nom de machine y figure toujours alors que je voudrais y faire figurer le domaine uniquement. Y’a une raison à cela ?
> Non-filtrage de Spam basé sur le Message-ID
24 mars 2005

Peux-tu m’indiquer ce que tu as mis exactment dans le sendhook ? Et donner un des Message-ID ainsi généré ?

Sinon, si tu souhaites que seul le domaine apparaisse (et laisser à mutt le soin de générer tout seul le message-id selon son algo), tu as l’option : set hidden_host = yes

Enfin, dans certaines configurations, le MTA (sendmail, postfix, qmail, etc) remplace le message-ID par le sien.

> Non-filtrage de Spam basé sur le Message-ID
24 mars 2005, par mess-mate
j’ai mis ce qu’il y a dans votre texte : send-hook . my_hdr Message-ID :`date "+>%Y%m%d%H%m%S.\`pwgen -1\`@test>"` mais il-y-a toujours mon nom de machine qui apparait : mess.mydomain.com. J’utilise postfix qui me sert uniquement à envoyer les mails. Pour rapatrier les mails j’utilise fetchmail->mailfilter->procmail.
> Non-filtrage de Spam basé sur le Message-ID
25 mars 2005, par Maxime Ritter

Et est-ce que tu as bien installé pwgen ? (sous debian apt-get install pwgen).

Le Message-ID des mails sous mutt a quel forme ? <20050323140412.GA1983@sous-bock.netlibre.info> -> c’est mutt qui a généré le message-ID parce que le hook a échoué (ou autre chose ?). (La lettre G est fixe, puis suis une lettre majuscule, puis le PID du process de mutt. Au début, c’est la date). Si ton message-ID ne suit pas ce format, c’est postfix qui réécrit ton message-ID.

> Non-filtrage de Spam basé sur le Message-ID
24 mars 2005, par mess-mate
j’ai oublié de dire que j’ai pas ce problème avec sylpheed-claws. On coche ’without generation Message-ID’ et c’est le Message-ID de free.fr qui apparait. Par contre y’a pas de possibilité de mettre un autre Message-ID.
> Non-filtrage de Spam basé sur le Message-ID
3 avril 2005, par mess-mate
Pour mutt, j’ai trouvé smiley Au fait c’est le MTA qui change le message-id comme par exemple postfix. Il faut donc ordonné à postfix de ne pas changer le message-id. (Si cela a été fait avant par mutt biensûr) Ceci ne peut ce faire qu’avec la dernière version, la 2.2.2 !
> Non-filtrage de Spam basé sur le Message-ID
21 novembre 2005

Bonjour,

J’aimerais connaître l’algorithme de Message ID des 4 plus gros MTA’s sous Unix, à savoir Exim, PostFix, SendMail et Qmail.Je l’ai déjà pour Exim, et en partie pour SendMail, mais tout info supplémentaire est la bienvenue, mon but étant de produire un code capable de reconnaitre si le message ID d’un message est valide ou non.

Merci ! A+

Clément

 
Steves free web site templates Site réalisé avec SPIP Valid HTML 4.01!