Outbound DANE in 15 Minuten einrichten

DANE gesicherter Versand von E-Mail ist mit wenigen Handgriffen eingerichtet. Anders als viele vermuten, ist es dafür nicht notwendig die eigene Domain mit DNSSEC abzusichern. Dieser Artikel zeigt wie Postfix durch Verändern von nur zwei Optionen so konfiguriert werden kann, dass er beim Versand immer dann DANE nutzt, wenn die andere Seite dieses Sicherheitslevel anbietet.

Ein wenig Theorie…

DANE-gesicherter Transport verifiziert die Identität des Servers, zu dem eine TLS-verschlüsselte Verbindung aufgebaut werden soll. Dazu prüft jener Server, der die Nachricht senden will, ob die Domain des Zielservers DNSSEC-aktiviert ist. Ist das der Fall, prüft der SMTP-Client ob ein TLSA-Record für den Mailserver hinterlegt wurde.

Für den MX der sys4 AG (mail.sys4.de) prüft der Client dafür ob auf dem dafür bestimmten Port tcp/25 ein TLSA-RR vorliegt:

$ dig @9.9.9.9 TLSA _25._tcp.mail.sys4.de

; <<>> DiG 9.13.7 <<>> @9.9.9.9 TLSA _25._tcp.mail.sys4.de
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4132
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1        (1)

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;_25._tcp.mail.sys4.de.		IN	TLSA

;; ANSWER SECTION:
_25._tcp.mail.sys4.de.	3600	IN	TLSA	3 1 1 236831AEEAB41E7BD10DC14320600B245C791B338121383D5A2916F7 EF97B49B        (2)

;; Query time: 238 msec
;; SERVER: 9.9.9.9#53(9.9.9.9)
;; WHEN: Mo Mär 04 10:01:14 CET 2019
;; MSG SIZE  rcvd: 97
1 Das ad-flag zeigt bei den Daten der Zone sys4.de handelt es sich um „Authentic Data” – die Domain ist DNSSEC-gesichert.
2 Der <rdata>-Teil des TLSA-Records – das ist in der Zeile alles nach dem TLSA – beschreibt Eigenschaften des Zertifikat das der Mailserver verwendet.

Mit dem Daten, welche die DNS-Anfrage zurückgeliefert hat, prüft der SMTP-Client in der nun folgenden SMTP-Session mit dem Zielserver ob dessen Fähigkeiten und Identität mit den Vorgaben aus der DNS-Anfrage übereinstimmen.

Fähigkeiten

Allein die Existenz eines TLSA-RR teilt dem Client mit, dass der Zielserver TLS unterstützen sollte. Zeigt der Server im, die Session einleitenden SMTP-Banner kein ESMTP an, wird konsequenterweise keine TLS-gesicherte Verbindung zustande kommen.
Fehlt das ESMTP muss der Client annehmen, dass der Server auch nicht die für TLS erforderliche Fähigkeit STARTTLS beherrscht. Diese ist Teil der ursprünglichen Spezifikation von SMTP gewesen; sie wurde erst später als eine von mehreren „capabilities“ (engl. Fähigkeiten) hinzugefügt.
Beherrscht der Server ESMTP, bietet aber kein STARTTLS an, führt auch das zum Verbindungsabbruch. In beiden Fällen muss der Client davon ausgehen, dass die Verbindung manipuliert wurde und möglicherweise ein Session Downgrade vorliegt.

"SHOULD" und "MUST" in RFCs

Lange Zeit nahm ich an, ein "SHOULD", so wie es in den RFCs steht, sei als guter Rat und Empfehlung zu verstehen. Viktor Dukhovni hat mich dann irgendwann in einem Gespräch aufgeklärt: In RFCs wird "SHOULD" als forderndes „das sollte wirklich so sein“ verstanden. Ein "MUST" hat in dem Kontext was von „wenn das nicht so ist, werden wir alle sterben…“. ;-)

Identität

Der RDATA-Anteil des TLSA-RR beinhaltet Angaben über das Zertifikat, welches der Server in der TLS-Session einsetzen soll, verifiziert werden kann. Stimmen diese Angaben nicht mit den Vorgaben des TLSA-RR ein muss der Client davon ausgehen, dass er nicht mit dem richtigen Server spricht. Es könnte sich um eine „Man-in-the-Middle“-Attacke handeln. Der Client bricht die Session folgerichtig ab und sendet die E-Mail nicht.

Ein DNSSEC-fähiger Resolver muss her!

Postfix verlässt sich bei DNS-Anfragen auf jene DNS-Resolver, die das Betriebsystem seinen Applikationen über Einträge in der Datei /etc/resolv.conf bereitstellt. Deren Fähigkeit, DNSSEC-signierte Domains zu erkennen, muss sichergestellt werden, bevor der Postfix SMTP-Client auf DANE-Verifkation umgestellt wird.

