IT security, FreeBSD, Linux, mail server hardening, post-quantum crypto, DNS, retro computing & hands-on hardware hacks. Privater Tech-Blog seit 2003.

Schlagwort: Postfix (Seite 1 von 5)

Post-Quantum TLS für E-Mail — Postfix und Dovecot mit X25519MLKEM768 auf FreeBSD 15

Visualisierung hybrider Post-Quantum-TLS-Verschlüsselung für E-Mail mit X25519MLKEM768 (ML-KEM-768 + X25519) auf Postfix und Dovecot unter FreeBSD 15

Siehe auch: Post-Quantum TLS für Nginx — X25519MLKEM768 auf FreeBSD 15 konfigurieren

Nachdem ich im letzten Beitrag OpenSSH mit hybriden Post-Quantum-Algorithmen abgesichert habe, lag die Frage nahe: Was ist eigentlich mit E-Mail? Mein FreeBSD 15 liefert Postfix 3.10.6, Dovecot 2.3.21.1 und OpenSSL 3.5.4 – und genau diese Kombination bringt alles mit, was man für quantensichere Verschlüsselung im Mailverkehr braucht. Ohne zusätzliche Pakete, ohne Patches, ohne Gefrickel.

Warum überhaupt PQC für E-Mail?

Das „Store now, decrypt later„-Szenario, das ich beim SSH-Beitrag angesprochen habe, trifft auf E-Mail mindestens genauso zu. E-Mails werden über SMTP zwischen Servern transportiert – und dieser Transport ist grundsätzlich abfangbar. Wer heute TLS-verschlüsselten Mailverkehr mitschneidet und archiviert, könnte diesen in einigen Jahren mit einem ausreichend leistungsfähigen Quantencomputer entschlüsseln. Zumindest theoretisch.

Heißt das, morgen liest jemand eure Mails? Nein. Aber wenn ihr vertrauliche Kommunikation betreibt und die heute eingesetzte Kryptografie in zehn Jahren noch standhalten soll, ist jetzt der richtige Zeitpunkt zum Handeln. Zumal der Aufwand (wie ihr gleich seht) überschaubar ist.

Was steckt hinter X25519MLKEM768?

Kurz zur Einordnung: ML-KEM (ehemals CRYSTALS-Kyber) ist der vom NIST im August 2024 standardisierte Post-Quantum-Algorithmus für den Schlüsselaustausch (FIPS 203). X25519MLKEM768 ist ein sogenannter Hybrid-Algorithmus – er kombiniert das klassische X25519 (Curve25519 ECDH) mit ML-KEM-768 zu einem gemeinsamen Schlüssel.

Der Clou dabei: Selbst wenn ML-KEM irgendwann gebrochen werden sollte, bleibt die klassische X25519-Komponente intakt. Und umgekehrt. Man muss also nicht darauf vertrauen, dass der neue Algorithmus auch wirklich hält – man bekommt das Beste aus beiden Welten.

Wer Firefox nutzt, hat das übrigens vermutlich schon in Aktion gesehen: Seit Firefox 124 wird bei TLS 1.3 standardmäßig X25519MLKEM768 für den Schlüsselaustausch verwendet. Schaut mal in die Verbindungsdetails einer HTTPS-Seite – die Chancen stehen gut, dass dort bereits ein hybrider PQC-Schlüsselaustausch stattfindet. Also, wenn der Server das anbietet, wie dieser hier *zwinker*.

Voraussetzungen prüfen

Bevor ihr konfiguriert, solltet ihr sicherstellen, dass euer OpenSSL ML-KEM überhaupt kann. Auf meinem FreeBSD 15:

$ openssl version
OpenSSL 3.5.4 30 Sep 2025 (Library: OpenSSL 3.5.4 30 Sep 2025)

Und dann die entscheidende Frage – kennt OpenSSL die benötigten KEM-Algorithmen?

$ openssl list -kem-algorithms | grep -i mlkem
  ML-KEM-512
  ML-KEM-768
  ML-KEM-1024
  X25519MLKEM768
  SecP256r1MLKEM768

Wenn X25519MLKEM768 in der Liste auftaucht, seid ihr startklar. Das ist bei OpenSSL ab Version 3.5 der Fall – der ML-KEM-Support ist im Default-Provider enthalten, es wird kein zusätzlicher OQS-Provider und kein liboqs benötigt.

Noch ein Check – sind die Algorithmen auch als TLS-Gruppen verfügbar?

$ openssl list -tls-groups | grep -i mlkem
  X25519MLKEM768
  SecP256r1MLKEM768
  SecP384r1MLKEM1024

Perfekt. Weiter geht’s.

Postfix konfigurieren

Postfix steuert die verwendeten TLS-Gruppen für den Schlüsselaustausch über den Parameter tls_eecdh_auto_curves. Dieser gilt sowohl für eingehende (smtpd) als auch für ausgehende (smtp) Verbindungen.

Vorher:

tls_eecdh_auto_curves = X25519, prime256v1, secp384r1

Nachher:

tls_eecdh_auto_curves = X25519MLKEM768, X25519, prime256v1, secp384r1

Das war’s. Eine Zeile. X25519MLKEM768 wird als bevorzugte Gruppe an den Anfang gestellt, die klassischen Kurven bleiben als Fallback erhalten. Clients die kein ML-KEM beherrschen, verhandeln einfach X25519 oder prime256v1 – die Abwärtskompatibilität bleibt also vollständig gewahrt.

Die Änderung setzt ihr entweder direkt in /usr/local/etc/postfix/main.cf oder über:

# postconf "tls_eecdh_auto_curves = X25519MLKEM768, X25519, prime256v1, secp384r1"
# postfix reload

