← Blog

Macros SPF et mécanisme exists : aller au-delà de la limite des 10 lookups

Par Thomas · RSSI virtuel · 2026-07-15

La plupart des réponses à l'erreur « too many DNS lookups » cherchent à réduire le décompte : faire le ménage dans les include, remplacer par des ip4:, aplatir, découper en sous-domaines. Toutes partagent la même logique — rester sous la barre des dix. Il existe pourtant une technique d'une autre nature, qui ne réduit rien : elle contourne la limite. Une seule résolution DNS, mais un nombre potentiellement illimité d'adresses autorisées. Son secret : les macros SPF combinées au mécanisme exists. C'est puissant, c'est parfaitement standard, et c'est aussi mal compris que rarement expliqué. Ce guide décrit précisément comment ça marche, pourquoi ça échappe au plafond des dix, et surtout ce que tu échanges en retour — car rien n'est gratuit.

D'abord, un rappel : ce que compte vraiment la limite

Pour bien saisir l'astuce, il faut se souvenir de ce que borne la RFC 7208. Ce ne sont pas les adresses IP autorisées, mais les résolutions DNS déclenchées pendant l'évaluation de ton SPF. Chaque include:, a, mx, ptr ou exists: coûte au moins une requête ; les ip4: et ip6:, eux, sont des littéraux et ne coûtent rien. Dépasse dix résolutions et c'est le PermError : SPF cesse d'être évalué. Le mécanisme complet, avec ses effets de cascade sur les include imbriqués, est détaillé dans notre guide sur la limite des dix résolutions DNS.

Retiens ce point, parce que tout repose dessus : c'est le nombre de résolutions qui est plafonné, pas le nombre d'IP. Un mécanisme ip4: peut couvrir une plage entière sans jamais compter. Et un mécanisme exists: ne compte que pour une résolution — quel que soit le nombre d'adresses qu'il finit par autoriser. C'est exactement la faille dans laquelle s'engouffre la technique.

Le mécanisme exists, en deux mots

exists est le mécanisme SPF le plus méconnu. Sa définition est pourtant simple : exists:<domaine> demande au serveur destinataire de faire une requête A (adresse IPv4) sur le domaine indiqué. Si cette requête renvoie au moins un enregistrement A — n'importe lequel, la valeur importe peu —, le mécanisme matche. Sinon, il ne matche pas et l'évaluation continue.

Pris tel quel, avec un domaine fixe, exists n'a rien de spectaculaire. Toute sa puissance vient de ce qu'on met dans ce domaine : non pas une chaîne figée, mais une macro qui se réécrit à la volée, différemment pour chaque message reçu.

Les macros SPF : un domaine qui se réécrit tout seul

