Einen TLSA-Record für DANE mit BIND 9 publizieren

Abstract

DANE-Sicherheit ist derzeit in aller Munde. Mittels DANE (DNS[SEC]-based Authentiction of Named Entities) können SSL/TLS-Zertifikate abgesichert werden. In diesem Artikel geht es um die DNS-Server-Seite von DANE, das Publizieren eines TLSA-Records.

DANE-Sicherheit ist derzeit in aller Munde. Mittels DANE (DNS[SEC]-based Authentiction of Named Entities) können SSL/TLS-Zertifikate abgesichert werden. In diesem Artikel geht es um die DNS-Server-Seite von DANE, das Publizieren eines TLSA-Records.

Note

Patrick hat in DNSSEC für Mailserver richtig einrichten die Client-Seite der DNSSEC-Einrichtung beschrieben.

DANE funktioniert derzeit für verschlüsselte Web-Anwendungen (HTTPS-Protokoll), E-Mail (SMTP) und Jabber Chat (XMPP). Weitere Internet-Protokolle werden in der Zukunft folgen. Diese Anleitung ist unabhängig vom Protokoll, das per DANE abgesichert wird. Die Schritte, die im DNS vorzunehmen sind, sind bei allen Protokollen identisch.

Der TLSA-Record (RFC 6698) speichert entweder ein kryptologischen Hash eines Zertifikats oder direkt das X.509-Zertifikat im DNS. Die sichere Benutzung von DANE setzt voraus, dass die DNS-Zone mit dem TLSA-Record per DNSSEC signiert ist.

DANE Übersicht

Note

Update 27. Mai 2014: Ablauf mit Informationen von Viktor Dukhovni über die Implementierung in Postfix erweitert und verbessert.

Die nachfolgenden Grafiken vermitteln eine Übersicht der Kommunikation im DANE-Protokoll (am Beispiel von DANE für SMTP-E-Mail):

  1. Ein Client liefert eine E-Mail an einen Mail-Server.
  2. Der Mail-Server ermittelt die Empfänger-Mail-Server mittels der MX-Records im DNS und prüft, ob die MX-Records per DNSSEC gesichert sind. Gibt es einen DNSSEC-Fehler, wird die Mail-Auslieferung verzögert (deferred).
  3. Sind die MX-Records mit DNSSEC abgesichert (DS-Record in der Eltern-Zone), so werden für jeden MX-Host...
  1. ...die Adress-DNS-Records (A für IPv4, AAAA für IPv6) per DNSSEC geprüft. Schlägt die DNS-Abfrage fehl, so wird der MX-Host übersprungen.
  1. Ermittle den TLSA-Record aus dem DNS. Der DNS-Resolver prüft via DNSSEC, ob der TLSA-Record eine korrekte DNSSEC-Signatur besitzt und ob sich die Signatur zu einem bekannten Trust Anchor (Vertrauensanker) validieren lässt. Das Ergebnis wird an den sendenden E-Mail-Server übermittelt (TLSA-Record mit AD-Flag bei positiver DNSSEC-Prüfung, Fehlermeldung SERVFAIL und kein TLSA-Record bei negativer DNSSEC-Prüfung). Bei fehlerhafter DNSSEC-Validierung wird der MX-Host übersprungen.
  2. Wurde ein benutzbarer TLSA-Record gefunden, konnte der TLSA-Record per DNSSEC geprüft werden und ist wenigstens eine Kombination aus MX- und A/AAAA-Records benutzbar, so wird TLS-Authentisierung vom entfernten Mail-Server verlangt (vergleichbar den Postfix-Sicherheitsleveln encrypt oder secure)
  1. Eine Verbindung zum entfernten Mail-Server auf Port 25 aufbauen, per STARTTLS eine verschlüsselte Verbindung starten. Wird kein STARTTLS angeboten, diesen Mail-Host überspringen.
  2. TLS-Handshake, das X.509-Zertifikat gegen die Werte im TLSA-Record prüfen, wenn das Zertifikat stimmt, dann die E-Mail über die verschlüsselte Verbindung austauschen. Stimmt das Zertifikat nicht mit den TLSA-Daten überein, wird dieser Server übersprungen.