Wichtig: Dieser Parameter beeinflusst alle Postfix-Dienste – SMTP (Port 25), Submission (Port 587) und SMTPS (Port 465). Ihr müsst also nicht jeden Port einzeln konfigurieren.

Update 01.04.2026: Die oben gezeigte globale Methode über main.cf hat einen Haken, den ich erst später auf der Postfix-Users Mailingliste realisiert habe. Die korrigierte Konfiguration mit getrennten Einstellungen für Inbound und Outbound findet ihr weiter unten im Nachtrag.

Dovecot konfigurieren

Dovecot verwendet den Parameter ssl_curve_list um die TLS-Gruppen für IMAP-Verbindungen festzulegen. Standardmäßig ist dieser leer, was bedeutet, dass OpenSSL seine eigenen Defaults verwendet. Das kann funktionieren, muss aber nicht.

In /usr/local/etc/dovecot/conf.d/10-ssl.conf:

ssl_curve_list = X25519MLKEM768:X25519:prime256v1:secp384r1

Achtung: Dovecot verwendet Doppelpunkte als Trennzeichen (OpenSSL-Syntax), Postfix verwendet Kommas. Nicht verwechseln. Ja, passiert mir oft.

Danach:

# doveadm reload

Überprüfen

Jetzt wird’s spannend. Funktioniert es tatsächlich? Zum Testen verwende ich openssl s_client direkt auf dem Server; denn euer lokales Linux oder macOS hat möglicherweise noch kein OpenSSL 3.5 mit ML-KEM-Support. Mein Linux Mint 22.3 hat es leider noch nicht *schnief*

SMTP (Port 25, STARTTLS):

$ openssl s_client -connect smtp.kernel-error.de:25 -starttls smtp \
    -groups X25519MLKEM768 -brief </dev/null 2>&1 | grep -E 'Protocol|group'
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768

SMTPS (Port 465):

$ openssl s_client -connect smtp.kernel-error.de:465 \
    -groups X25519MLKEM768 -brief </dev/null 2>&1 | grep -E 'Protocol|group'
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768

Submission (Port 587, STARTTLS):

$ openssl s_client -connect smtp.kernel-error.de:587 -starttls smtp \
    -groups X25519MLKEM768 -brief </dev/null 2>&1 | grep -E 'Protocol|group'
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768

IMAPS (Port 993):

$ openssl s_client -connect imap.kernel-error.de:993 \
    -groups X25519MLKEM768 -brief </dev/null 2>&1 | grep -E 'Protocol|group'
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768

Alle vier Ports verhandeln TLSv1.3 mit X25519MLKEM768. Die hybride Post-Quantum-Verschlüsselung ist aktiv.

Wenn ihr testen wollt, was passiert wenn ein Client kein ML-KEM unterstützt:

$ openssl s_client -connect imap.kernel-error.de:465 \
    -groups X25519 -brief </dev/null 2>&1 | grep -E 'Protocol|group'
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519

Fallback auf X25519 – funktioniert sauber.

Was das nicht leistet

Wie schon beim SSH-Beitrag muss ich auch hier einschränken: Wir sichern damit den Schlüsselaustausch ab, nicht die Authentifizierung. Die TLS-Zertifikate verwenden weiterhin klassische Algorithmen (RSA, ECDSA). Für Post-Quantum-Signaturen in Zertifikaten bräuchte man ML-DSA (ehemals CRYSTALS-Dilithium) – und obwohl OpenSSL 3.5 das theoretisch unterstützt, gibt es Stand heute keine öffentliche Zertifizierungsstelle, die ML-DSA-Zertifikate ausstellt. Das wird kommen, ist aber noch Zukunftsmusik. Hey, wie ECDSA bei S/MIME (oder ist das schon anders?).

Für die Praxis bedeutet das: Ein Angreifer mit einem Quantencomputer könnte theoretisch die Serverauthentifizierung angreifen (ECDSA/RSA brechen), müsste das aber in Echtzeit tun – hier greift „store now, decrypt later“ nicht, weil eine gefälschte Authentifizierung nur im Moment der Verbindung nützt. Der Schlüsselaustausch hingegen – und damit die eigentliche Vertraulichkeit der transportierten E-Mails – ist durch X25519MLKEM768 auch gegen zukünftige Quantenangriffe geschützt.

Nachtrag (01.04.2026): Inbound und Outbound trennen

Ich muss die Postfix-Konfiguration oben korrigieren. Der Parameter tls_eecdh_auto_curves gilt für SMTP-Client und SMTP-Server gleichzeitig. Steht X25519MLKEM768 an erster Stelle, wird der PQC Key-Share direkt im initialen ClientHello mitgeschickt. Das bläht den ClientHello von rund 400 auf über 1400 Bytes auf.

Klingt erstmal harmlos. Ist es aber nicht. Manche Zielserver kommen mit dem übergroßen ClientHello nicht klar, der TLS-Handshake scheitert. Bei smtp_tls_security_level = may fällt Postfix dann stillschweigend auf Plaintext zurück. Dasselbe passiert bei dane ohne TLSA-Records, also bei der Mehrheit aller Domains da draußen. Eure Mails gehen raus, aber unverschlüsselt. Super.

Das Problem ist, dass hier zwei unterschiedliche Policies in einem Parameter stecken. Inbound will man PQC bevorzugen, weil man selbst kontrolliert was der Server akzeptiert. Outbound will man Kompatibilität priorisieren, weil man nicht weiß was auf der anderen Seite steht. Die gehören nicht in einen globalen Parameter.

Die Lösung: tls_eecdh_auto_curves nicht mehr global in main.cf setzen, sondern per master.cf pro Dienst überschreiben.

