← Blog

SPF-Makros und der exists-Mechanismus: über die Grenze der 10 Lookups hinaus

Von Thomas · virtueller CISO · 2026-07-15

Die meisten Antworten auf den Fehler „too many DNS lookups“ versuchen, die Anzahl zu reduzieren: ungenutzte include-Einträge aufräumen, durch ip4: ersetzen, abflachen, auf Subdomains aufteilen. Alle folgen derselben Logik — unter der Grenze von zehn bleiben. Es gibt jedoch eine Technik anderer Art, die nichts reduziert: Sie umgeht die Grenze. Eine einzige DNS-Abfrage, aber eine potenziell unbegrenzte Anzahl autorisierter Adressen. Ihr Geheimnis: SPF-Makros in Kombination mit dem exists-Mechanismus. Sie ist mächtig, vollkommen standardkonform und ebenso schlecht verstanden wie selten erklärt. Dieser Leitfaden beschreibt genau, wie sie funktioniert, warum sie der Obergrenze von zehn entkommt, und vor allem, was im Gegenzug eingetauscht wird — denn nichts ist umsonst.

Zuerst eine Erinnerung: was die Grenze tatsächlich zählt

Um den Trick zu verstehen, muss man sich daran erinnern, was RFC 7208 begrenzt. Nicht die autorisierten IP-Adressen, sondern die DNS-Abfragen, die während der Auswertung eines SPF-Eintrags ausgelöst werden. Jedes include:, a, mx, ptr oder exists: kostet mindestens eine Abfrage; ip4: und ip6: sind Literale und kosten nichts. Über zehn Abfragen hinaus folgt ein PermError: SPF wird nicht mehr ausgewertet. Der vollständige Mechanismus, mit seinem Kaskadeneffekt auf verschachtelte include-Einträge, ist in unserem Leitfaden zu der Grenze von 10 DNS-Abfragen beschrieben.

Dieser Punkt ist festzuhalten, denn alles beruht darauf: begrenzt ist die Anzahl der Abfragen, nicht die Anzahl der IPs. Ein ip4:-Mechanismus kann einen ganzen Bereich abdecken, ohne je zu zählen. Und ein exists:-Mechanismus zählt nur als eine Abfrage — egal, wie viele Adressen er am Ende autorisiert. Genau das ist die Lücke, durch die sich die Technik schiebt.

Der exists-Mechanismus, kurz erklärt

exists ist der unbekannteste SPF-Mechanismus. Seine Definition ist dennoch einfach: exists:<Domain> fordert den empfangenden Server auf, eine A-Record-Abfrage (IPv4-Adresse) auf die angegebene Domain durchzuführen. Wenn diese Abfrage mindestens einen A-Record zurückgibt — irgendeinen, der Wert spielt keine Rolle —, dann matcht der Mechanismus. Andernfalls nicht, und die Auswertung geht weiter.

So wie er ist, mit einer festen Domain, ist exists nichts Besonderes. Seine ganze Kraft entsteht aus dem, was in diese Domain hineingesteckt wird: keine feste Zeichenkette, sondern ein Makro, das sich zur Laufzeit selbst umschreibt — für jede empfangene Nachricht anders.

SPF-Makros: eine Domain, die sich selbst umschreibt

Makros sind ein ganzer Abschnitt von RFC 7208 (Abschnitt 7), den fast niemand von Hand nutzt. Sie erlauben es, in einen Mechanismus Variablen einzufügen, die zur Auswertungszeit ersetzt werden — durch Daten der aktuellen Verbindung. Die nützlichsten:

  • %{i} — die IP-Adresse des Clients, der die Nachricht zu senden versucht.
  • %{ir} — dieselbe Adresse, aber umgekehrt (für die IPv4 203.0.113.5 ergibt das 5.113.0.203).
  • %{d} — die ausgewertete Domain.
  • %{v} — die Zeichenkette in-addr für IPv4, ip6 für IPv6 (praktisch, um beide zu unterscheiden).

Die Umkehrung bei %{ir} ist keine Laune: Sie bildet die Logik des Reverse-DNS (in-addr.arpa) nach, bei der man die Adresse vom Spezifischsten zum Allgemeinsten liest. Dadurch wird jedes Oktett der IP zu einem eigenen DNS-Label, was den Aufbau feingliedriger Zonen-Bäume erlaubt. Man ahnt, worauf das hinausläuft.

Der Kern: eine Abfrage, eine unbegrenzte Anzahl von IPs

Beide Teile zusammengesetzt, ergibt sich dies:

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

Ein einziger abfragekostender Mechanismus, also eine Abfrage in der Zählung der zehn. Aber entscheidend ist, was bei der Auswertung passiert. Ein Server empfängt eine Nachricht, deren sendende IP 203.0.113.5 ist. Er schreibt das Makro um und fragt ab:

