SPF Milter ist eine Milter-Anwendung zur Verifizierung von E-Mail-Absendern mittels des Sender-Policy-Framework-Protokolls. In einen milterfähigen Mailserver integriert setzt sie die im DNS veröffentlichte SPF-Policy gegenüber Clients durch.
SPF Milter setzt die Vorgaben der SPF-Spezifikation [RFC 7208] wortgetreu um.
Die Verifizierung wird stets in der von der Spezifikation empfohlenen Folge
durchgeführt: Erst wird optional die HELO identity (der mittels SMTP-Befehl
HELO
angegebene Domainname) des Clients überprüft. Führt dieser Schritt nicht
zu einem Ergebnis, dann wird seine MAIL FROM identity (der mittels SMTP-Befehl
MAIL FROM
angegebene Absender) überprüft. Das so ermittelte endgültige
Resultat wird dann vom Milter in geeigneter Weise behandelt, entweder indem mit
einem SMTP-Fehler geantwortet wird, oder indem das Resultat in den Kopfteil der
Nachricht geschrieben wird.
Innerhalb des von der Spezifikation gesetzten Rahmens bietet SPF Milter flexible Konfigurationsmöglichkeiten. Konfigurationsparameter für den Verifikationsablauf, die Behandlung des Resultats, SMTP-Antwort, Header und so weiter decken eine Bandbreite von Anwendungsszenarien ab. Konfiguration kann im laufenden Betrieb angepasst werden, ohne dass ein Neustart nötig ist.
Was die Implementierung angeht, ist SPF Milter im Wesentlichen nicht mehr als eine Konfigurationsmaske, die über eine in das Milter-Protokoll integrierte SPF-Bibliothek gelegt ist. Die SPF-Implementierung besorgt [viaspf], die dazugehörige DNS-Implementierung besorgt [domain]. Wir erachten diese Komponenten als eine solide Basis für SPF-Milter-Software.
SPF Milter ist ein [Rust]-Projekt. Es kann wie üblich mit Cargo kompiliert und/oder installiert werden. Das folgende Kommando etwa lädt und installiert die neuste Version von [crates.io]:
cargo install --locked spf-milter
Als Milter-Anwendung benötigt SPF Milter die C-Bibliothek libmilter. Unter
Debian und Ubuntu beispielsweise muss das Paket libmilter-dev
installiert
werden.
Bei der Kompilierung wird das Programm pkg-config
verwendet, um die
Milter-Bibliothek zu lokalisieren. Fehlen auf einer Distro die
pkg-config-Metadaten für libmilter, kann die in diesem Projekt vorhandene Datei
milter.pc
Hilfe bieten: Dazu einfach milter.pc
in einem Verzeichnis ablegen
und dann beliebige Cargo-Befehle mit diesem Verzeichnis auf dem pkg-config-Pfad
ausführen. Das Kompilieren des spf-milter
-Programms geht dann so:
PKG_CONFIG_PATH=/path/to/dir cargo build
Die Bibliothek [domain] benötigt die Bibliothek OpenSSL. Auf Debian und Ubuntu
muss das Paket libssl-dev
installiert werden.
Als Mindestanforderung für Rust gilt Version 1.46.0.
Fürs Kompilieren aus dem Quellcode gelten die obengenannten Anforderungen.
Ausserdem ist für das Ausführen der Integrationstests das Programm miltertest
notwendig. (miltertest
ist Teil der Software [OpenDKIM].)
Der Standardpfad für die Konfigurationsdatei kann zur Kompilierzeit
überschrieben werden, indem die Umgebungsvariable SPF_MILTER_CONFIG_FILE
definiert wird.
Nach der Installation kann SPF Milter auf der Kommandozeile als spf-milter
aufgerufen werden. SPF Milter liest Konfigurationseinstellungen aus dem File
/etc/spf-milter.conf
. Darin muss mindestens der Parameter socket
eingestellt
werden. Die Beispielkonfiguration spf-milter.conf
zeigt wie das geht.
Beim Aufruf von spf-milter
startet der Milter im Vordergrund. Er kann mit
einem Signal oder mittels Tastenkombination Steuerung-C heruntergefahren werden.
Soll SPF Milter als Dienst betrieben werden, empfiehlt sich als Vorlage der im
Projekt vorhandene systemd-Service spf-milter.service
. Diese Datei nach Bedarf
anpassen (zum Beispiel User
und UMask
beifügen), in /etc/systemd/system
installieren und dann den Service aktivieren und starten.
Statusmeldungen schreibt SPF Milter standardmässig ins Syslog. Neben Fehlermeldungen und Warnungen wird für jede überprüfte Identität das Verifizierungsergebnis in das Log geschrieben.
Die Konfiguration von SPF Milter erfolgt in erster Linie über
Konfigurationsparameter, die in der Datei /etc/spf-milter.conf
hinterlegt
werden. Alle Parameter haben sinnvolle Standardwerte, mit Ausnahme des
Parameters socket
, der zwingend angegeben werden muss.
Als Referenz ist die man page spf-milter.conf(5) massgebend. (Die man page
lässt sich auch ohne Installation ansehen mit: man ./spf-milter.conf.5
)
Konfiguration kann im laufenden Betrieb vom File neu geladen werden, indem das
Signal SIGUSR1
an den Milter-Prozess gesandt wird. Einzelheiten dazu stehen in
der man page.
Für jene, die SPF Milter zum ersten Mal verwenden, bietet der folgende Abschnitt eine kurze praktische Einführung und Übersicht über die wichtigsten Konfigurationsparameter.
Nehmen wir uns zwei Minuten Zeit um zum ersten Mal SPF Milter aufzusetzen.
Der erste Schritt ist, das Socket des Milters, wohin sich der MTA verbinden
wird, auszuwählen und einzurichten. Dazu dient der Parameter socket
. Als
Wert muss eine Socket-Spezifikation in einem von zwei Formaten stehen:
inet:port@host
oder
inet6:port@host
für ein TCP-Socketunix:path
für ein UNIX-Domain-SocketSo muss das im Konfigurationsfile ausschauen:
```
socket = inet:3000@localhost ```
Zur Erinnerung: Die Konfigurationseinstellungen gehören ins File
/etc/spf-milter.conf
. Die Syntax ist wie oben gezeigt und in der man page
dokumentiert. Dabei nicht vergessen, den Milter mit dem MTA zu integrieren. Mit
[Postfix] etwa heisst das, das Socket in /etc/postfix/main.cf
anzugeben:
smtpd_milters = inet:localhost:3000
non_smtpd_milters = $smtpd_milters
Diese Dinge eingestellt, den Milter aufgestartet und die Postfix-Konfiguration neu geladen, beginnt SPF Milter sogleich eintreffende Nachrichten zu verarbeiten.
Verschiedene Aspekte der Verarbeitung können angepasst werden. Die wichtigste
konfigurierbare Facette des Verifikationsablaufs ist, ob die HELO identity
überprüft wird oder nicht. Dazu dient der Boole’sche Parameter
verify_helo
:
```
verify_helo = yes ```
Verifikation der HELO identity einschalten bedeutet nicht Verifikation der MAIL FROM identity ausschalten. Vielmehr wird so die HELO identity zusätzlich vor der MAIL FROM identity überprüft. Nur wenn diese ein definitives Ergebnis liefert, kann MAIL FROM übersprungen werden. Es ist im Allgemeinen von Vorteil, diese Option eingeschaltet zu lassen. Denn, wie in Abschnitt 2.3 von RFC 7208 ausgeführt, ist die HELO identity gewöhnlich simpler als die komplexere MAIL FROM identity, und ist oft mit einer weniger komplexen SPF-Policy verknüpft, die mit weniger DNS-Abfragen auskommt. Insgesamt kann diese Einstellung daher die Auswertung beschleunigen.
Absender mit einem negativen Autorisierungsresultat oder einem Fehlerresultat
können vom Milter auf SMTP-Ebene mit einer temporären oder permanenten
Fehlerantwort abgewiesen werden. Die abzuweisenden SPF-Resultate werden mit dem
Parameter reject_results
deklariert:
```
reject_results = fail, temperror, permerror ```
Die SPF-Resultate werden mit Kommas getrennt aufgelistet. Im obigen Beispiel würden Absender mit Resultat fail abgewiesen, Absender mit Resultat softfail jedoch angenommen.
Bei angenommenen, also nicht abgewiesenen Absendern wird das Resultat in eine
neue Headerzeile ihrer Nachricht geschrieben. Die Art der Headerzeile kann
ebenfalls konfiguriert werden, und zwar mittels Parameter header
. Zur
Auswahl stehen die Header-Typen Received-SPF
und Authentication-Results
.
Beispiel:
```
header = Received-SPF ```
Und damit seid ihr gerüstet fürs selbständige Experimentieren.
Beim Experimentieren mit der Konfiguration ist jeweils kein Neustart nötig, es genügt, dem Milter das Neuladen-Signal zu schicken. Dieses Feature sowie viele weitere Einstellungen sind in der man page spf-milter.conf(5) erklärt.
Zu Vertiefung wollen wir uns in diesem Abschnitt zwei geläufige Anwendungsfälle genauer ansehen: „Standard“-SPF und SPF als Teil von DMARC.
Der RFC-konforme Standardanwendungsfall für SPF-Verifikation wird von den
Standardeinstellungen von SPF Milter gut abgedeckt. Es genügt also, den
Pflichtparameter socket
einzustellen und alle anderen Parameter auf der
Defaulteinstellung zu belassen, um diesen Anwendungsfall einzurichten.
/etc/spf-milter.conf
:
socket = inet:3000@localhost
Gehen wir nun das Standardverhalten der Reihe nach durch.
Als erstes verifiziert SPF Milter die HELO identity (verify_helo=yes
). Wenn
sich aus diesem Test keines der definitiven Autorisierungsresultate ergibt –
pass oder fail –, wird als nächstes die MAIL FROM identity verifiziert.
Die Menge der „definitiven“ HELO-Resultate, infolge derer MAIL FROM
übersprungen wird, kann mit dem Parameter definitive_helo_results
eingestellt
werden. Wie erwähnt ist der Initialwert pass, fail
, der aber auf beliebige
SPF-Resultate angepasst werden kann.
Aus dem HELO- oder MAIL-FROM-Test resultiert ein finales Ergebnis. Dieses wird
dann vom Milter gemäss den Empfehlungen von RFC 7208 in eine Antwort umgesetzt:
Die Resultate fail, temperror und permerror werden mit einer permanenten
beziehungsweise temporären SMTP-Fehlerantwort abgewiesen, alle anderen Resultate
werden in einer Headerzeile der Nachricht hinzugefügt. Die Menge der
abzuweisenden Resultate ist wiederum mit einem Parameter, reject_results
,
konfigurierbar. Ebenso können Statuscode und Text der SMTP-Antwort für jedes
SPF-Resultat ajustiert werden.
Für den Header wird standardmässig eine Headerzeile vom Typ Received-SPF
generiert. Der Header-Typ lässt sich mit dem Parameter header
anpassen
(header=Received-SPF
). Beide in RFC 7208 definierten Header-Typen sind
„Standard“, dienen aber verschiedenen Zwecken: Received-SPF codiert
vollständig die Eingabeparameter und Informationen zum SPF-Resultat,
Authentication-Results hingegen dient nur der Übermittlung des Resultats. Hier
und generell ist es das Bestreben von SPF Milter, die Spezifikationen genau zu
befolgen, insbesondere RFC 7208 und 8601, sowie die dort referenzierten. Im
Zweifelsfall also die RFCs lesen!
softfail
wie ein negatives Autorisierungsresultat behandeln. Unter
besonders restriktiven Bedingungen kann das Resultat softfail
wie fail
behandelt, also abgewiesen werden. Um dies zu implementieren, muss softfail
zu
den definitiven HELO-Resultaten sowie zu den abzuweisenden Resultaten
hinzugefügt werden.
/etc/spf-milter.conf
:
definitive_helo_results = pass, fail, softfail
reject_results = fail, softfail, temperror, permerror
Beide Header-Typen verwenden. SPF Milter unterstützt beide spezifizierten Header-Typen. Es können nicht nur der eine oder der andere, sondern auch beide gleichzeitig verwendet werden. Der RFC mahnt zwar, dass in dem Fall beide Header-Typen nicht je ein abweichendes Resultat beinhalten sollten, aber natürlich wird dies von SPF Milter gewährleistet.
/etc/spf-milter.conf
:
header = Received-SPF, Authentication-Results
SPF kann auch als Teil einer DMARC-Verifikation genutzt werden. Domain-based Message Authentication, Reporting, and Conformance (DMARC) ist in [RFC 7489] spezifiziert. Da DMARC das Resultat, das die SPF-Komponente produziert, als Eingabe für seinen eigenen Validierungsprozess verwendet, sind einige Anpassungen an der Standardkonfiguration vorzunehmen.
/etc/spf-milter.conf
:
socket = inet:3000@localhost
verify_helo = no
reject_results =
header = Authentication-Results
Erstens ist bei DMARC nur die MAIL FROM identity von Belang, die HELO
identity spielt keine Rolle. Daher sollte dieser Schritt übersprungen werden,
indem verify_helo
deaktiviert wird.
Zweitens liegt es nahe, Absender nicht gleich nach der SPF-Verifikation
abzuweisen, da eine solche Entscheidung ja an die nachfolgende DMARC-Komponente
delegiert werden soll (je nach dem kann diese Anforderung aber auch anders
gelöst werden). In der obigen Konfiguration werden dank der Einstellung
reject_results=
(die leere Menge) keine Abweisungen mit SMTP-Fehlerantwort
getätigt. Der Milter schreibt alle Resultate nur in den Header.
Drittens wird mit dem Parameter header
der Typ der Headerzeile von
Received-SPF
zu Authentication-Results
abgeändert, da dies der Header ist,
mit dem DMARC arbeitet. Der Authentication-Results-Header wurde allgemein zur
Transportierung von Authentisierungsresultaten für spätere maschinelle
Verarbeitung entworfen. Spezifiziert wurde er jüngst in [RFC 8601].
Fehlende Autorisierung der HELO identity frühzeitig abweisen. Mit ein
wenig Fantasie lässt sich von der HELO identity auch in einem DMARC-Szenario
Gebrauch machen: Ein Absender mit nicht autorisierter HELO identity führt
bestimmt nichts Gutes im Schilde und darf abgewiesen werden. Zur Implementierung
dieser Anforderung fügen wir nur fail
den definitiven und den für die HELO
identity abzuweisenden Resultaten hinzu. In allem Übrigen verhält sich diese
Konfiguration wie die oben.
/etc/spf-milter.conf
:
verify_helo = yes
definitive_helo_results = fail
reject_helo_results = fail
reject_results =
Jeder Beitrag ist willkommen. Bitte ein Ticket auf dem Issue-Tracker aufmachen, sei es für Fragen, Anregungen, Bugs, Features, Dokumentation, Übersetzungen usw. Um das Projekt langfristig am Leben zu erhalten, kann ich Interessierten auch Commit-Rechte geben.
Bitte neue Features zuerst diskutieren, bevor ihr sie implementiert. Wir glauben, dass die Implementierung verhältnismässig oft das einfachere ist, die meiste Zeit braucht das Design und die Motivation eines Features. Genaue und fehlerresistente Implementierung der RFCs ist im Vergleich mit ähnlicher Software eine der herausragenden Leistungen von SPF Milter – immer die RFCs zu Rate ziehen!
Dieses Projekt wird als freie Software unter einer GPL-Lizenz entwickelt. Wir bitten, diese Entscheidung zu respektieren.
Copyright © 2020–2021 David Bürgin
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.