Server-Seite (Inbound) – PQC bevorzugen, an allen smtpd-Listenern:

smtp      inet  n       -       n       -       -       smtpd
  -o tls_eecdh_auto_curves=X25519MLKEM768,X25519,prime256v1,secp384r1

submission inet n       -       n       -       -       smtpd
  -o tls_eecdh_auto_curves=X25519MLKEM768,X25519,prime256v1,secp384r1

smtps     inet  n       -       n       -       -       smtpd
  -o tls_eecdh_auto_curves=X25519MLKEM768,X25519,prime256v1,secp384r1

Client-Seite (Outbound) – kleiner ClientHello, PQC nur via HelloRetryRequest:

smtp      unix  -       -       n       -       -       smtp
  -o tls_eecdh_auto_curves=X25519,X25519MLKEM768,prime256v1,secp384r1

Der Trick: Outbound steht X25519 an erster Stelle. Der initiale ClientHello bleibt damit klein. X25519MLKEM768 steht trotzdem in den supported_groups und wird verhandelt, wenn der Zielserver per HelloRetryRequest nachzieht. Inbound bekommen moderne Clients dagegen sofort PQC.

Dovecot ist davon nicht betroffen. Da gibt es nur die Server-Seite, ssl_curve_list bleibt wie oben beschrieben.

Noch ein Wort zum Postfix-Default: postconf -d zeigt auf meinem 3.10.6 kein X25519MLKEM768 im Default. Die postconf(5)-Doku beschreibt zwar für neuere Builds ein Delayed-Key-Share-Verhalten, aber was die Doku beschreibt und was ein konkreter Build tut, können zwei verschiedene Dinge sein. Deshalb die explizite Trennung per master.cf. Danke an die Postfix-Users Mailingliste für die Diskussion, die mich auf dieses Problem aufmerksam gemacht hat und selbstverständlich an den Kommentierenden!

Zwei Zeilen Konfiguration, ein Reload pro Dienst – und euer Mailserver verhandelt quantensichere Verschlüsselung. Okay, es sind jetzt ein paar mehr Zeilen als ursprünglich versprochen. Aber die Trennung zwischen Inbound und Outbound ist es wert, denn blind auf Kompatibilität aller Zielserver zu hoffen ist keine Strategie.

Viel Spaß beim Nachbauen – und wie immer: bei Fragen, fragen.

Postfix: Verschleierung nur für SASL-Benutzer einrichten

Wie man bei allen ausgehenden E-Mails dafür sorgt, dass die Client IP Adresse sowie der eingesetzte Mailclient vom Postfix verschleiert wird… Ja dieses habe ich bereits geschrieben. Postfix soll verschleiern…

Nun kann es dennoch Sinn ergeben dieses nicht für jede E-Mail zu tun, welche den Mailserver verlässt. Wenn man dieses nur auf E-Mails anwenden möchte, welche von angemeldeten Benutzern versendet werden, funktioniert es wie folgt.

Man erstellt in der master.cf vom Postfix einen neuen Service:

anonym unix n       -       -       -       0       cleanup
  -o header_checks=pcre:/usr/local/etc/postfix/header_cleanup

Nun sorgt man in der gleichen Konfigurationsdatei noch dafür, dass am Ende vom Submission und smtps Service in diesen neuen Service gesprungen wird:

submission inet n       -       n       -       -       smtpd
[...]
  -o cleanup_service_name=anonym
[...]
smtps     inet  n       -       n       -       -       smtpd
[...]
  -o cleanup_service_name=anonym

Der Inhalt unserer /usr/local/etc/postfix/header_cleanup ist dabei weiterhin gleich:

/^(Received: from)[^\n]*(.*)/ REPLACE $1 ::88 (YOUR MOM [::88])$2
/^X-Originating-IP/ IGNORE
/^User-Agent*(.*)/ REPLACE User-Agent: YOUR MOMS MAILER
/^X-Mailer*(.*)/ REPLACE X-Mailer: YOUR MOMS MAILER

Nach einem Restart vom Postifx hat man nun den gewünschten Zustand. Natürlich dürfen nun die smtp_header_checks nicht mehr in der main.cf sein:

#smtp_header_checks = pcre:/usr/local/etc/postfix/header_cleanup

Viel Spaß

Fragen? Einfach melden.

Postfix: Eingehende E-Mails ohne TLS ablehnen

Standardmäßig nimmt Postfix E-Mails auch ohne Transportverschlüsselung an. Mit smtpd_tls_security_level = may bietet der Server TLS an, erzwingt es aber nicht. Das bedeutet: Wenn die Gegenseite kein STARTTLS kann oder will, wird die Mail trotzdem im Klartext übertragen.

Man kann das ändern und E-Mails ohne TLS komplett ablehnen. Die Frage ist ob man sich das leisten kann.

Konfiguration

# /usr/local/etc/postfix/main.cf
smtpd_tls_security_level = encrypt

Mit encrypt verweigert Postfix die Annahme wenn der sendende Server kein STARTTLS aushandelt. Die Gegenseite bekommt einen temporären Fehler (454) und kann es später nochmal versuchen. Im Log steht dann:

postfix/smtpd: NOQUEUE: reject: RCPT from mail.example.de[...]: 454 4.7.0 TLS is required but was not offered

Vorher prüfen

Bevor man TLS erzwingt, sollte man wissen wie viele Mails betroffen wären. Im Postfix-Log lässt sich das auswerten:

# Anteil TLS vs. Klartext bei eingehenden Verbindungen
grep "TLS connection established" /var/log/maillog | wc -l
grep "connect from" /var/log/maillog | wc -l