Beherrscht keiner der genutzten Resolver DNSSEC, kann Postfix auch keinen DANE-gesicherten Versand durchführen. Beherrschen nur manche, aber nicht alle gelisteten DNS-Resolver DNSSEC, ist keine lückenlose Verifikation gegeben und der Resolver-Stack ist als nicht sicher zu betrachten.

Lückenloses DNSSEC

DNSSEC prüft ob die Einträge einer Domain signiert sind und verifiziert werden können. Kann ein Eintrag in einer DNSSEC-signierten Domain nicht verifiziert werden, unterrückt ein DNSSEC-fähiger Resolver die Antwort denn er muss davon ausgehen, dass der Antwort nicht zu trauen ist.

Befindet sich in einer Kette von DNS-Resolvern nur einer, der nicht mit DNSSEC umgehen kann und wird dieser abgefragt, wird er mangels Verifizierung die Antwort an die Applikation nicht unterdrücken.

Gerade dann, wenn sichergestellt werden soll, dass die Antwort vertrauenswürdig ist, würde der eigene DNSSEC-unfähige Resolver eine Antwort geben, die das gesamte Sicherheitsmodell ad Absurdum führt. Aus diesem Grund muss DNSSEC auf den Resolvern durchgängig verfügbar sein.

Unbound

Ich setze auf Unbound von NLnet Labs. Dieser DNS-Resolver ist sehr schnell, vielseitig konfigurierbar und gut abgehangen.

Wieso nicht systemd-resolved?

Mit systemd hat der DNS-Resolver systemd-resolved Einzug in viele Betriebssysteme gehalten. Die Verlockung ist groß ihn einzusetzen, aber systemd-resolved liefert „'opportunistisches' DNSSEC. Wenn DNSSEC Validierung funktioniert, dann wird das AD-Flag gesetzt, wenn DNSSEC nicht validiert, wird die Antwort trotzdem zurückgegeben.” (Carsten Strotmann). Opportunistisches DNSSEC ist nicht das Sicherheitslevel, welches DANE benötigt. Deshalb kommt systemd-resolved hier nicht zur Anwendung.

Je nach Distribution finden sich nach der Installation einige Dateien und/oder zusätzliche Unterverzeichnisse in /etc/unbound/:

# ls /etc/unbound/
trusted-key.key  unbound.conf  unbound.conf.example

Unbound ist von Haus aus DNSSEC-valdierend, d.h. es kann erkennen ob die Zone einer Domain DNSSEC-signiert ist. Nach einem Start und einer kurzen Statusabfrage, ob er auch wirklich läuft geht es gleich darum herauszufinden wo Unbound auf Anfragen lauscht:

# systemctl start unbound
# systemctl status unbound
● unbound.service - Unbound DNS Resolver
   Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2019-03-04 14:26:02 CET; 1s ago
 Main PID: 1194 (unbound)
    Tasks: 1 (limit: 4915)
   Memory: 5.8M
   CGroup: /system.slice/unbound.service
           └─1194 /usr/bin/unbound

Mär 04 14:26:02 v22019012687780671 systemd[1]: Started Unbound DNS Resolver.
Mär 04 14:26:02 v22019012687780671 unbound[1194]: [1194:0] notice: init module 0: subnet
Mär 04 14:26:02 v22019012687780671 unbound[1194]: [1194:0] notice: init module 1: validator
Mär 04 14:26:02 v22019012687780671 unbound[1194]: [1194:0] notice: init module 2: iterator
Mär 04 14:26:02 v22019012687780671 unbound[1194]: [1194:0] info: start of service (unbound 1.9.0).

Wer einen Mailserver betreibt hat möglicherweise mehrere Resolver in Betrieb. Einen cachenden Resolver für lokale DNS-Anfragen und vielleicht noch einen, der DNS-basierte Blacklist-Anfragen beantwortet.

Weil ich das lsof-Kommando lieber als netstat mag, setze ich das nun ein um herauszufinden wer denn so alles auf Port 53 meines Servers lauscht:

# lsof -Poni :53                                                           (1)
COMMAND  PID    USER   FD   TYPE  DEVICE OFFSET NODE NAME
unbound 1194 unbound    3u  IPv6 4535314    0t0  UDP [::1]:53
unbound 1194 unbound    4u  IPv6 4535315    0t0  TCP [::1]:53 (LISTEN)
unbound 1194 unbound    5u  IPv4 4535316    0t0  UDP 127.0.0.1:53
unbound 1194 unbound    6u  IPv4 4535317    0t0  TCP 127.0.0.1:53 (LISTEN)
1 Ich mag Poni auch lieber als tulpen. ;-)

Jetzt, wo ich weiß auf welcher IP und welchem Port ich Unbound ansprechen muss, nutze ich das dig-Kommando.

