SPF (Sender Policy Framework)
Référence RFC 7208 : syntaxe de l’enregistrement (mécanismes, qualificateurs, modificateurs, macros), algorithme d’évaluation check_host(), limites de requêtes DNS, codes de résultat et pièges courants.
SPF (RFC 7208) est un protocole d’authentification fondé sur le chemin : un domaine publie un enregistrement DNS TXT qui déclare quels hôtes sont autorisés à utiliser le domaine dans l’identité RFC5321.MailFrom (l’expéditeur d’enveloppe, « Envelope From » ou Return-Path) et, séparément, dans l’identité HELO/EHLO. Les serveurs de réception évaluent l’adresse IP du client qui se connecte par rapport à cet enregistrement.
Pour savoir comment SPF alimente l’alignement DMARC, voir DMARC.
Identités vérifiées
- Les vérificateurs DOIVENT vérifier l’identité
MAIL FROMsi aucune vérification HELO n’a été effectuée ou si elle n’a pas abouti à un résultat définitif. - Il est RECOMMANDÉ que les vérificateurs vérifient aussi, séparément, l’identité
HELO. LorsqueMAIL FROMest vide (rebonds,MAIL FROM:<>), le domaine HELO sert de domaine MAIL FROM (postmaster@<HELO domain>).
L’enregistrement
- Il est publié sous forme d’enregistrement DNS TXT sur le domaine vérifié. L’enregistrement doit commencer exactement par
v=spf1(par exemple,v=spf10ne correspond pas et est ignoré). Le type d’enregistrement DNS propre à SPF (type 99) a été rendu obsolète par la RFC 7208 : publiez uniquement du TXT. - S’il n’existe aucun enregistrement
v=spf1→ résultat none. S’il en existe plus d’un → permerror. - Les termes sont évalués de gauche à droite ; le premier mécanisme qui correspond détermine le résultat, selon son qualificateur. Si rien ne correspond et qu’aucun
redirect=n’est présent, le résultat par défaut est neutral (un?allimplicite).
Qualificateurs
| Qualificateur | Résultat quand le mécanisme correspond |
|---|---|
+ (par défaut s’il est omis) |
pass |
- |
fail |
~ |
softfail |
? |
neutral |
Mécanismes
| Mécanisme | Syntaxe | Sémantique | Requête DNS ? |
|---|---|---|---|
all |
all |
Correspond toujours. Placé en dernière position, il sert de valeur par défaut explicite (-all, ~all, …). Tout ce qui suit all est ignoré. |
Non |
include |
include:<domain> |
Évalue récursivement l’enregistrement SPF de <domain>. pass récursif → le mécanisme correspond ; fail/softfail/neutral → il ne correspond pas (l’évaluation continue) ; temperror/permerror se propagent ; none récursif → permerror. |
Oui |
a |
a[:<domain>][/<cidr4>][//<cidr6>] |
Correspond si l’IP du client est égale à un enregistrement A (IPv4) ou AAAA (IPv6) du domaine cible (par défaut : le domaine courant), éventuellement dans un préfixe CIDR. | Oui |
mx |
mx[:<domain>][/<cidr4>][//<cidr6>] |
Recherche les enregistrements MX de la cible, puis les enregistrements d’adresse de chaque nom MX ; correspond si l’IP du client en fait partie. | Oui |
ptr |
ptr[:<domain>] |
Vérification par DNS inverse validé. « Ce mécanisme NE DEVRAIT PAS être publié » : lent, peu fiable, obsolète dans la pratique. | Oui |
ip4 |
ip4:<network>[/<cidr>] |
IP du client comprise dans le réseau IPv4. Préfixe par défaut /32. |
Non |
ip6 |
ip6:<network>[/<cidr>] |
IP du client comprise dans le réseau IPv6. Préfixe par défaut /128. |
Non |
exists |
exists:<domain-spec> |
Développe les macros du domaine, puis effectue une requête A (même pour les connexions IPv6) ; correspond si au moins un enregistrement A est renvoyé. Permet des politiques par IP grâce aux macros. | Oui |
Longueurs de préfixe CIDR : IPv4 /0–/32 (par défaut /32), IPv6 /0–/128 (par défaut /128). Seul le nombre indiqué de bits de poids fort est comparé.
Modificateurs
Les modificateurs sont des paires nom=valeur ; chacun peut apparaître au plus une fois, n’importe où dans l’enregistrement.
| Modificateur | Syntaxe | Sémantique |
|---|---|---|
redirect |
redirect=<domain> |
Si aucun mécanisme n’a correspondu, l’évaluation se poursuit avec l’enregistrement SPF de <domain>, dont le résultat est repris tel quel. Si la cible de la redirection n’a pas d’enregistrement SPF, le résultat est permerror (et non none). Compte dans la limite de 10 requêtes. Ignoré lorsque l’enregistrement contient aussi all (puisque all correspond toujours en premier). |
exp |
exp=<domain> |
En cas de résultat fail, un enregistrement TXT est demandé pour ce domaine ; son texte, après développement des macros, est renvoyé comme explication lisible par un humain. Ne compte pas dans la limite de 10 requêtes. |
Macros
Le développement des macros (%{x}) est disponible dans les champs domain-spec et dans le texte de exp :
| Macro | Se développe en |
|---|---|
%{s} |
Expéditeur (adresse MAIL FROM complète) |
%{l} |
Partie locale de l’adresse de l’expéditeur |
%{o} |
Domaine de l’expéditeur |
%{d} |
Domaine en cours de vérification |
%{i} |
IP du client (notation décimale pointée pour IPv4 ; quartets séparés par des points pour IPv6) |
%{p} |
Domaine DNS inverse validé de l’IP du client (NE DEVRAIT PAS être utilisé : mêmes problèmes que ptr) |
%{v} |
in-addr pour IPv4, ip6 pour IPv6 |
%{h} |
Domaine HELO/EHLO |
%% / %_ / %- |
% littéral / espace / espace encodée pour URL (%20) |
Transformateurs : un chiffre limite le nombre de libellés conservés à droite (%{d2} → les deux derniers libellés) ; r inverse l’ordre des libellés ; d’autres caractères délimiteurs peuvent suivre.
Codes de résultat
| Résultat | Signification (RFC 7208 §2.6) | Traitement recommandé côté réception (§8) |
|---|---|---|
| none | Aucun domaine valide extrait, ou aucun enregistrement SPF trouvé | Aucune information ; non concluant |
| neutral | Le domaine n’affirme explicitement rien au sujet de l’IP (?) |
DOIT être traité exactement comme none |
| pass | Le client est autorisé à injecter du courrier pour le domaine | Le domaine est responsable ; poursuivre |
| fail | Le client n’est explicitement pas autorisé (-) |
Politique locale ; en cas de rejet, SMTP 550, code d’état étendu 5.7.1 |
| softfail | L’hôte n’est probablement pas autorisé (~) ; le domaine est en transition |
NE DEVRAIT PAS rejeter sur ce seul motif ; PEUT appliquer un examen plus attentif |
| temperror | Erreur passagère (généralement DNS) pendant l’évaluation | Accepter ou reporter ; en cas de report, SMTP 451, code d’état 4.4.3 |
| permerror | L’enregistrement publié n’a pas pu être interprété correctement (correction nécessaire par l’opérateur DNS) | En cas de rejet, SMTP 550, code d’état 5.5.2 |
Remarque pour DMARC : fail, softfail, neutral, none et les deux erreurs comptent tous comme non pass ; seul pass (avec alignement) peut satisfaire le volet SPF de DMARC.
Limites de requêtes DNS (§4.6.4)
| Limite | Valeur | En cas de dépassement |
|---|---|---|
Termes qui interrogent le DNS, par évaluation (include, a, mx, ptr, exists, redirect) |
10 au total, comptés sur toute la récursion via include/redirect |
permerror |
| « Requêtes vides » (void lookups : NXDOMAIN ou réponse vide) | DEVRAIENT être limitées à 2 | permerror |
Requêtes d’adresse par mécanisme mx |
10 noms MX | permerror |
Requêtes d’adresse par évaluation ptr |
10 noms PTR | Enregistrements au-delà des 10 premiers ignorés |
all, ip4, ip6 et exp ne comptent pas dans la limite de 10 termes.
Pièges courants
- Dépasser 10 requêtes. Les chaînes d’
includeimbriquées des fournisseurs de services de messagerie (ESP), des CRM et des outils de gestion de tickets s’additionnent vite ; le résultat est permerror, que DMARC traite comme une absence totale de SPF. Aplatissez les mécanismesincludeou retirez les prestataires inutilisés ; préférezip4/ip6, qui ne consomment aucune requête, àa/mxquand c’est possible. - Plusieurs enregistrements
v=spf1sur un même nom → permerror. Fusionnez-les en un seul enregistrement. +all(ou une valeur par défaut absente ou permissive) autorise l’Internet entier : c’est pire que pas d’enregistrement du tout. Terminez vos enregistrements par-allou~all.included’un domaine sans enregistrement SPF → permerror (none récursif). Vérifiez les includes de vos prestataires lorsque vous cessez d’utiliser un service.- Mécanisme
ptr/ macro%{p}— obsolètes, lents et peu fiables ; ne les publiez pas. - Le transfert casse SPF : l’IP du serveur de transfert ne figure pas dans l’enregistrement du domaine d’origine, donc SPF échoue après tout saut qui conserve le MAIL FROM d’origine. C’est inhérent à l’authentification fondée sur le chemin ; c’est pourquoi DKIM (fondé sur le contenu) est préféré pour que DMARC résiste au transfert, et c’est la raison d’être d’ARC.
- SPF pass ≠ DMARC pass : de nombreux ESP utilisent leur propre domaine de rebond dans le MAIL FROM, si bien que SPF passe mais n’est pas aligné avec le domaine From:. Pour l’alignement, utilisez comme Return-Path (adresse de rebond) un sous-domaine personnalisé du domaine From: — voir DMARC.
- Les chaînes TXT de plus de 255 caractères doivent être découpées en plusieurs chaînes entre guillemets au sein de l’enregistrement unique (elles sont concaténées) ; les gros enregistrements peuvent aussi imposer le DNS sur TCP.
- Un
redirect=aprèsallest du code mort :allcorrespond en premier.