In der Praxis liegt der TLS-Anteil bei den meisten Mailservern über 95 Prozent. Die letzten paar Prozent sind oft schlecht gewartete Systeme, Onlineshop-Bestätigungen oder Geräte aus Asien die sich nie um TLS gekümmert haben. Ob das ein Problem ist, hängt davon ab wessen Mails man bereit ist zu verlieren.

Ausgehend erzwingen

Für ausgehende Mails ist die Situation anders. Mit smtp_tls_security_level = encrypt verweigert Postfix die Zustellung wenn die Gegenseite kein TLS anbietet. Das ist riskant, weil man keine Kontrolle darüber hat ob der Empfänger-Server TLS kann.

Der bessere Weg für ausgehende Mails: MTA-STS und DANE prüfen automatisch ob die Zieldomain TLS verlangt und welches Zertifikat erwartet wird. Damit erzwingt man TLS nur dort wo die Gegenseite es auch unterstützt und verifiziert gleichzeitig die Identität.

# Ausgehend: opportunistisch, aber DANE wenn verfügbar
smtp_tls_security_level = dane
smtp_dns_support_level = dnssec

Mit dane als Security-Level nutzt Postfix DANE/TLSA-Records aus dem DNS. Ist ein TLSA-Record vorhanden, wird TLS erzwungen und das Zertifikat verifiziert. Ohne TLSA-Record bleibt es bei opportunistischem TLS. Zusammen mit dem Abschalten von TLS 1.0/1.1 ergibt das eine saubere Konfiguration. Fragen? Einfach melden.

Postfix: Client-Initiated Renegotiation sicher deaktivieren

client-initiated renegotiation beim SMTPD Server kann für DDoS Angriffe ausgenutzt werden. Die einzelnen TLS/SSL Optionen lassen sich über die recht gleichnamige Option im Postfix ein und ausschalten. Gibt es noch keinen mappenden Namen kann die jeweilige Option auch ein/ausgeschaltet werden mit dem jeweiligen Hexwert. Genau Infos findet man hier: http://www.postfix.org/postconf.5.html#tls_ssl_options

If the value of the parameter is a hexadecimal long integer starting with "0x", the options corresponding to the bits specified in its value are enabled (see openssl/ssl.h and SSL_CTX_set_options(3))

Für ein Postfix  3.3 und einem OpenSSL ab Version 1.1.1 ist der passende Hexwert 0x40000000.

Die Option setzt man wie so oft in der main.cf:

root@smtp:/ # postconf  tls_ssl_options
tls_ssl_options = 0x40000000

Ab Postfix >=3.4 gibt es: NO_RENEGOTIATION

Fragen? Dann fragen.

Fragen? Einfach melden.

Postfix Header Cleanup: Client-IPs und Mailer-Versionen aus E-Mail-Headern entfernen

Jede E-Mail enthält Header, die Informationen über den Absender preisgeben: Die IP-Adresse des Clients (Received), den verwendeten Mailclient samt Version (User-Agent, X-Mailer) und manchmal die originale IP (X-Originating-IP). Für einen Angreifer ist das nützlich. Er sieht welche Software in welcher Version läuft und kann gezielt nach bekannten Schwachstellen suchen. Die IP-Adresse verrät die interne Netzwerktopologie oder ermöglicht Tracking über verschiedene Netze.

Postfix kann diese Header beim Versand per Regex umschreiben oder entfernen.

Konfiguration

In der main.cf die Header-Checks aktivieren:

smtp_header_checks = pcre:/usr/local/etc/postfix/header_cleanup

Die Datei header_cleanup enthält die Regex-Regeln:

# Client-IP im Received-Header ersetzen
/^(Received: from)[^\n]*(.*)/ REPLACE $1 [127.0.0.1] (localhost [127.0.0.1])$2

# Originating-IP komplett entfernen
/^X-Originating-IP/ IGNORE

# Mailclient-Version verschleiern
/^User-Agent/ IGNORE
/^X-Mailer/ IGNORE

REPLACE ersetzt die Zeile, IGNORE löscht sie komplett. Die erste Regel tauscht die echte Client-IP im Received-Header gegen localhost aus. Die restlichen Regeln entfernen Mailclient-Informationen.

smtp_header_checks vs. header_checks

Postfix kennt zwei Stellen für Header-Manipulation: header_checks greift bei der Annahme (Cleanup-Daemon), smtp_header_checks greift beim Versand (SMTP-Client). Für die Verschleierung eigener Absender-Daten ist smtp_header_checks die richtige Wahl. Die Header werden erst beim Versand umgeschrieben, nicht bei der internen Verarbeitung. So bleiben die originalen Header in den lokalen Logs erhalten.

DKIM-Kompatibilität

Die DKIM-Signatur wird nicht gebrochen. DKIM signiert standardmäßig den Body und ausgewählte Header wie From, To, Subject und Date. Die Received-, User-Agent– und X-Mailer-Header sind nicht Teil der Signatur. Außerdem greift smtp_header_checks nach dem Signing, der Cleanup-Daemon hat die DKIM-Signatur zu diesem Zeitpunkt bereits erstellt.

Fragen? Einfach melden.

Postfix-Fehlerantworten anpassen: So gehst du vor

Wieder wurde ich gefragt wie ich bei meinem Postfix den Error Reply für rejected 5xx E-Mails geändert habe. Nun ja, das habe ich überhaupt nicht.

Postfix hat seit vielen Jahren die Option: smtpd_reject_footer diese wurde in 2011 beim „Aufräumen“ umbenannt in: smtpd_reject_footer

Cleanup: smtpd_reject_contact_information is renamed to smtpd_reject_footer, because it can be used for non-contact information.

