C'est la suite de l'article sur Postfix et SPF parce qu'en pratique le protocole SPF
créé un nouveau problème lors du “forward” de mail.
Je vais proposer ma solution, parce que celles que j'ai pu glaner sur le Net ne me convenait pas. ~~READMORE~~
Comme vu précédemment, le protocole SPF permet de dire au Monde qu'elles sont les serveurs autorisés a émettre des e-mails pour un domaine.
Donc, les serveurs qui tiennent comptent du protocole SPF peuvent filtrer les mails, et même les refuser.
Lorsqu'on “forward” (ou relaye) un e-mail, par defaut, on ne touche a rien à e-mail: on trouve juste une trace du transfert dans les entêtes.
Exemple, soit dans une ligne d'un fichier “virtual” de Postfix :
xmartin@tjaouen.fr xmartin1234@dir.com
2 choses sont déterminant pour comprendre le problème!
Si le destinataire ne vérifie pas le protocole SPF: il n'y a aucun problème.
Si l'adresse de l'envoyeur n'appartient pas à un domaine qui gère le SPF: il n'y a aucun problème.
C'est le cas, par exemple, de Free.fr
, qui n'interdit pas de forger des adresses e-mails en utilisant son domaine “@free.fr”.
On peut le vérifier avec la commande spfquery
:
$ spfquery -ip=11.22.33.44 -sender=toto@free.fr StartError Context: Failed to query MAIL-FROM ErrorCode: (2) Could not find a valid SPF record Error: No DNS data for 'free.fr'. EndError none
Peu importe ip
, il n'y a pas de support du SPF
.
Voila que (From
) jojo@annu.com
veut envoyer un e-mail a (To
) xmartin@tjaouen.fr
.
Que ce passe-t-il ?
MX
de tjaouen.fr
.xmartin@tjaouen.fr
existexmartin1234@dir.com
MX
de dir.com
reçoivent le mail de la part des serveurs du domaine tjaouen.fr
.Et BANG .
Les serveurs de tjaouen.fr
ne sont pas autorisé a envoyer des e-mails From:jojo@annu.com
.
Une solution simple (un peu trop a mon goût) est proposé là: http://www.openspf.org/FAQ/Forwarding
Le SRS
permet de changer l'enveloppe et d'encapsuler le From
de tel sorte qu'on ait , à la fin , un domaine qualifié à envoyer des mails.
Par exemple, si on a un From:jojo@annu.com
, et sera modifié pour devenir:
From:SRS0=cccc=dd=annu.com=jojo@tjaouen.fr
Où , en gros :
cccc | un checksum pour empêcher des vilains de forger des mails |
dd | le jour de création (pour donner une durée de vie) |
On retrouve aussi annu.com
et jojo
…
Et surtout: @tjaouen.fr
en domaine d'envoi.
Les serveurs du domaine tjaouen.fr
sont bien autorisé a envoyer pour tjaouen.fr
!
Afin de ne pas trop polluer mes logs et écarter les effets de bords, je vais mettre en place un nouveau (sous) domaine qui sera dédier au SRS
.
Pour être clair: les mails forwardé avec SRS
utiliseront le domain srs-forward.tjaouen.fr
.
Et non simplement tjaouen.fr
.
Cela nécessite de préparer le DNS: Un enregistrement MX pour ce sous domaine.
Il faut aussi préparer Postfix
a accepter ce sous-domaine: même s'il est vide, et doit le rester.
(Car des mails utilisants le format “SRS” peuvent revenir, ne serait-ce des “bounce” ).
Aprés avoir testé quelques solutions (dont pfix-srsd
de l'ensemble pfixtools
),
j'ai écrit un petit scripte en Perl.
A mes yeux, ses avantages sont:
spawn
)Choses en dur (et pas forcément un mal) :
hash
est fixé à 6 (au lieu de 4 par defaut).hash
est fixé à 6.$SRSMAXAGE
) est laissé par defaut à 21 jours.Plus d'info: http://search.cpan.org/~shevek/Mail-SRS-0.31/lib/Mail/SRS.pm
Mail::SPF
et Mail::SRS
# aptitude update # aptitude install libmail-spf-perl libmail-srs-perl
version | Date | Download |
---|---|---|
0.9.2 | 31/03/2016 | http://reload.eez.fr/pub/bypass-srsd/bypass-srsd-0-9-2.zip |
0.9.1 | 12/12/2012 | |
$ cd /usr/local/bin $ wget http://reload.eez.fr/_media/bypass-srsd-0-9-1.zip $ unzip bypass-srsd-0-9-1.zip
Le scripte bypass-srsd
est dans le répertoire courant.
Verifier qu'il compile , sinon, vérifier les dépendances:
$ perl -c ./bypass-srsd
Assurez-vous qu'il est executable:
$ chmod a+x ./bypass-srsd
Créer un compte local sans droit, et dédié a l’exécution de ce scripte:
# adduser --system --no-create-home --group bypass-srs
Créer un secret: cela permet de créer un checksum unique pour chaque renommage via SRS.
(En fait, le jour suivant, le checksum sera different pour un même e-mail)
Par exemple:
# cd /etc/postfix # dd if=/dev/urandom bs=512 count=1000 | sha512sum - > bypass-srsd.key # dd if=/dev/urandom bs=512 count=1000 | sha512sum - >> bypass-srsd.key # dd if=/dev/urandom bs=512 count=1000 | sha512sum - >> bypass-srsd.key
Il faut que ce soit des lignes de textes, avec un contenu aléatoire dedans… |
Finir en mettant les bons droits, pour un secret:
# chown root:bypass-srs bypass-srsd.key # chmod 0440 bypass-srsd.key
Evidement, ce secret doit resté le même dans le temps ! sinon, les “decodage” SRS echoueront! |
A ce stade, on doit pouvoir répondre a quelques questions simples:
Mes reponses:
IP publique | 88.190.21.130 |
---|---|
HELO | mail.eez.fr |
Domaine SRS | srs-forward.tjaouen.fr |
Ce sont ces paramètres que je vais utiliser par la suite… pour mon cas bien sur !
Préparer l'éxecution du scripte en editant le fichier /etc/postfix/master.cf
, afin d'avoir:
# TJ -------------- # encode 127.0.0.1:10005 inet n n n - 0 spawn user=bypass-srs argv=/usr/local/bin/bypass-srsd --forward --srs-secret-key=file:///etc/postfix/bypass-srsd.key --quiet --fwd-domain=srs-forward.tjaouen.fr --fwd-ip-address=88.190.21.130 --fwd-helo-identity=mail.eez.fr # decode 127.0.0.1:10006 inet n n n - 0 spawn user=bypass-srs argv=/usr/local/bin/bypass-srsd --reverse --srs-secret-key=file:///etc/postfix/bypass-srsd.key --quiet --fwd-domain=srs-forward.tjaouen.fr # -----------------
Remplacer --quiet par --debug --verbose pour voir plus de chose dans les logs ! |
Les daemons attendront les requêtes sur les port 10005
et 10006
: adapter selon vos disponibilité!
Adapter /etc/postfix/main.cf
ainsi :
# --------------- # SRS Remapping # --------------- # bypass-srsd # Decode recipient_canonical_maps = tcp:127.0.0.1:10006 recipient_canonical_classes = envelope_recipient,header_recipient # Encode sender_canonical_maps = tcp:127.0.0.1:10005 sender_canonical_classes = envelope_sender # --- 127.0.0.1:10005_time_limit = 3600 127.0.0.1:10006_time_limit = 3600 # ---------------
Update 2014/05/09 : recipient_canonical_classes = envelope_recipient,header_recipient |
Aprés avoir rechargé ou redemarré Postfix
:
# postfix reload
ou
# /etc/init.d/postfix restart
Quelques tests:
Exemples:
$ host -t TXT emailing-newsletter.com emailing-newsletter.com descriptive text "v=spf1 +a +mx -all"
forward:
$ postmap -q "toto@emailing-newsletter.com" tcp:localhost:10005 SRS0=J8jhkM=KC=emailing-newsletter.com=toto@srs-forward.tjaouen.fr
reverse:
$ postmap -q "SRS0=J8jhkM=KC=emailing-newsletter.com=toto@srs-forward.tjaouen.fr" tcp:localhost:10006 toto@emailing-newsletter.com
Pour le “forward”, si la transformation “SRS” n'est pas necessaire, alors ne retourne rien (sauf si l'option --fwd-catch-all
)
Pour le “reverse”, si le reverse “SRS” fonctionne, alors retourne le resultat, sinon rien.
Les logs ( voir --debug
et --verbose
) peuvent expliquer les raisons.
Ou sinon:
$ echo "get toto@emailing-newsletter.com" | nc -q 5 localhost 10005 200 SRS0=J8jhkM=KC=emailing-newsletter.com=toto@srs-forward.tjaouen.fr
Encodage (forward) encore:
Par exemple avec free.fr
:
$ echo "get toto@free.fr" | nc -q 5 localhost 10005 500 No SRS needed
Effectivement: free.fr
n'utilise pas le protocole SPF.
$ echo "get toto@annu.com" | nc -q 5 localhost 10005 200 SRS0=fkIWI5=KC=annu.com=toto@srs-forward.tjaouen.fr
Effectivement: annu.com
utilise le protocole SPF.
Decodage (reverse) :
$ echo "get toto@annu.com" | nc -q 5 localhost 10006 500 reverse: can't parse 'toto@annu.com'
Effectivement: ce n'est pas un encodage SRS
(ne commence pas par SRS0
entre autre)
$ echo "get SRS0=fk8WI5=KC=annu.com=toto@srs-forward.tjaouen.fr" | nc -q 5 localhost 10006 200 toto@annu.com
Effectivement: l'encodage SRS est correct.
$ echo "get SRS0=fk8WI5=KC=annu.com=toto@annu.com" | nc -q 5 localhost 10006 500 reverse: Domain 'annu.com' not allowed
Effectivement: C'est le domaine srs-forward.tjaouen.fr
qui est attendu.
Option | Descriptions |
---|---|
--forward | encode en SRS: si toutes les conditions sont remplis |
--reverse | decode SRS : si toutes les conditions sont remplis |
--srs-secret-key= | code secret ou fichier contenant le code secret (préfixé avec : file:// ) |
--debug | trés bavard dans les logs |
--verbose | simplement bavard dans les logs |
--quiet | sans --debug et sans --verbose (ne log que les erreurs) |
--fwd-domain= | domaine dédié au SRS |
Option | Descriptions |
---|---|
--fwd-ip-address= | IP publique du serveur de mails |
--fwd-helo-identity= | Nom du serveur de mails, lors du HELO |
--no-spf-check | Désactive le test SPF avant d'appliquer le SRS. Le renommage SRS sera toujours fait. |
--spf-check | (Default:Yes) Active le test SPF. Le renommage SRS n'aura lieu que si le test échoue. |
--no-srs | Interdit le renommage SRS dans tout les cas. |
--srs | (Default:Yes) Active le renommage SRS, si toutes les conditions sont remplis. |
--fwd-catch-all | Repond a toutes demande de forward (au lieu de retourner: “500 je ne sais pas faire”) |
Option | Descriptions |
---|---|
--no-domain-strict | ne verifie pas le domaine: le décodage s'applique a tous les domaines |
pour info: ce n'est pas le service SRS que j'utilise, finalement. |
# aptitude install libev3 libev-dev libsrs2-0 libsrs2-dev libpcre3-dev
# cd /usr/local/src # git clone https://github.com/Fruneau/pfixtools.git # cd pfixtools # git submodule init # git submodule update # cd common # make # cd ../pfix-srsd # make
Un petit coup d'oeil sur le résultat:
# file pfix-srsd pfix-srsd: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped # ldd pfix-srsd linux-vdso.so.1 => (0x00007ffffdbff000) libsrs2.so.0 => /usr/lib/libsrs2.so.0 (0x00007fa4f4080000) libev.so.3 => /usr/lib/libev.so.3 (0x00007fa4f3e72000) libc.so.6 => /lib/libc.so.6 (0x00007fa4f3b0f000) libresolv.so.2 => /lib/libresolv.so.2 (0x00007fa4f38f9000) libnsl.so.1 => /lib/libnsl.so.1 (0x00007fa4f36e1000) libm.so.6 => /lib/libm.so.6 (0x00007fa4f345e000) /lib64/ld-linux-x86-64.so.2 (0x00007fa4f428d000)
Installer à la main:
# cp /usr/local/src/pfixtools/pfix-srsd/pfix-srsd /usr/local/bin/
Créer/modifier un fichier /etc/init.d/pfix-srsd
contenant:
#!/bin/sh ### BEGIN INIT INFO # Provides: pfix-srsd # Required-Start: $local_fs $remote_fs # Required-Stop: $local_fs $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: pfixtools SRS Daemon backend for Postfix ### END INIT INFO PFIXSRSD_CONFIG="/etc/default/pfix-srsd" NAME="pfix-srsd" DAEMON="/usr/local/bin/pfix-srsd" PID_FILE="/var/run/pfix-srsd.pid" if [ -f $PFIXSRSD_CONFIG ]; then . $PFIXSRSD_CONFIG else exit 0 fi test -x $DAEMON || exit 0 case "$1" in start) echo -n "Starting Postfix SRS Daemon: $NAME" start-stop-daemon -S -q -b -p $PID_FILE -x $DAEMON -- -p $PID_FILE $OPTIONS $DOMAIN $SECRETS echo "." ;; stop) echo -n "Stopping Postfix SRS Daemon: $NAME" if [ -f $PID_FILE ]; then kill `cat $PID_FILE` rm $PID_FILE fi echo "." ;; restart) $0 stop sleep 1 $0 start ;; force-reload) $0 restart ;; *) echo "Usage: $0 start|stop|restart|force-reload" exit 1 ;; esac
Rendre executable:
# chmod a+x /etc/init.d/pfix-srsd
Faire en sorte que le script soit executé au boot.
# update-rc.d pfix-srsd defaults
Créer un fichier /etc/default/pfix-srsd
contenant (à adapter):
DOMAIN=eez.fr SECRETS=/etc/postfix/pfix-srs.secrets OPTIONS=-I
Créer le fichier de secret (PS:il faut un fichier texte avec des lignes…):
# ( for(( i=0; $i<5; i=$[$i+1] )) do dd if=/dev/urandom bs=200 count=1 | sha1sum -b - ; done ) >/etc/postfix/pfix-srs.secrets # chmod 0400 /etc/postfix/pfix-srs.secrets # chown root:root /etc/postfix/pfix-srs.secrets
Il faut que ce soit des caractères “sha1sum like” , sinon, ça va deconner |
# /etc/init.d/pfix-srsd start
Encodage SRS sur le port 10001 Decodage SRS sur le port 10002
codage:
$ postmap -q "nobody@tjaouen.fr" tcp:localhost:10001 SRS0=NsPX=J6=tjaouen.fr=nobody@eez.fr
decodage:
$ postmap -q "SRS0=NsPX=J6=tjaouen.fr=nobody@eez.fr" tcp:localhost:10002 nobody@tjaouen.fr
Dans master.cf
: rien a faire. C'est un daemon indépendant.
Dans main.cf
:
# --------------- # SRS # --------------- # Decode recipient_canonical_maps = regexp:/etc/postfix/pfix-no-srs.regexp, tcp:127.0.0.1:10002 recipient_canonical_classes = envelope_recipient # Encode sender_canonical_maps = regexp:/etc/postfix/pfix-no-srs.regexp, tcp:127.0.0.1:10001 sender_canonical_classes = envelope_sender # ---------------
Le fichier pfix-no-srs.regexp
contient les regex des domaines à ne pas toucher par le SRS
.
Exemple:
# ------------------------------------------------ # __ _ # _ __ / _(_)_ __ _ __ ___ ___ _ __ ___ # | '_ \| |_| \ \/ /____| '_ \ / _ \ _____/ __| '__/ __| # | |_) | _| |> <_____| | | | (_) |_____\__ \ | \__ \ # | .__/|_| |_/_/\_\ |_| |_|\___/ |___/_| |___/ # |_| # # ------------------------------------------------ /^([^@]+@srs-forward\.tjaouen\.fr)$/ $1 /^([^@]+@eez\.fr)$/ $1 /^([^@]+@tjaouen\.fr)$/ $1 # ------------------------------------------------ # EOF
Recharger Postfix
:
# postfix reload
… et puis surveillez les logs !
Postfix
est mort)SRS
est appliqué a tout les mails.