Lutte contre les spams avant réception avec un outil OpenBSD : spamd

Trier les spams une fois qu'ils sont reçus, c'est pas mal. Mais embêter les spammeurs, c'est bon pour tout le monde 😋. Spamd fait semblant d'être un serveur mail afin de filtrer les spams et ralentir les spammeurs. Il a été écrit dans l'optique d'être très efficace et ne pas ralentir la machine. Bien sûr, il transmet les mails légitimes au serveur smtpd ensuite.

Ce qui est rigolo, c'est qu'il va communiquer tout doucement avec les spammeurs et leur faire dépenser inutilement temps et ressources 😊.

Enfin, avantage non négligeable, il est présent par défaut dans OpenBSD.

Comment ça marche?

Deux méthodes sont possibles et compatibles. La première consiste à laisser traîner sur le web une fausse adresse mail. Tous les messages envoyés à cette adresse sont émis par des robots spammeurs : l'origine de ces derniers est alors mise sur liste noire puis ralentie.

L'autre méthode est le "greylisting". Afin de reconnaître les pourriels, spamd va mettre en attente ceux qui contactent le serveur. Ils sont mis sur liste grise.

Il existe aussi un mode "blacklist only" pour ne piéger que des IP déjà sur des listes noires.

Normalement, un serveur expéditeur légitime réessaie automatiquement de délivrer le message après un certain temps. Lors du 2e essai, ce serveur est mis sur liste blanche et le message est correctement distribué. Tous ceux à qui vous avez écrit sont aussi mis sur liste blanche.

Les spammeurs ne vont pas réessayer de délivrer le message. Dans ce cas, ils seront oubliés après un délai assez long, et vous n'aurez pas reçu le spam.

Attention : Cette méthode, bien que très efficace, suppose que l'expéditeur fait les choses comme il faut. Ce n'est malheureusement pas toujours le cas, notamment pour certains sites marchands. Pensez-y. C'est heureusement facile d'ajouter un serveur sur liste blanche.

Vous devriez de toute manière utiliser une adresse poubelle comme guerrilamail dans ces cas de figure.

Afin d'enregistrer les vilains (et bons) expéditeurs, il faudra exécuter la commande spamd-setup régulièrement.

Mise en place

On commence par activer spamd au démarrage, en indiquant les options dont il aura besoin, puis on le lance :

# rcctl enable spamd
# rcctl set spamd flags "-v -G 25:4:864"
# rcctl start spamd

Le premier nombre correspond au nombre de minutes qu'un expéditeur doit attendre avant de réessayer de nous renvoyer son mail (puisque les spammeurs envoient des salves de mails très rapidement). Le second correspond au temps qu'une entrée reste dans la liste grise, et le dernier le temps pendant lequel une entrée restera sur la liste blanche (en heures).

En complément, je vous invite à activer spamlogd qui gardera en mémoire les expéditeurs légitimes de mail dans le temps sans repasser par la case "liste grise", tant que ces derniers envoient des mails régulièrement. Il enregistre aussi sur liste blanche les serveurs auxquels vous envoyez des messages. Attention, il faut bien avoir précisé le mot clé "log" dans la configuration du parefeu, comme précisé un peu plus loin.

# rcctl enable spamlogd
# rcctl start spamlogd

spamd se place juste avant smtpd. On va éditer la configuration du parefeu en conséquence. Il va envoyer à spamd tout le flux destiné au serveur smtp, qui relaiera ensuite le mail normalement s'il est légitime.

Voici ce qu'il faut donc ajouter dans /etc/pf.conf :

table <spamd-white> persist
table <nospamd> persist file "/etc/mail/nospamd"
pass in on egress proto tcp to any port smtp divert-to 127.0.0.1 port spamd
pass in on egress proto tcp from <nospamd> to any port smtp
pass in log on egress proto tcp from <spamd-white> to any port smtp

Dans l'ordre des lignes :

Voilà pour le parefeu. N'oubliez pas de le recharger :