Beide Optionen sind anscheinend eher unbekannt. Was ich gut verstehen kann. Denn setzt man nun in seiner main.cf den smtpd_reject_footer wird diese zwar brav angehangen und taucht sogar beim Absender im Postfach auf, nur welcher Benutzer liest diese schon und folgt dann noch dem jeweiligen Hinweis? Bisher ist diese Rückmeldung meines Systems nur sehr wenigen überhaupt aufgefallen ;-P

Vor ~12 Jahren habe ich sie wohl zum ersten Mal gesetzt. Ich meine da auf die Adresse vom Postmaster verwiesen zu haben, damit die Nutzer sich dort hin melden können. Später hatte ich mal einen Link auf eine zweisprachige Hilfeseite bei mir und noch später etwas wie: „Das Problem ist zu 99% dein Mailserver, frag DEINEN Admin!“. Dieses war es bis heute, denn heute habe ich die erneute Frage zum Anlass genommen, dieses hier zu schreiben und natürlich direkt auf riot.im zu verlinken. Dann kann man mich direkt anschreiben. Sicher etwas freundlicher als: „geh weg du bist eh das Problem“ und einfacher als noch eine E-Mail an den Postmaster zu schreiben. Sicher werde ich nun durch diese Nachricht 1 oder 2 mal im Jahr angeschrieben, wenn es dieses überhaupt wird.

Achja, so sieht der Eintrag in der main.cf von Postfix aus:

root@smtp:/usr/local/etc/postfix # postconf smtpd_reject_footer
smtpd_reject_footer = For assistance, visit https://matrix.to/#/@kernel-error:kernel-error.com

Damit lässt sich nun dieses Ergebnis erzielen:

banane@bsd03:~ # telnet smtp.kernel-error.de 25
Trying 2a01:4f8:150:1095::25...
Connected to smtp.kernel-error.de.
Escape character is '^]'.
220 smtp.kernel-error.de ESMTP Postfix
helo asdf
250 smtp.kernel-error.de
mail from: <test@spam.de>
250 2.1.0 Ok
rcpt to: <spamlover@kernel-error.com>
250 2.1.5 Ok
data
354 End data with <CR><LF>.<CR><LF>
subject: test
.test
.
554-5.7.1 Spam message rejected
554 5.7.1 For assistance, visit https://matrix.to/#/@kernel-error:kernel-error.com
Connection closed by foreign host.

Fragen? Dann wie immer bitte fragen…

Siehe auch: E-Mails ohne TLS ablehnen

Fragen? Einfach melden.

Postfix MTA-STS Resolver für FreeBSD mit Logfile einrichten

Ich habe heute auch mal den postfix-mta-sts-resolver auf meinem privaten System zugeschaltet. Einfach um es mal zu „probieren“.

Tut einfach und wie beschrieben, ist so aber sicher nicht für größeren und produktiven Betrieb gedacht. So wie der resolver kommt schreibt er alle Meldungen leider nur in die Konsole, es gibt keinen File-Logger. Ich ähm will/brauch den aber!

Also habe ich einen Fork erstellt und ihn überredet in eine Datei zu loggen und direkt noch ein sehr rudimentäres rc.d init script beigelegt: https://github.com/Kernel-Error/postfix-mta-sts-resolver

Wer es also ebenfalls mal probieren möchte, viel Spaß.

Der mta-sts-daemon loggt nun per default in /var/log/mta-sts.log. Config über yml ist ebenfalls nun drin genau wie die Konfiguration per Startparameter. Das rc.d script für FreeBSD könnte sicher schöner sein und hätte gerne im default den Benutzer mta-sts im System. Wir wollen es ja nicht als Root laufen lassen, hm?

Das einzelne Programm mta-sts-query greift auf den gleichen Logger zu, gibt damit also nichts mehr in der Konsole aus sondern auch im Logfile. Vielleicht passe ich dieses noch an, wenn dann mache ich auch einen pull request. Sonst gehe ich mal davon aus, dass es eh bald im postifx ist *daumen-drück*


Update

Habe ich jetzt gemacht. Pullrequest wurde angenommen und das neue Release ist auch schon gemacht. Jetzt also mit Logfile und rc.d script für FreeBSD.

Fragen? Dann fragen.

Siehe auch: MTA-STS einrichten

Fragen? Einfach melden.

MTA-STS einrichten: Transportverschlüsselung für E-Mail erzwingen

SMTP überträgt E-Mails standardmäßig im Klartext. Mit STARTTLS lässt sich die Verbindung verschlüsseln, aber kein sendender Server ist gezwungen das auch zu tun. Schlimmer noch: Ein Angreifer im Netzwerk kann die STARTTLS-Antwort einfach unterdrücken und die Verbindung bleibt unverschlüsselt. MTA-STS (RFC 8461) löst dieses Problem: Der Empfänger veröffentlicht eine Policy, die sendenden Servern sagt „hier wird nur verschlüsselt zugestellt, mit gültigem Zertifikat, an genau diesen MX“.

MTA-STS vs. DANE

Es gibt zwei Wege, Transportverschlüsselung für E-Mail zu erzwingen: DANE und MTA-STS. DANE nutzt DNSSEC und TLSA-Records im DNS. Das ist technisch sauberer, setzt aber DNSSEC auf der Empfängerseite voraus. Viele große Provider (Google, Microsoft) haben kein DNSSEC. MTA-STS funktioniert ohne DNSSEC: Die Policy liegt als Textdatei auf einem Webserver, abgesichert durch ein normales TLS-Zertifikat. Wer beides kann, sollte beides einsetzen. DANE für die Server die DNSSEC können, MTA-STS für den Rest.

Die drei Komponenten