5.113.0.203._spf.example.com

In diesem Moment entscheidet der eigene DNS-Server. Die Zone _spf.example.com, die unter eigener Kontrolle steht, antwortet auf eine von zwei Arten:

  • sie gibt einen A-Record zurück (per Konvention 127.0.0.1) → das exists matcht → die IP ist autorisiert, SPF besteht;
  • sie gibt NXDOMAIN zurück (Name existiert nicht) → das exists matcht nicht → die Auswertung landet beim -all, SPF scheitert.

Der Umschalter liegt vollständig darin, wie die Zone auf diese synthetischen Namen antwortet. Sie lässt sich an eine Datenbank von Zehntausenden IPs anbinden, an eine dynamische Generierung, an geografische Regeln, an eine Liste pro Absender… Eine Abfrage, N Autorisierungen. Die Grenze von zehn wird nicht weiter hinausgeschoben: Sie ist schlicht irrelevant, weil nur noch ein abfragekostender Mechanismus übrig ist und die Intelligenz von der Zonendatei in die Logik des DNS-Servers gewandert ist.

Genau so bieten manche großen Versender ihren Kunden „ein einziger include, unbegrenzte Absender“: Hinter ihrem include verbirgt sich oft ein makrobasiertes exists, das ihren wechselnden IP-Bestand dynamisch autorisiert, ohne je die Zählung ihrer Kunden zu sprengen.

Ein konkretes Beispiel von Anfang bis Ende

Nehmen wir ein Unternehmen, das aus einem großen, wechselnden IP-Bestand sendet — mehrere Rechenzentren, wöchentlich hinzugefügte und entfernte Adressen. Als klassisches include würde dieser Bestand allein den Großteil des Budgets von zehn verbrauchen, und die kleinste Ergänzung könnte in den PermError kippen. Mit der Makro-Technik:

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

Das include deckt die Standard-Mail ab (etwa Microsoft 365, das der Anbieter für seine Kunden pflegt). Das exists delegiert den gesamten dynamischen Bestand an die Zone _auth.example.com. Das %{v} unterscheidet dort IPv4 von IPv6, sodass eine einzige Regel beide Familien bedient. Wenn eine IP sendet, prüft die Zone das aktuelle Inventar und antwortet entsprechend. Morgen tausend Adressen hinzuzufügen ändert nichts am veröffentlichten SPF-Eintrag: Er bleibt bei zwei abfragekostenden Mechanismen, weit unter der Grenze. Die Pflege hat das öffentliche DNS zugunsten des internen Inventars verlassen — wo sie ohnehin leichter aktuell zu halten ist.

Die Kompromisse (denn es gibt welche)

Wäre diese Technik makellos, würde sie jeder nutzen, und den Fehler „too many lookups“ gäbe es nicht mehr. Ist sie nicht, aus guten Gründen.

Es braucht eine programmierbare DNS-Zone. Das makrobasierte exists ist nur nützlich, wenn der DNS-Server dynamisch auf synthetische Namen antworten kann, die er nie zuvor gesehen hat. Ein klassischer statischer DNS-Host, bei dem Einträge einzeln in einer Oberfläche eingetippt werden, kann das nicht. Nötig ist entweder ein selbst programmiertes DNS oder ein spezialisierter Dienst, der diesen Mechanismus anbietet. Das sind die eigentlichen Einstiegskosten.

Das SPF wird undurchsichtig. Ein Prüfer, der exists:%{ir}._spf.example.com liest, kann die autorisierten IPs nicht mehr aufzählen: Die Menge ist aus der Zonendatei verschwunden und lebt in der Logik eines Servers. Das ist ein bewusster Verlust an Lesbarkeit. Für eine Domain unter Compliance-Prüfung ist dieser Transparenzverlust nicht belanglos — man beweist seine Konfiguration nicht mehr, indem man einen Eintrag liest.

Das Debugging wird schwieriger. Wenn eine legitime Quelle scheitert, hilft die Lektüre des Eintrags nicht mehr weiter: Man muss den synthetischen Namen für ihre IP selbst abfragen und sehen, was die Zone zurückgibt. Machbar, aber weniger unmittelbar als ein Klartext-Eintrag.

Das Risiko wird verlagert, nicht beseitigt. Die Autorisierung hängt nicht mehr von einem festen Text ab, sondern vom Verhalten eines Dienstes. Ein Fehler in der Logik der Zone oder ihre Kompromittierung kann einen Angreifer ebenso lautlos autorisieren, wie sie die eigenen Server autorisiert. Die Sorgfalt, die bislang dem Eintrag galt, gilt nun dem DNS-Backend.

Makros, Flattening oder Subdomains: was wählen?

Diese drei Ansätze behandeln dasselbe Symptom, spielen aber nicht in derselben Liga.