Les macros sont un pan entier de la RFC 7208 (section 7) que presque personne n'utilise à la main. Elles permettent d'insérer, dans un mécanisme, des variables qui seront remplacées au moment de l'évaluation par des données de la connexion en cours. Les plus utiles :

  • %{i} — l'adresse IP du client qui tente d'envoyer le message.
  • %{ir} — la même adresse, mais inversée (pour l'IPv4 203.0.113.5, ça donne 5.113.0.203).
  • %{d} — le domaine évalué.
  • %{v} — la chaîne in-addr pour de l'IPv4, ip6 pour de l'IPv6 (pratique pour distinguer les deux).

L'inversion de %{ir} n'est pas un caprice : elle reproduit la logique du DNS inverse (in-addr.arpa), où l'on lit l'adresse du plus spécifique au plus général. Résultat, chaque octet de l'IP devient un label DNS distinct, ce qui permet de construire des arborescences de zones fines. Tu commences à voir où on va.

Le cœur : une résolution, un nombre illimité d'IP

Assemble les deux pièces et tu obtiens ceci :

v=spf1 exists:%{ir}._spf.example.com -all

Un seul mécanisme à résolution, donc un seul lookup dans le décompte des dix. Mais observe ce qui se passe à l'évaluation. Un serveur reçoit un message dont l'IP émettrice est 203.0.113.5. Il réécrit la macro et interroge :

5.113.0.203._spf.example.com

À ce moment, c'est ton serveur DNS qui décide. La zone _spf.example.com, que tu contrôles, répond de deux façons possibles :

  • elle renvoie un enregistrement A (par convention 127.0.0.1) → le exists matche → l'IP est autorisée, SPF passe ;
  • elle renvoie NXDOMAIN (nom inexistant) → le exists ne matche pas → on tombe sur le -all, SPF échoue.

La bascule tient entièrement dans la manière dont ta zone répond à ces noms synthétiques. Tu peux y brancher une base de données de dizaines de milliers d'IP, une génération dynamique, des règles géographiques, une liste par expéditeur… Un lookup, N autorisations. La limite des dix n'est pas repoussée : elle est simplement hors sujet, puisque tu n'as plus qu'un seul mécanisme à résolution, et que l'intelligence a migré du fichier de zone vers la logique du serveur DNS.

C'est précisément ainsi que certains gros émetteurs offrent à leurs clients « un seul include, expéditeurs illimités » : derrière leur include se cache souvent un exists à macro qui autorise dynamiquement leur parc d'IP mouvant, sans jamais faire exploser le décompte de leurs clients.

Un exemple concret de bout en bout

Imaginons une entreprise qui émet depuis un parc d'IP vaste et changeant — plusieurs centres de données, des adresses ajoutées et retirées chaque semaine. En include classique, ce parc consommerait à lui seul l'essentiel du budget de dix, et le moindre ajout risquerait de faire basculer en PermError. Avec la technique des macros :

v=spf1 include:_spf.corp.example exists:%{ir}.%{v}._auth.example.com -all

Le include couvre la messagerie standard (Microsoft 365, par exemple, qu'on laisse maintenu par le prestataire). Le exists, lui, délègue tout le parc dynamique à la zone _auth.example.com. Le %{v} y distingue l'IPv4 de l'IPv6, si bien qu'une même règle sert les deux familles. Quand une IP émet, la zone consulte l'inventaire à jour et répond en conséquence. Ajouter mille adresses demain ne change rien à l'enregistrement SPF publié : il reste à deux mécanismes à résolution, loin sous la barre. La maintenance a quitté le DNS public pour l'inventaire interne — là où elle est de toute façon plus facile à tenir à jour.

Les contreparties (parce qu'il y en a)

Si cette technique était sans défaut, tout le monde l'utiliserait et l'erreur « too many lookups » n'existerait plus. Ce n'est pas le cas, pour de bonnes raisons.

Il te faut une zone DNS pilotable. Le exists à macro n'a d'intérêt que si ton serveur DNS peut répondre dynamiquement à des noms synthétiques qu'il n'a jamais vus. Un hébergeur DNS statique classique, où tu saisis des enregistrements un par un dans une interface, ne sait pas faire ça. Il te faut soit un DNS que tu programmes toi-même, soit un service spécialisé qui expose cette mécanique. C'est le vrai coût d'entrée.

Ton SPF devient opaque. Un auditeur qui lit exists:%{ir}._spf.example.com ne peut plus énumérer tes IP autorisées : l'ensemble a disparu du fichier de zone pour vivre dans la logique d'un serveur. C'est un recul de lisibilité assumé. Pour un domaine soumis à revue de conformité, cette perte de transparence n'est pas anodine — on ne prouve plus sa configuration en lisant un enregistrement.

Le débogage est plus difficile. Quand une source légitime échoue, tu ne peux plus lire l'enregistrement pour comprendre : tu dois interroger toi-même le nom synthétique correspondant à son IP et voir ce que ta zone renvoie. C'est faisable, mais moins immédiat qu'un enregistrement en clair.

Tu déplaces le risque, tu ne le supprimes pas. L'autorisation ne dépend plus d'un texte figé mais du comportement d'un service. Un bug dans la logique de ta zone, ou sa compromission, peut autoriser un attaquant aussi silencieusement qu'il autorise tes serveurs. La rigueur que tu mettais dans ton enregistrement, tu dois désormais la mettre dans ton backend DNS.

Macros, flattening ou sous-domaines : lequel choisir ?

Ces trois approches répondent au même symptôme mais ne jouent pas dans la même cour.

Le SPF flattening fige les IP des prestataires dans ton enregistrement : simple à mettre en place, mais fragile, car ces IP changent et ton instantané périme. Le découpage par sous-domaine offre à chaque flux son propre budget de dix résolutions : c'est l'approche la plus saine pour la grande majorité des organisations, et celle qu'on recommande d'abord. Les macros exists, elles, ne se justifient que dans un cas précis : un parc d'IP vaste, dynamique et maîtrisé en interne, avec une infrastructure DNS capable de répondre à la volée. Pour un site qui empile quatre include de prestataires grand public, c'est un marteau-pilon — le ménage et les sous-domaines suffisent, sans la complexité d'une zone programmée.

Autrement dit : les macros ne sont pas « la meilleure » solution, elles sont la solution des grands émetteurs techniques. Si tu ne fais pas partie de cette catégorie, tu gagneras à passer d'abord par notre analyseur DMARC gratuit pour voir si un simple nettoyage te ramène sous la barre — c'est presque toujours le cas.

Questions fréquentes

Est-ce standard, ou un bricolage ? Parfaitement standard. Le mécanisme exists et les macros sont définis noir sur blanc dans la RFC 7208 (sections 5.7 et 7). Ce n'est pas un contournement contre la spec, c'est un usage prévu par elle — simplement pointu.

Les serveurs destinataires le supportent-ils ? Les grands opérateurs (Gmail, Microsoft, Yahoo…) implémentent les macros correctement. Le point de vigilance vient de validateurs plus anciens ou marginaux, dont le support des macros est parfois incomplet — d'où l'intérêt de garder un -all propre et un DKIM solide en filet.

Ça compte quand même pour un lookup, non ? Oui, le exists coûte une résolution. Et quand une IP n'est pas autorisée, la réponse NXDOMAIN compte comme une « void lookup » — mais la RFC en tolère deux, donc un seul exists non concluant reste dans les clous. Ce qu'il ne faut pas faire, c'est empiler plusieurs exists qui échouent tous.

Et l'IPv6 ? %{ir} fonctionne aussi en IPv6, mais l'adresse s'y déplie en 32 labels (le format « nibble » du DNS inverse ip6.arpa). Ta zone doit donc gérer les deux formes ; c'est là que la macro %{v} (in-addr vs ip6) sert à aiguiller proprement.

Est-ce risqué côté sécurité ? Le risque se déplace vers ton backend DNS. Tant que sa logique d'autorisation est correcte et protégée, la posture reste saine. Une erreur y a en revanche le même effet qu'un +all mal placé : elle ouvre la porte. À manier avec la même rigueur que le reste de ta configuration — la PermError comprise.

Laisse Thomas juger si tu en as vraiment besoin

Les macros exists sont un outil de spécialiste, pas un réflexe. Avant de programmer une zone DNS, encore faut-il être sûr que le problème le mérite. Thomas, ton RSSI virtuel, déplie ton SPF, mesure ton décompte réel de résolutions, repère les include les plus lourds, et te dit honnêtement quelle voie te convient : un simple ménage, un découpage par sous-domaine, un flattening ciblé — ou, si ton parc l'exige vraiment, les macros. Le bon outil pour ta situation, pas le plus impressionnant.

Analyse ton domaine gratuitement → ou crée un compte pour savoir exactement où en est ton SPF.

Prêt à appliquer DMARC ?

Thomas, ton RSSI virtuel, identifie chaque source d'envoi légitime, écrit les enregistrements DNS exacts et amène ton domaine de p=none à p=reject — sans casser ton courrier.

Atteindre p=reject — gratuit

Guides liés

À propos de l'auteur

ThomasThomas est le RSSI virtuel de DMARC.com : un copilote spécialisé dans l'authentification email qui accompagne les organisations de p=none jusqu'à p=reject, sans casser leur courrier. Ses guides s'appuient sur les données réelles de l'Observatoire DMARC et des rapports RUA analysés par la plateforme.