MTA-STS besteht aus drei Teilen: einem DNS-Record, einer Policy-Datei auf einem Webserver und optional TLS Reporting.

1. DNS TXT-Record

Ein TXT-Record unter _mta-sts.domain.de signalisiert, dass eine Policy existiert:

_mta-sts.kernel-error.de.  IN TXT  "v=STSv1;id=20260115130000Z;"

Die id ist ein beliebiger String. Sendende Server cachen die Policy und prüfen über die ID ob sich etwas geändert hat. Bei jeder Policy-Änderung muss die ID aktualisiert werden. Ich verwende dafür einen Zeitstempel, das macht es nachvollziehbar.

2. Policy-Datei

Die eigentliche Policy liegt unter https://mta-sts.domain.de/.well-known/mta-sts.txt. Wichtig: Der Webserver muss ein gültiges TLS-Zertifikat haben und unter genau diesem Hostnamen erreichbar sein.

version: STSv1
mode: enforce
mx: smtp.kernel-error.de
max_age: 2419200
modeenforce = nur verschlüsselt zustellen. testing = wie enforce, aber bei Fehlern trotzdem zustellen (gut zum Einstieg). none = Policy deaktiviert.
mxAn welche MX-Server zugestellt werden darf. Mehrere Einträge möglich (je eine Zeile). Wildcards gehen: *.kernel-error.de
max_ageWie lange die Policy gecacht wird, in Sekunden. 2419200 = 28 Tage.

Der empfohlene Weg: Mit mode: testing anfangen und die TLS-Reports auswerten. Wenn alles sauber ist, auf enforce umstellen.

3. TLS Reporting

Wie bei DMARC gibt es auch für MTA-STS ein Reporting-System: SMTP TLS Reporting (RFC 8460). Ein weiterer DNS TXT-Record teilt Absendern mit, wohin sie Berichte über TLS-Verbindungsprobleme schicken sollen:

_smtp._tls.kernel-error.de.  IN TXT  "v=TLSRPTv1;rua=mailto:postmaster@kernel-error.de"

Die Reports kommen als JSON per Mail und enthalten Informationen über fehlgeschlagene TLS-Verbindungen, ungültige Zertifikate oder MX-Mismatches. Google und Microsoft schicken diese Reports zuverlässig.

Postfix und MTA-STS

Postfix prüft von Haus aus keine MTA-STS-Policies. Für die ausgehende Seite braucht es postfix-mta-sts-resolver, ein Policy-Daemon der sich als smtp_tls_policy_maps in Postfix einhängt. Der Daemon cached die Policies und liefert Postfix die passende TLS-Konfiguration pro Zieldomain.

# /usr/local/etc/postfix/main.cf
smtp_tls_policy_maps = socketmap:unix:/var/run/mta-sts-daemon/mta-sts-daemon.sock:postfix

Die eingehende Seite braucht keine Software. Die drei DNS-Records und die Policy-Datei auf dem Webserver reichen aus. Sendende Server wie Gmail, Outlook oder Yahoo werten die Policy selbständig aus.

Testen

# DNS-Records prüfen
dig TXT _mta-sts.kernel-error.de +short
dig TXT _smtp._tls.kernel-error.de +short

# Policy abrufen
curl https://mta-sts.kernel-error.de/.well-known/mta-sts.txt

Siehe auch: internet.nl: Mailserver-Sicherheit testen mit dem niederländischen Standard, TLS 1.3 für Postfix & Dovecot: Einrichtung und Konfiguration, internet.nl verschärft die TLS-Anforderungen für Mailserver

Zusammen mit SPF, DKIM, DMARC und DANE ergibt MTA-STS eine lückenlose Absicherung: Authentifizierung (wer darf senden), Integrität (DKIM-Signatur) und Transportverschlüsselung (DANE/MTA-STS). Fragen? Einfach melden.

TLS 1.3 für Postfix & Dovecot: Einrichtung und Konfiguration

TLS 1.3 ist im Mailbetrieb kein Sonderfall mehr, sondern der Normalzustand. Voraussetzung ist lediglich, dass Postfix und Dovecot gegen eine aktuelle OpenSSL-Version gelinkt sind. Sobald OpenSSL TLS 1.3 unterstützt, wird es automatisch verwendet. Eine explizite Aktivierung in der Applikation ist nicht erforderlich.

Die eigentliche Aufgabe der Konfiguration besteht daher nicht darin, TLS 1.3 „einzuschalten“, sondern darin, alte Protokollversionen sauber zu deaktivieren und für den verbleibenden TLS-1.2-Fallback eine kontrollierte Cipher-Policy zu definieren.

Illustration zu TLS 1.3 im Mailbetrieb: Symbolische Darstellung von Postfix und Dovecot mit Schloss und Schlüssel vor Server-Hintergrund, steht für verschlüsselte SMTP- und IMAP-Verbindungen mit modernen TLS-Standards.

Voraussetzungen

Postfix und Dovecot müssen gegen OpenSSL ≥ 1.1.1 gebaut sein. OpenSSL 3.x funktioniert ebenfalls ohne Einschränkungen. Welche Version tatsächlich genutzt wird, lässt sich eindeutig prüfen:

postconf -a | grep -i tls
dovecot --version
ldd $(which dovecot) | grep ssl
openssl version

Wenn hier OpenSSL 1.1.1 oder neuer auftaucht, ist TLS 1.3 verfügbar.

Postfix

Postfix verwendet TLS 1.3 automatisch, sofern der Client es anbietet. Entscheidend ist, welche Protokollversionen minimal erlaubt werden. TLS 1.0 und TLS 1.1 gelten als kryptographisch überholt und sollten nicht mehr akzeptiert werden.