Das SPF-Flattening friert die IPs der Anbieter im Eintrag ein: einfach umzusetzen, aber fragil, weil diese IPs sich ändern und die Momentaufnahme veraltet. Die Aufteilung nach Subdomain gibt jedem Fluss sein eigenes Budget von zehn Abfragen: Das ist der gesündeste Ansatz für die große Mehrheit der Organisationen und der, den wir zuerst empfehlen. Makros mit exists rechtfertigen sich nur in einem ganz bestimmten Fall: einem großen, dynamischen, intern kontrollierten IP-Bestand, mit einer DNS-Infrastruktur, die zur Laufzeit antworten kann. Für eine Domain, die vier include-Einträge von Endkunden-Anbietern stapelt, ist es ein Vorschlaghammer — Aufräumen und Subdomains genügen, ohne die Komplexität einer programmierten Zone.

Anders gesagt: Makros sind nicht „die beste“ Lösung, sie sind die Lösung der großen technischen Versender. Außerhalb dieser Kategorie lohnt sich zuerst ein Durchlauf durch unseren kostenlosen DMARC-Analyzer, um zu sehen, ob ein einfaches Aufräumen unter die Grenze bringt — fast immer ist das der Fall.

Häufige Fragen

Ist das standardkonform oder eine Bastelei? Vollkommen standardkonform. Der exists-Mechanismus und die Makros sind in RFC 7208 (Abschnitte 5.7 und 7) schwarz auf weiß festgeschrieben. Das ist kein Umgehen der Spezifikation, sondern eine von ihr vorgesehene Verwendung — nur eine anspruchsvolle.

Unterstützen die empfangenden Server das? Die großen Betreiber (Gmail, Microsoft, Yahoo…) implementieren Makros korrekt. Vorsicht ist bei älteren oder randständigen Validatoren geboten, deren Makro-Unterstützung mitunter unvollständig ist — deshalb lohnt es sich, ein sauberes -all und ein solides DKIM als Auffangnetz zu behalten.

Zählt es trotzdem als eine Abfrage? Ja, das exists kostet eine Abfrage. Und wenn eine IP nicht autorisiert ist, zählt die NXDOMAIN-Antwort als „Void Lookup“ — aber die RFC toleriert zwei, sodass ein einzelnes ergebnisloses exists im Rahmen bleibt. Was nicht geht, ist mehrere exists zu stapeln, die alle scheitern.

Und IPv6? %{ir} funktioniert auch in IPv6, aber die Adresse dehnt sich dort auf 32 Labels aus (das „Nibble“-Format des Reverse-DNS ip6.arpa). Die Zone muss also beide Formen handhaben; genau hier hilft das Makro %{v} (in-addr vs. ip6), um sauber zu unterscheiden.

Ist es sicherheitstechnisch riskant? Das Risiko verlagert sich ins DNS-Backend. Solange dessen Autorisierungslogik korrekt und geschützt ist, bleibt die Konfiguration solide. Ein Fehler dort hat hingegen dieselbe Wirkung wie ein fehlplatziertes +all: Er öffnet die Tür. Das Thema verdient dieselbe Sorgfalt wie der PermError und der Rest der Konfiguration.

Thomas beurteilt, ob es wirklich nötig ist

Makros mit exists sind ein Werkzeug für Spezialisten, kein Reflex. Vor dem Programmieren einer DNS-Zone muss sicher sein, dass das Problem es rechtfertigt. Thomas, der virtuelle CISO, löst das SPF auf, misst die tatsächliche Abfragezahl, findet die schwersten include-Einträge und sagt ehrlich, welcher Weg zum behandelten Fall passt: ein einfaches Aufräumen, eine Aufteilung nach Subdomain, ein gezieltes Flattening — oder, wenn der Bestand es wirklich verlangt, Makros. Das richtige Werkzeug für die jeweilige Situation, nicht das beeindruckendste.

Eine Domain kostenlos analysieren oder ein Konto erstellen, um genau zu wissen, wo das SPF steht.

DMARC anwenden — konkret

Thomas, der virtuelle CISO von DMARC.com, identifiziert jede legitime Versandquelle, schreibt die exakten DNS-Einträge und bringt eine Domain sicher von p=none zu p=reject — ohne den Mailverkehr zu stören.

Zu p=reject — kostenlos

Verwandte Leitfäden

Über den Autor

ThomasThomas ist der virtuelle CISO von DMARC.com: ein auf E-Mail-Authentifizierung spezialisierter Copilot, der Organisationen von p=none bis p=reject begleitet, ohne ihren Mailverkehr zu stören. Seine Leitfäden stützen sich auf echte Daten aus dem DMARC-Observatorium und aus den von der Plattform analysierten RUA-Berichten.