# pfctl -ef /etc/pf.conf

Il est nécessaire de régulièrement charger la liste noire des spammeurs dans pf afin que spamd fonctionne bien. Nous allons nous servir d'une tâche cron pour ça. Saisissez # crontab -e, puis décommentez la ligne suivante :

~  *  *  *  *  /usr/libexec/spamd-setup

Le "~" permet de lancer à intervalles aléatoires la commande précédente 😉. Notez que c'est un nombre de minutes aléatoire, cette intevalle sera donc toujours inférieure à 1h.

Spamtrap

Vous pouvez piéger les spammeurs en laissant traîner sur le web une fausse adresse mail. Si spamd voit un message arriver pour cette adresse, alors il sait déjà que c'est un spam : il peut donc le mettre sur liste noire. Vous voilà protégés pour l'avenir.

Afin de glisser cette "adresse-piège" sur le web sans que ça soit visible par les humains, vous pouvez l'insérer ainsi dans le code html de votre site :

<a href="mailto:piege@chezmoi.tld"></a>

Sinon, copiez-la sur des pastebins publics.

Pour indiquer à spamd cette adresse piège, il faut ajouter les options suivantes à spamdb (attention au "b" final, ce n'est pas spamd). :

# spamdb -T -a 'piege@chezmoi.tld'

Bien entendu, cette adresse piège ne doit pas être créée et ne risque pas de servir à quiconque.

Utiliser des listes noires ou blanches pré-existantes

Les gens sympas, ça existe ! Ces derniers ont rassemblé une liste de spammeurs qu'ils rendent publique. Afin de les utiliser avec spamd, il faut éditer le fichier /etc/mail/spamd.conf.

Voyons l'exemple par défaut livré de base:

la liste nixspam

Dans le fichier /etc/mail/spamd.conf, nous mettrons les lignes suivantes :

all:\
        :nixspam
# Nixspam recent sources list.
# Mirrored from http://www.heise.de/ix/nixspam
nixspam:\
        :black:\
        :msg="Your address %A is in the nixspam list\n\
        See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\
        :method=http:\
        :file=www.openbsd.org/spamd/nixspam.gz

Au début du fichier, vous lisez all. Précisez ensuite le nom des listes qui seront utilisées et qui sont configurées en-dessous en les séparant par des ":". Nous allons en ajouter dans les paragraphes suivants.

Les listes peuvent être récupérées par spamd-setup en précisant leur URL, ou bien être des fichiers présents sur votre serveur.

Utiliser la liste noire de bsdly

Peter N.M.Hansteen publie une liste d'IP piégées avec ses propres SPAMTRAPS.

Il met sur liste noire les IP cherchant à télécharger trop souvent sa liste pour éviter les surcharges sur son serveur. On va donc les récupérer régulièrement en ajoutant à votre crontab, toutes les heures à 20 minutes passées :

20 * * * *   /usr/local/sbin/bsdly-spamd

Le script bsdly-spamd ne fait que récupérer la liste de Peter :

#!/bin/sh
# update bsdly.net traplist into DST
URL="https://www.bsdly.net/~peter/bsdly.net.traplist"
# alternative URL
#URL="https://home.nuug.no/~peter/bsdly.net.traplist"
DST=/var/db/bsdly.traplist
ftp -o "${DST}" "${URL}"

Ensuite, indiquez dans /etc/mail/spamd.conf d'ajouter le contenu du fichier /var/db/bsdly.traplist à la liste noire :

all:\
      :nixspam:bsdlyblack:
nixspam:\
      :black:\
      :msg="Your address %A is in the nixspam list\n\
      See http://www.heise.de/ix/nixspam/dnsbl_en/ for details":\
      :method=https:\
      :file=www.openbsd.org/spamd/nixspam.gz
bsdlyblack:\
      :black:\
      :msg="SPAM.  Your address %A has sent spam within the last 24 hours.  See http://www.bsdly.net/~peter/traplist.shtml for details.":\
      :method=file:\
      :file=/var/db/bsdly.traplist

Utiliser les listes noire et blanches de uceprotect

Le site uceprotect devrait vous plaire si vous n'aimez par les spams.

Ils proposent des listes d'IP mises à jour toutes les heures. Il est possible de récupérer les listes en entier comme on l'a fait avec bsdly.net.traplist, mais cela consommera moins de bande passante de ne récupérer que les changements avec (open)rsync. C'est mieux pour vous et pour uceprotect.

Dans le crontab, on appelle le script qui mettra à jour toutes les heures (Ne mettez pas à jour les listes plus souvent, sinon vous serez bloqués par leur serveur) :

10 * * * *     /usr/local/sbin/uceprotect-spamd 

Le contenu du script uceprotect-spamd est le suivant :

#!/bin/sh
RSYNC="/usr/bin/openrsync -a"
URLS="rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-1.uceprotect.net
rsync-mirrors.uceprotect.net::RBLDNSD-ALL/dnsbl-2.uceprotect.net
rsync-mirrors.uceprotect.net::RBLDNSD-ALL/ips.whitelisted.org"
OUT="/var/db/RBLDNSD-ALL/"
mkdir -p "${OUT}"
for URL in ${URLS}; do
      ${RSYNC} "${URL}" "${OUT}"
done

On charge ces listes dans /etc/mail/spamd.conf. Il y a des listes noires et des listes blanches :

all:\
      :nixspam:bsdlyblack:\
      rbldnsd-1:rbldnsd-2:rbldnsd-white:
...
rbldnsd-1:\
      :black:\
      :msg="Your address %A is listed on UCEPROTECT-Level 1\n \
      see http://www.uceprotect.net/en":\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/dnsbl-1.uceprotect.net
rbldnsd-2:\
      :black:\
      :msg="Your address %A is listed on UCEPROTECT-Level 2\n \
      see http://www.uceprotect.net/en":\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/dnsbl-2.uceprotect.net
rbldnsd-white:\
      :white:\
      :method=file:\
      :file=/var/db/RBLDNSD-ALL/ips.whitelisted.org

N'hésitez pas à faire un don à uceprotect.net, leur travail est impressionnant. 😃

Problèmes éventuels avec le greylisting

Trop de personnes utilisent encore un fournisseur de mail, comme Gmail. Ces derniers disposent de plusieurs serveurs et donc de plusieurs adresses IP. Malheureusement, le temps que l'adresse IP du premier serveur à tenter l'envoi d'un message soit mise sur liste blanche, c'est un autre de leurs serveurs avec une IP différente qui prend le relais. Au final, ils ne sont jamais mis sur liste blanche.

Ici, nous allons créer une liste des domaines pour lesquels on ne veut pas faire de greylisting.

Je vous propose de mettre sur liste blanche les adresses IPs des fournisseurs de mail relativement connus. Depuis qu'OpenBSD est disponible en version 6.3, nous pouvons utiliser la commande smtpctl spf walk très pratique pour récupérer ces informations.

Tout d'abord, on crée un fichier qui contient la liste des domaines à qui on épargne le greylisting. Ce fichier sera /etc/mail/nospamd_domains_list.txt :

gmail.com
hotmail.com
facebookmail.com
apple.com
microsoft.com
lists.openbsd.org
linkedin.com
freebsd.org
twitter.com
amazon.com
yahoo.com
yahoo.fr
live.fr
mail-out.ovh.net
mxb.ovh.net
gandi.net
laposte.net
protonmail.com

Complétez ce fichier à votre guise si vous remarquez que des serveurs restent indéfiniment sur liste grise.

Maintenant, on crée le script /usr/local/sbin/generate-nospamd qui va enregistrer dans le fichier /etc/mail/nospamd les IP des serveurs définis ci-dessus.

#!/bin/sh
# /usr/local/sbin/generate-nospamd
# Auteur :      prx <prx@si3t.ch>
# licence :     MIT
DOMAINS=/etc/mail/nospamd_domains_list.txt
WHITELIST=/etc/mail/nospamd
echo "#$(date)" > "$WHITELIST"
smtpctl spf walk < "${DOMAINS}" >> "$WHITELIST"
exit 0

Je vous invite à appeler ce script via /etc/daily.local afin de régulièrement mettre à jour la liste des IP. Ensuite, il faut penser à recharger la table dans le parefeu :

# /etc/daily.local
/usr/local/sbin/generate-nospamd
pfctl -t nospamd -T replace -f /etc/mail/nospamd

spamd en mode blacklist seul

Pour éviter le problème cité ci-dessus, et être sûr de n'embêter QUE les spammeurs sans gêner les expéditeurs légitimes, vous pouvez seulement faire tourner spamd en mode blacklist. On retire alors le greylisting, et on piège seulement les communications venant d'IP connues comme malsaines.

Pour cela, ajoutez le flag "-b" au lancement de spamd :

# rcctl set spamd flags -b

La configuration du parefeu est aussi à revoir : seules les IP dans la table "spamd" seront à piéger. Dans "/etc/pf.conf" :

table <spamd> persist
[...]
pass in on egress inet proto tcp from <spamd> to any port smtp \
     divert-to 127.0.0.1 port spamd

Vous ouvrirez ensuite le port "smtp" si vous en avez besoin. En effet, vous pouvez très bien héberger spamd sans avoir de serveur mail, rien que pour lutter contre le spam 😄

Enfin, reste à ajouter le flag "-b" à spamd-setup. Lancez "crontab -e" puis veillez à avoir cette ligne qui permet de lancer spamd-setup toutes les heure s:

~       *       *       *       *       /usr/libexec/spamd-setup -b

Consulter l'activité de spamd

Pour voir l'activité de spamd, lancez la commande spamdb pour voir apparaître des choses comme ça :

WHITE|62.4.1.33|||1462699174|1462699174|1465809574|1|0
GREY|182.70.43.24|abts-mum-dynamic-024.43.70.182.airtelbroadband.in|<Estella32@thunderguy.co.uk>|<toto@chezmoi.tld>|1473409924|1473424324|1473424324|1|0
GREY|14.183.132.63|static.vnpt.vn|<Abby5@toddelliott.com>|<kiki@chezmoi.tld>|1473410586|1473424986|1473424986|1|0

On peut lire dans l'ordre :

Il n'y a pas à dire, les "temps" sont illisibles pour les humains. Utiliser la commande date pour avoir un format lisible :

$ date -r 1462699174
    Sun May  8 11:19:34 CEST 2016

Pour manuellement mettre sur liste blanche une IP que vous savez valide, utilisez :

# spamdb -a "62.4.1.37"

Partager les informations entre deux instances de spamd

Puisque vous avez demandé à un(e) ami(e) d'être un backup au cas où votre serveur mail serait indisponible (n'est-ce pas ? 😊), il est important que son serveur ait connaissance des spammeurs détectés par votre spamd. Sinon, les spammeurs pourraient passer par leur backup pour vous délivrer des messages gênants.

Heureusement, spamd peut partager ses listes. Vous devez le lancer avec les options -Y et -y :

Éditez le fichier "/etc/rc.conf.local" en fonction pour obtenir par exemple :

spamd_flags=-y em0 -Y 211.217.177.100 -Y domaine.tld

Avant de relancer spamd, créez un fichier "/etc/mail/spamd.key" qui servira de clé partagée :

# dd if=/dev/random of=/etc/mail/spamd.key bs=2048 count=1

Tous les serveurs qui communiqueront entre eux devront avoir le même fichier. Envoyez-le donc à vos amis 😊.

Ouvrez dans votre parefeu et routeur le port 8025/udp (spamd-sync) au cas où il serait fermé.

#/etc/pf.conf
pass in quick on egress proto udp to any port spamd-sync

Enfin, relancez spamd :

# rcctl restart spamd