Die folgende Konfiguration beschränkt Postfix auf TLS 1.2 und neuer. TLS 1.3 wird dabei bevorzugt ausgehandelt, TLS 1.2 dient nur noch als Fallback.

smtpd_tls_protocols = >=TLSv1.2
smtp_tls_protocols  = >=TLSv1.2

smtpd_tls_security_level = may
smtp_tls_security_level  = may

smtpd_tls_cert_file = /etc/letsencrypt/live/DOMAIN/fullchain.pem
smtpd_tls_key_file  = /etc/letsencrypt/live/DOMAIN/privkey.pem

Cipher-Optionen in Postfix gelten ausschließlich für TLS 1.2 und ältere Protokolle. TLS 1.3 verwendet fest definierte Cipher-Suites und ignoriert diese Einstellungen vollständig. Dennoch ist es sinnvoll, für den TLS-1.2-Fallback eine saubere Policy zu setzen.

tls_preempt_cipherlist = yes

smtpd_tls_ciphers = high
smtp_tls_ciphers  = high

Damit werden nur moderne Cipher mit Forward Secrecy genutzt, abhängig von den OpenSSL-Defaults der jeweiligen Distribution. Wer zusätzlich sicherstellen will, dass ausgehende Verbindungen verschlüsselt bleiben, sollte sich MTA-STS ansehen.

Session-Caching reduziert Handshake-Overhead und sollte aktiv sein:

smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database  = btree:${data_directory}/smtp_scache

Dovecot

Auch Dovecot nutzt TLS 1.3 automatisch, sofern OpenSSL es bereitstellt. Die relevante Einstellung ist die minimale Protokollversion. Alles darunter wird explizit ausgeschlossen.

ssl = required
ssl_min_protocol = TLSv1.2

Die Cipher-Liste in Dovecot betrifft ebenfalls nur TLS 1.2 und älter. TLS 1.3 wird davon nicht beeinflusst. Eine explizite, restriktive Cipher-Liste verhindert jedoch unsaubere Fallbacks bei älteren Clients.

ssl_cipher_list = \
ECDHE-ECDSA-CHACHA20-POLY1305:\
ECDHE-RSA-CHACHA20-POLY1305:\
ECDHE-ECDSA-AES256-GCM-SHA384:\
ECDHE-RSA-AES256-GCM-SHA384

ssl_prefer_server_ciphers = yes

Die Zertifikate werden wie gewohnt eingebunden:

ssl_cert = </etc/letsencrypt/live/DOMAIN/fullchain.pem
ssl_key  = </etc/letsencrypt/live/DOMAIN/privkey.pem

TLS 1.3 und Cipher-Suites

TLS 1.3 unterscheidet sich grundlegend von älteren Versionen. Die Cipher-Suites sind fest definiert und bestehen ausschließlich aus modernen AEAD-Verfahren mit integrierter Authentifizierung und Forward Secrecy. Typische Cipher sind AES-GCM und CHACHA20-POLY1305.

Postfix und Dovecot bieten keine Möglichkeit, diese Cipher direkt zu konfigurieren. Die Auswahl erfolgt intern durch OpenSSL während des Handshakes. Das ist beabsichtigt und reduziert Fehlkonfigurationen erheblich.

Wer versucht, TLS-1.3-Cipher über Applikationsoptionen zu beeinflussen, konfiguriert faktisch nur TLS 1.2.

Verifikation

Ob TLS 1.3 tatsächlich genutzt wird, lässt sich eindeutig prüfen.

SMTP mit STARTTLS:

openssl s_client -starttls smtp -connect mail.example.com:25 -tls1_3

IMAPS:

openssl s_client -connect mail.example.com:993 -tls1_3

Wird der Handshake erfolgreich aufgebaut und ein moderner AEAD-Cipher angezeigt, ist TLS 1.3 aktiv. Fällt die Verbindung auf TLS 1.2 zurück, greift die konfigurierte Cipher-Liste.

Fazit

TLS 1.3 erfordert in Postfix und Dovecot keine Sonderbehandlung. Entscheidend ist eine aktuelle OpenSSL-Version, eine klare Mindest-TLS-Policy und eine saubere Cipher-Konfiguration für den unvermeidbaren TLS-1.2-Fallback.

Alles andere erledigt der TLS-Stack selbst. Wer noch einen Schritt weiter gehen will, findet im Beitrag zu Post-Quantum TLS für E-Mail die nächste Stufe.

Kein Feature-Flag.
Keine Magie.
Nur korrekte Defaults, bewusst begrenzt.

Fragen? Einfach melden.

Anruf bei der G Data Hotline: Ein Erfahrungsbericht

Ich: tuuuuut…… tuuuuuut
Hotline: Bla gdata Hotline bla
Ich: Pffffhhhh
Hotline: *laala* (mucke)
Ich: Pffffhhhh
Hotline: Willkommen an der Hotline, mein Name ist Mann, was kann ich für sie tun?
Ich: Sie brauchen sicher meinen Benutzernamen, oder?

Das scheint da so etwas wie die Kundennummer in anderen Unternehmen zu sein….

Hotline: Oh ja, den nehme ich gerne.
Ich: Konrad-5-Julius-Heinrich-97- [Hotlinemann unterbricht mich]
Hotline: Konrad ausgeschrieben?
Ich: Öhm ähh ne also öh der Buchstabe?!?
Hotline: OK
Ich: Kundenummer…
Hotline: und was kann ich nun für sie tun?
Ich: Wir testen gerade die Amavis Integration eurer G DATA Business Lösung und das läuft nicht ganz rund.
Hotline: uhhaaa ohh
Ich: Warum uhaaa ohh?
Hotline: Öhm (hehe) also ähh, da bekommen wir eher weniger Anfragen. Wird nicht so oft benutzt.
Ich: Na aber ihr verkauft das ja.
Hotline: Ja aber ähh gut.