Ein Zertifikat erstellen

Ein TLS-Zertifikat wird mit OpenSSL (oder LibreSSL) erstellt:

$ openssl genrsa -out <servername>.key 4096

Die Erstellung wird durch eine Konfigurationsdatei <servername>.conf vereinfacht. <servername> und die Werte der Konfigurationsdatei müssen an die eigene Situation angepasst werden. Hier ein Beispiel:

[ req ]
default_bits = 4096
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
prompt = no
req_extensions = v3_req

[ req_dn ]
C=DE
ST=Bayern
L=Muenchen
O=example.com
OU=Server
CN=<servername>
emailAddress=certmaster@example.com

[ cert_type ]
nsCertType = server

[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = mail.example.com
DNS.2 = helpdesk.example.com
DNS.3 = system.example.com

Mit dieser Konfigurationsdatei kann dann bequem ein Certificate Request generiert werden:

$ openssl req -new -nodes -key <servername>.key \
    -config <servername>.conf -out <servername>.csr

An dieser Stelle wird das erstellte csr (Certification Signing Request) an eine Zertifizierungstelle gesendet (z.B. CACert).

Note

DANE kann auch mit selbst-unterschriebenen Zertifikaten betrieben werden. Das Signieren des Zertifikats durch eine offizielle CA ist also nicht zwingend notwendig.

Von der Zertifizerungsstelle wird eine crt-Datei zurückgesendet, die das unterschriebene Zertifikat enthält. Aus dieser Datei wird in den folgenden Schritten das Zertifikat für den Server erstellt.

$ cat <servername>.key <servername>.crt > <servername>.pem
$ openssl gendh >> <servername>.pem
$ chmod 400 <servername>.*
$ openssl x509 -text -in <servername>.pem

Dieses Zertifikat wird nun in den Server (Web-Server, Mail-Server, Jabber-Server etc.) eingebunden.

Den TLSA-Record erstellen

DANE und der TLSA-Record können in verschiedenen Kombinationen zur Prüfung von Zertifikaten benutzt werden. Die verschiedenen Optionen des TLSA-Records können im RFC nachgelesen werden. Hier erstellen wir einen TLSA-Record für den Benutzungstyp "DANE-EE (Domain-issued certificate)" (Wert 3), den Selector "Cert (Hash des vollen Zertifikats)" (Wert 0) mit dem Hash-Algorithmus (Matching-Type) "SHA2-256" (Wert 1). In den Flag-Feldern des TLSA-Records stehen die Werte 3 0 1.

Der folgende OpenSSL-Befehl erzeugt den SHA2-256-Hash des Zertifikats:

$ openssl x509 -in <servername>.crt -outform DER | openssl sha256

(stdin)=8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1
$

In Verbindung mit den Flags 3 0 1 ergibt sich der folgende TLSA-Record:

_25._tcp.<servername>.   IN TLSA 3 0 1 \
    8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1

oder mit einem konkreten DNS-Namen des Servers (hier: mail.example.com):

_25._tcp.mail.example.com.  IN TLSA 3 0 1 \
    8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1

Dieser Record wird in die DNS-Zone (hier die Zone example.com) kopiert.

Die Zone per DNSSEC signieren

Damit die Empfänger des TLSA-Records den Daten auch vertrauen können, muss die DNS-Zone, die den TLSA-Record enthält, per DNSSEC signiert werden. Das Signieren von DNS-Zonen ist ein großes Thema, zu groß für diesen Blog-Artikel. Es folgt eine Anleitung für BIND 9.7.2 (und neuer) mit dynamischen Zonen, die aber aus Platzgründen nicht auf alle Feinheiten des DNSSEC-Signierens eingehen kann.

Note

Wer sich im Detail mit DNSSEC beschäftigen möchte, dem empfehle ich (m)einen DNSSEC-Kurs (z.B. im LinuxHotel) und das Buch DNSSEC Mastery von Michael W. Lucas.

DNSSEC in der BIND-9-Konfiguration aktivieren

In der BIND-9-Konfigurationsdatei named.conf schalten wir DNSSEC an und die Resolver-Funktion ab, denn DNSSEC erwartet, dass autoritative DNS-Server mit Zonen und die DNS-Resolver/Caching-DNS-Server unterschiedliche Systeme sind:

options {
   # Haupt- und Schlüsselverzeichnis
   directory "/var/named";
   key-directory "keys";
   # DNSSEC anschalten
   dnssec-enable yes;
   # Resolver abschalten
   recursion no;
   # weitere Optionen
   ...
};

BIND 9 wird nun im Verzeichnis /var/named/keys nach DNSSEC-Schlüsseln suchen. BIND 9 prüft dieses Verzeichnis alle 60 Minuten; ist ein gültiger DNSSEC-Schlüssel für eine Domain dort hinterlegt (und DNSSEC für die Domain aktiviert), so wird die Domain automatisch signiert.

Important

Die Domain wird mit jedem gültigen Schlüssel der Domain signiert. Es darf – außer bei einem Key-Rollover – immer nur ein gültiges Schlüsselpaar (KSK und ZSK) pro Domain in diesem Verzeichnis liegen. Ist das nicht der Fall, wird die DNS-Zone mit mehreren Schlüsseln signiert, was zu sehr großen DNS-Antworten und zu potentiellen DDoS-Angriffen auf oder mittels des DNS-Servers führen kann

DNSSEC und dynamische Updates für die Zone aktivieren

Damit BIND 9 die DNS-Zone per DNSSEC signiert, muss die automatische DNSSEC-Verwaltung für dynamische Zonen auf der Zone angeschaltet werden. Die automatische DNSSEC-Verwaltung im BIND 9 sorgt dafür, dass

  • die DNSSEC-Signaturen erneuert werden (Signature Refresh). DNSSEC-Signaturen haben eine fest voreingestellte Lebenszeit und müssen vor dem Verfallsdatum (Expiry Date) neu erstellt werden
  • für neue DNS-Records in der Zone diese Records per DNSSEC signiert werden
  • für gelöschte DNS-Records die Signaturen auch gelöscht werden
  • die öffentlichen Teile der DNSSEC-Schlüssel in der Zone publiziert werden (DNSKEY Records)
  • bei jeder Änderung die Serienummer der Zone im SOA-Record hochgezählt (und der SOA-Record neu signiert) wird

Eine Zone sieht dann in etwa so aus:

zone "example.com" {
   type master;
   file "masters/example.com";
   # lokale dynamische Updates aktivieren
   update-policy local;
   # DNSSEC-Automatisierung aktivieren
   auto-dnssec maintain;
};

Nun die BIND-9-Konfiguration prüfen, und wenn kein Fehler angezeigt wird, die Konfiguration in den BIND-9-DNS-Server laden:

% named-checkconf -z
% rndc reload

Nach dem Reload behandelt BIND die Zone example.com als dynamische DNS-Zone.

Important

Die Zonendatei einer dynamischen Zone auf der Festplatte darf unter keinen Umständen mit einem Editor bearbeitet werden. Alle Änderungen müssen über "dynamische Updates" an den DNS-Server gesendet werden, z.B. mit dem nsupdate-Programm (Beispiele folgen weiter unten).

DNSSEC-Schlüssel für die Zone erzeugen

Damit BIND 9 die Zone per DNSSEC signieren kann, werden zwei Schlüssel für die DNS-Zone benötigt: ein Zone Signing Key (ZSK) und ein Key Signing Key (KSK). Beide Schlüssel erstellen wir im Verzeichnis /var/named/keys.

Important

Die Schlüssel müssen vom BIND-9-Prozess named lesbar sein!

% dnssec-keygen -a RSASHA256 -b 2048 -K /var/named/keys -n ZONE example.com
% dnssec-keygen -a RSASHA256 -b 2560 -f KSK -K /var/named/keys -n ZONE example.com

Wenn die Schlüssel erzeugt sind, wird BIND 9 die Zone nach spätestens 60 Minuten automatisch signieren. Wer nicht solange warten möchte, kann den Signaturvorgang anstoßen:

% rndc sign example.com

Ein schneller Test zeigt uns, dass die DNSKEY-Records in der Zone publiziert wurden (und Signaturen/RRSIG-Records vorhanden sind):

% dig @localhost dnskey example.com +dnssec +multi
; <<>> DiG 9.9.4-P2 <<>> @localhost example.com dnskey +dnssec +multi
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10300
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;example.com.               IN DNSKEY

;; ANSWER SECTION:
example.com.                7200 IN DNSKEY 256 3 8 (
                            AwEAAc9OHopRwAafweStGCMifqaDpFPm9EtA2t5yzXC8
                            N7EAvqXgRxO5YNCHxJ0ZrSAzqVgDM0WS0W1GBPcbqDfB
                            GBh6Lj+BwNZE3poC//iAdTOXAx+7REnlxJ4T0/L0f/iT
                            /54X7+aQmdCDji3OQrKUB9p/4nyAyuTur0Nsr5F9NUHj
                            ) ; ZSK; alg = RSASHA256; key id = 64491
 example.com.               7200 IN DNSKEY 257 3 8 (
                            AwEAAdRNEDl+Ft7juCrPE50X/AHPkb0ADh+DRff7NfxH
                            7L1+SbB4+/3JjjFccH0/PkHtyYTnCI9VLq+c0O7X0P3t
                            Nh6WxDSkYTW1dFySssVQfY8ik8qwMOPTHOgJu76Gr8o5
                            L4hhT8w4qG/S44mSYE5eGsaDwkdG9peMtL9pdwRbM8eW
                            Ul4oHpccs6wndaGuQKaU+6e3eqMd57ElaCLZ1mDL1L0T
                            S4Ev27keFncfQwT5CYmeMGEq6/Q9J7qRrAJqRmVvIqqa
                            fHKhVea5EOktWpi2liCXmDAZRS2lQltTf/+XrNDgJU94
                            cDHhRwIGjRlC1O3pryWo5n6Ahim7pO6zhB4C84AVKaKe
                            eQCz9Oo39kO4AD03si+fbfHy4cbEERbBQRD8KjvPx8Vy
                            SV50VgtXwi4BfEncaVtjFstnNPmqbssArOJ/EumWRr99
                            a/tvjurr8QDoTuDGn3M+TzBb/Q+GO1aenzgkjbJ3fAgX
                            s2kPxcwI1loucJ/vmOUtqnENp99vY61BMElBhhj/78+U
                            s/Xdz2E4JZCB/YIgLIjmvC2/A+wq0Bwwoyz1aPgNqCW2
                            wIqAuJ7e2RN+JaCB0AJNM38IopjYkA+0FkkMdggq41AC
                            V9vNgTf83Ni6BtoGAn7lfVUtuKYo5eO+dWvs/y5dz1TY
                            1dFSsfeE5BYuI4Fx5DoOVPMzLNXP
                            ) ; KSK; alg = RSASHA256; key id = 40924
 example.com.               7200 IN RRSIG DNSKEY 8 2 7200 (
                            20140606210719 20140507203158 40924 example.com.
                            YHYAgdDUbuZtfHlHy08eUI8FKjWTaRm8EOkd7GrdOHOF
                            qtH1WZrufFsKyBgbNIdXjI8CwVmH9Iwk7KslCYj5GEPH
                            rkdBdiFEX50J2CkOXjLSzw1l93iX9JT7Rm94yffPCzwq
                            Zu2gy8KYPDa5IsJKIJeMULyOevIVRWk5VpHl6neseL1B
                            hSVp94VSPuACBtFHLAk8rBDU1gp5P53j6QQR6JN8bXIT
                            bgdFgd7KVQUr9YOISekwcs9/xF2UHObiq456mqqSvK0v
                            5vQNB1/cBnrc32iCD0aENlg9Oy+Vt1PMia4jiNxNt3je
                            Cva3rTilheFpolkeQGhqXVVY+mxqD8dKi+FQ1PhNhJEI
                            Kxh58SwqObda6z5egm7oMgHfwZ/mIbnkskFzHbAW+JxU
                            /LGHIOAN8fjawE/61fCmzwsXYnKQSf6vENIgnF7qrI39
                            A/Gipc4nNsbcggaU/47xqvTpDZsPvlMDp7UN5cNzFM/C
                            DDwYNaxmNvmP4DqaoJHk7+U7lLTR7mJzeTpEoqc9twbb
                            YKp2Ow3k+p8z6mg+YzCrMzCbnyUWrc7sOl5VHVl2Iit7
                            OxFSduPVcxFKD7TfjnBEQRtrTWR9+MKFspp1xE8W0y5z
                            ll/HU1dMDuPfksM/+JPQyd6lUFQqLZMFCcuZrZvLC21A
                            +H5+8kHtgSl7ljJRmKFmNns= )
example.com.                7200 IN RRSIG DNSKEY 8 2 7200 (
                            20140606210719 20140507203158 64491 example.com.
                            UCvuolv39URExNKeYiV0NT2Ho0cPlah7n3OIIlFjfYMq
                            hyCKeKheNnBnCFCVE5YD6dC81oa+AthgnhSjGGmsdVEt
                            Jg3uMeQXIluMmDtiT3Bu0q5ulvfanyr+H1rbqAnlvamG
                            SoVbaDgSbjbh40WMEYBssjlzC1etZM7XMcxTu3Y= )

;; Query time: 158 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Sat May 24 22:05:13 CEST 2014
;; MSG SIZE  rcvd: 1455

Um die DNSSEC-Vertrauenskette zu vervollständigen, muss nun über den eigenen DNS-Registrar (Domain-Bestell-Dienstleister) entweder der öffentliche Teil des KSK (bei einer .de-Zone) oder der 'Delegation Signer' (DS-Record) an die Elternzone übermittelt werden.

Sobald der DS-Record in der Elternzone auftaucht, ist die Vertrauenskette komplett und eine DNS-Abfrage mittels eines DNSSEC-Resolvers zeigt das AD-Flag (Authenticated Data – DNSSEC gesicherte DNS-Daten).

Der DS-Record wird aus dem Key Signing Key erstellt (hier der KSK mit dem Key Tag 40924):

% dnssec-dsfromkey /var/named/keys/Kexample.com.+008.+40924.key > dsset-example.com

Änderungen in einer dynamischen Zone

Resource Records können zu einer dynamischen Zone mit dem Werkzeug nsupdate hinzugefügt oder entfernt werden.

Hinzufügen des TLSA-Records per nsupdate:

% nsupdate -l
> ttl 3600
> update add _25._tcp.mail.example.com.  IN TLSA 3 0 1 8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1
> send
> quit

Löschen eines Records mit nsupdate:

% nsupdate -l
> ttl 3600
> update del doc.example.com. IN TXT
> send
> quit

Note

Dieses Kommando löscht alle TXT-Records mit dem DNS-Namen doc.example.com

Ändern eines Records per nsupdate:

% nsupdate -l
> ttl 3600
> update del www.example.com. IN A 192.0.2.80
> update add www.example.com. IN A 192.0.2.88
> send
> quit
Carsten Strotmann, 24. May 2014

   Bind    DNS    DNSSEC