# dig @127.0.0.1 +dnssec SOA sys4.de

; <<>> DiG 9.10.2-P4 <<>> @127.0.0.1 +dnssec SOA sys4.de                   (1)
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62485
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 3    (2)

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;sys4.de.			IN	SOA

;; ANSWER SECTION:
sys4.de.		3600	IN	SOA	ns.sys4.de. hostmaster.sys4.de. 2019030506 3600 3600 604800 3600
sys4.de.		3600	IN	RRSIG	SOA 8 2 3600 20190312022719 20190305115452 21474 sys4.de. FTsSOfCPI959KQYJtY7wHY9KvJv6Hw8/WX/UWpo+DbExbdFcqygOgP5C /x9k8XyCdoePJpZTpBPBoIRQJuEzZ3PlRPj/azN1qv1Hb64qAFWEMoIT mcjplH/6GXOXJXohBdjMU0j6sCCaowwR4jP9YNlrWcBNXWNwWpoZpz9Q 0Ig=

;; AUTHORITY SECTION:
sys4.de.		3600	IN	NS	ns.schiffbauer.net.
sys4.de.		3600	IN	NS	ns.sys4.de.
sys4.de.		3600	IN	RRSIG	NS 8 2 3600 20190312155143 20190305095452 21474 sys4.de. ueUAoNXPQnwu0tFy4F/Ff+R3nBFZi5SaZKM5fp4wGZnxI0t88TDaP7/r DS3P8HQPoQONB6FQnk1Inlj8ctM3Afb1J1te3kmb/oAifcvZdLU3llTC 2SeWmhVLgW3XgKQEfzFCFh62RTEcIXju1x+v6cbpUaulylb9jWXg/rD8 eJU=  (3)
1 Mit dem @127.0.0.1 weise ich dig an meinen Unbound zu fragen, der auf 127.0.0.1 lauscht.
2 Wie schon im Beispiel oben zeigt auch hier das ad-flag, dass die Daten erfolgreich authentifiziert werden konnten. Es ist eine gültige DNSSEC-aktivierte Domain.
3 Der digital signierte RRSIG-Record dient dazu die DNSSEC-Zone zu validieren.

Lokalen Resolver einbinden

Jetzt, da ich sichergestellt habe, dass ich mich auf meinen lokalen DNS-Resolver auch bei der DNSSEC-Valdierung verlassen kann, binde ich ihn in die /etc/resolv.conf ein:

nameserver 127.0.0.1
nameserver 192.0.2.1

Den zweiten Nameserver habe ich vorher auch mit dem drill-Kommando getestet und sichergestellt, dass auch er DNSSEC validieren kann, damit der Server über eine lückenlose DNSSEC-Validierung verfügt.

Outbound DANE in Postfix aktivieren

Postfix beherrscht seit Version 2.11.1 DANE. Ein kurzer Blick auf meinen installierten Postfix sagt mir es erfüllt die Voraussetzungen für DANE:

# postconf mail_version
mail_version = 3.4.0

Falls der Client bereits für „normales TLS“ konfiguriert war, muss nun der Parameter smtp_tls_security_level von may für „opportunistisches TLS“ auf dane für „opportunistisches DANE TLS“ abgeändert werden.

Zusätzlich und unabhängig von der Art des TLS, muss Postfix lernen ab sofort DNSSEC-Abfragen an seine Resolver zu stellen und nicht nur „einfaches DNS“. Dafür ist der Parameter smtp_dns_support_level im nachfolgenden Beispiel zuständig:

DANE in /etc/postfix/main.cf konfigurieren
smtp_dns_support_level = dnssec
smtp_tls_security_level = dane
smtp_tls_loglevel = 1

Das smtp_tls_loglevel setze ich auf 1, damit ich im LOG sehen kann ob die ausgehenden Verbindungen „nur“ normales oder „verified“ sind. Vermerkt der Postfix smtp-Client ein verified dann war es eine DANE-Verbindung und Postfix konnte die Indentität des Mailservers verifizieren.

Um das zu testen, sende ich eine Nachricht an sink@dane.sys4.de. Der sagt höflich Danke und wirft die Nachricht im Anschluss weg. Mir soll es recht sein, denn mich interessiert was mein DANE-aktivierter smtp-Client loggen wird:

# swaks -s 127.0.0.1 -f '<>' -t sink@dane.sys4.de
# grep Verified /var/log/mail.log
Mar  4 16:53:46 mail postfix/smtp[22611]: Verified TLS connection established to dane.sys4.de[194.126.158.134]:25: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)

Das Verified im LOG belegt, mein Client kann jetzt DANE-gesichert Nachrichten an Domains senden, die DNSSEC-gesichert sind und einen TLSA-RR für ihren Maildienst anbieten.

Patrick Ben Koetter, 04.03.2019

   DNSSEC    DANE