Dann wurden Version und OS abgefragt und ein Ticket angelegt. Ich sollte mal Auszüge aus dem Maillog senden. irgendwie habe ich das Gefühl als wenn das gerade nix wird.

Für Spaß auch mal die Logfiles:

Feb  7 08:27:54 mx amavis[27217]: (21323-04-4) (!)run_command: child process [27217]: Insecure dependency in exec while running with -T switch at /usr/sbin/amavisd-new line 4743.
Feb  7 08:27:54 mx amavis[21323]: (21323-04-4) (!!)collect_results from [27217] (/usr/bin/gdmailscannerc): exit 3 Feb  7 08:27:54 mx amavis[21323]: (21323-04-4) (!)checking with spam scanner GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158.
Feb  7 08:27:54 mx amavis[21323]: (21323-04-4) (!!)TROUBLE in check_mail: spam_scan FAILED: GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158. at (eval 98) line 159.
Feb  7 08:27:54 mx amavis[21323]: (21323-04-4) (!)PRESERVING EVIDENCE in /var/lib/amavis/tmp/amavis-20170207T082744-21323-gFK_Ofar
Feb  7 08:27:54 mx postfix/smtp[27003]: EFA15C0A13: to=<type@domain.de>, relay=127.0.0.1[127.0.0.1]:10024, conn_use=4, delay=85234, delays=85181/42/0/10, dsn=4.5.0, status=deferred (host 127.0.0.1[127.0.0.1] said: 451 4.5.0 Error in processing, id=21323-04-4, spam_scan FAILED: GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158. at (eval 98) line 159. (in reply to end of DATA command)) Feb  7 08:27:54 mx amavis[27219]: (21323-04-5) (!)run_command: child process [27219]: Insecure dependency in exec while running with -T switch at /usr/sbin/amavisd-new line 4743.
Feb  7 08:27:54 mx amavis[21323]: (21323-04-5) (!)run_av (GDAVCLIENTC SCANNER.) FAILED - unexpected , output=""
Feb  7 08:27:54 mx amavis[21323]: (21323-04-5) (!)GDAVCLIENTC SCANNER. av-scanner FAILED: CODE(0x2cc4260) unexpected , output="" at (eval 97) line 905.
Feb  7 08:27:54 mx amavis[21323]: (21323-04-5) (!)WARN: all primary virus scanners failed, considering backups Feb  7 08:27:54 mx amavis[27221]: (20783-09-4) (!)run_command: child process [27221]: Insecure dependency in exec while running with -T switch at /usr/sbin/amavisd-new line 4743.
Feb  7 08:27:54 mx amavis[20783]: (20783-09-4) (!!)collect_results from [27221] (/usr/bin/gdmailscannerc): exit 3 Feb  7 08:27:54 mx amavis[20783]: (20783-09-4) (!)checking with spam scanner GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158.
Feb  7 08:27:54 mx amavis[20783]: (20783-09-4) (!!)TROUBLE in check_mail: spam_scan FAILED: GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158. at (eval 98) line 159.
Feb  7 08:27:54 mx amavis[20783]: (20783-09-4) (!)PRESERVING EVIDENCE in /var/lib/amavis/tmp/amavis-20170207T082744-20783-75UHo67I
Feb  7 08:27:54 mx postfix/smtp[27159]: D74F7C00F4: to=<type@domain.de>, relay=127.0.0.1[127.0.0.1]:10024, conn_use=4, delay=342238, delays=342185/42/0/10, dsn=4.5.0, status=deferred (host 127.0.0.1[127.0.0.1] said: 451 4.5.0 Error in processing, id=20783-09-4, spam_scan FAILED: GDATA_SPAM_SCANNER failed: GdataSpamScanner: Failed processing request; illegal response(%d) at /usr/local/lib/site_perl/Amavis/SpamControl/GdataSpamScanner.pm line 158. at (eval 98) line 159. (in reply to end of DATA command)) Feb  7 08:27:55 mx amavis[20783]: (20783-09-5) Passed CLEAN {RelayedInbound}, SPAM_DISC [1.2.3.4]:44419 [1.2.3.4] <type@domain.de> -> <type@domain.de>, Queue-ID: 6D65CC0A33, Message-ID: <62734015.3835.1486452455492.JavaMail@domain.de>, mail_id: lsOZOYNAIa3o, Hits: 0, size: 44774, queued_as: 57B04C0A40, 471 ms

Feb  7 09:55:25 mx amavis[22893]: (22893-07) Passed CLEAN {RelayedInbound}, SPAM_DISC [1.2.32.4]:36945 [1.5.7.98] <type@domain.de> -> <type@domain.de>, Queue-ID: E7592C0071, Message-ID: <20170207085513.B8A52340881@domain.de>, mail_id: 3lhpfBFnyuAI, Hits: 0, size: 4172, queued_as: 1F499C00F7, 10166 ms Feb  7 09:55:25 mx amavis[20843]: (20843-14) (!)run_av (GDAVCLIENTC SCANNER.) FAILED - unexpected , output="SKIP"
Feb  7 09:55:25 mx amavis[20843]: (20843-14) (!)GDAVCLIENTC SCANNER. av-scanner FAILED: CODE(0x2cc4260) unexpected , output="SKIP" at (eval 97) line 905.
Feb  7 09:55:25 mx amavis[20843]: (20843-14) (!)WARN: all primary virus scanners failed, considering backups

Fragen? Einfach melden.

« Ältere Beiträge

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