Transitschutz: DNSSEC und DANE auf Linux-Servern konfigurieren

Die etablierte TLS-Verschlüsselung mit signierten Zertifikaten ist nicht wirklich sicher. Das modernere DANE prüft mittels DNSSEC ohne externen Stempel, ob das vom Server präsentierte Zertifikat echt und damit die verschlüsselte Verbindung beim Mail- und Webseiten-Transport vertrauenswürdig ist. Das lässt sich an einem Vormittag einrichten.

In Pocket speichern vorlesen Druckansicht 3 Kommentare lesen
Lesezeit: 13 Min.
Von
  • Carsten Strotmann
Inhaltsverzeichnis

TLS, Transport Layer Security, schützt Internetverbindungen per Verschlüsselung vorm Ausspähen. Aber seine Sicherheit hängt direkt von der externer Zertifizierer ab (CAs), die per digitaler Unterschrift für die Echtheit der verwendeten Schlüssel bürgen. Wenn eine solche Certification Authority gehackt wurde, muss man die von ihr unterschriebenen Zertifikate als kompromittiert betrachten und erneuern. Das ist inzwischen leider traurige Realität.

Glücklicherweise lässt sich diese fatale Abhängigkeit mit einem neuen Verfahren auflösen: DANE, DNS-based Authentication of Named Entities, sichert Zertifikate über das Domain Name System ab (DNS). Wie man das für den Mail-Transport nutzen kann beschreibt dieser Beitrag. Wer auf seinen Servern DANE und DNSSEC einsetzt, kann fürderhin selbst unterschriebene Zertifikate einsetzen. Mit der folgenden Anleitung bekommen Admins einen Leitfaden zur Installation auf Linux-Servern. Wer seine Dienste extern hostet, kann auf Anbieter wie dotplex zurückgreifen, die DANE bereits nutzen.

Bis die Mehrheit der Clients DANE beherrscht, muss man leider CA-signierte Zertifikate parallel einsetzen. Die folgenden Beispiele schildern deren Erzeugung und gehen davon aus, dass Sie mit Root-Rechten arbeiten.

Wie man Clients oder ganze Netze so einrichtet, dass sie die DANE-Infos nutzen, schildert der Beitrag Namen-Checker – DNSSEC für Clients und Client-Netze einrichten. Zunächst zum Server: Hier erstellen Sie als Erstes einen geheimen Schlüssel (Private Key) ohne Passwort für ein Zertifikat, das für den Web-Server (www.example.org) und den Mail-Server (mail.example.org) gelten soll:

cd /etc/ssl
openssl genrsa -out example.org.key 3248

Damit wird der RSA-Schlüssel 3248 Bit lang. Abhängig vom Zweck, der Arbeitslast der Server und vom Sicherheitsbedürfnis der Anwendung können Sie die Länge variieren. Dieses Best-Practice-Dokument von BetterCrypto gibt Hilfestellung.

Beim regelmäßigen Erneuern hilft eine für das Erstellen des Zertifikats angelegte Konfigurationsdatei enorm. Mit ihr erzeugen Sie die Signieranfrage:

openssl req -new -nodes -key example.org.key -config— example.org.conf -out example.org.csr

Die CSR-Datei (Certificate Signing Request) enthält den öffentlichen Schlüssel (Public Key). Schicken Sie nur diese Datei an die CA zur Unterschrift, aber keinesfalls den geheimen Schlüssel – dann wäre er ja nicht mehr geheim.

Ignorieren Sie grundsätzlich CA-Dienste, die Ihnen die angeblich „aufwendige Schlüsselerstellung“ abnehmen und Ihnen die Schlüssel zuschicken wollen. Denn dabei bekommt die CA Zugriff auf Ihren geheimen Schlüssel und kann damit prinzipiell allen Datenverkehr Ihrer Server dechiffrieren. Der Private Key ist also auch in diesem Fall alles andere als privat und folglich wertlos.

Von der CA kommt eine CRT-Datei mit der Unterschrift zurück. Verknüpfen Sie diese Datei mit Ihrem geheimen Schlüssel zur PEM-Datei, dem Zertifikat, das der Server verwendet:

cat example.org.key example.org.crt > example.org.pem
openssl gendh >> example.org.pem
chmod 400 example.org.*
chown www-data:wheel example.org.*

Der OpenSSL-Aufruf mit gendh erzeugt zufällige Diffie-Hellman-Parameter, damit der Server Perfect Forward Secrecy (PFS) nutzen kann. Die chmod- und chown-Aufrufe stellen sicher, dass nur die Nutzer www-data und root die Dateien lesen dürfen.

Beim Webserver NGINX tragen Sie den Pfad der Dateien im http-Abschnitt der Konfigurationsdatei und den Servernamen im darin stehenden server-Block ein:

http {
...
ssl_certificate /etc/ssl/example.org.pem;
ssl_certificate_key /etc/ssl/example.org.key;
...
server {
...
server_name www.example.org;
access_log logs/access_www.example.org.log;
...
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA';
...

Die oben stehende ssl_ciphers-Anweisung beschränkt die Chiffrieralgorithmen auf die aktuell als sicher angesehenen Methoden; unsichere sind mit einem vorangestellten "!" ausgeschlossen. Bei Apache 2.x tragen Sie die SSL-relevanten Parameter (erlaubte Chiffren, Pfade zu Zertifikat und Schlüssel) in die Datei /etc/apache2/default-vhost-ssl.conf ein.

Der häufig verwendete Mailverteiler Postfix benötigt neben den Zertifikatsdateien noch individuelle Zufallswerte für den Diffie-Hellman-Schlüsselaustausch (EDH, Ephemeral Diffie-Hellman key exchange), damit auch er PFS einsetzen kann:

openssl gendh -out /etc/ssl/dh_512.pem -2 512
openssl gendh -out /etc/ssl/dh_1024.pem -2 1024
Die TLS-relevanten Einträge stecken in der Konfigurationsdatei main.cf:
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/ssl/example.org.crt
smtpd_tls_key_file = /etc/ssl/example.org.key
...
smtpd_tls_dh1024_param_file = /etc/ssl/dh_1024.pem
smtpd_tls_dh512_param_file = /etc/ssl/dh_512.pem
smtpd_tls_eecdh_grade = strong
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_mandatory_ciphers=high
tls_ssl_options = NO_COMPRESSION
tls_preempt_cipherlist = yes

tls_high_cipherlist=EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA

Auch hier sind schwache Chiffren per "!" ausgeschlossen. Ferner ist TLS-Komprimierung deaktiviert, weil sie angreifbar ist.

Damit ein Client das Zertifikat eines Servers per DANE prüfen kannˇ[2], braucht er als Fingerabdruck den SHA256-Hash des Zertifikats. Diesen Hash bekommt er von seinem DNS-Resolver, der ihn aus dem vom Upstream-DNS-Server gelieferten TLSA-Record holt. Den TLSA-Record holt sich der Client mit einer DNS-Anfrage wie _25._tcp.mail.example.org. Dabei wird dem Servernamen die Portnummer 25 für SMTP und das Transportprotokoll (TCP) vorangestellt.

Neuere DNS-Server können bereits mit dem TLSA-Record umgehen. Bei vielen älteren Servern können Sie ihn in der Standard-Notation für unbekannte DNS-Records eintragen (RFC 3597). Windows Server 2012(R2) nutzt den TLSA-Record leider noch nicht. Den SHA256-Hash erzeugen Sie aus dem unterschriebenen Zertifikat:

openssl x509 -in /etc/ssl/example.org.crt -outform DER | openssl sha256

Die Ausgabe des Befehls sieht beispielsweise so aus:

(stdin)= 8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1

Der TLSA-Record enthält drei Flags, die seine Verwendung kennzeichnen. Das erste, die TLSA Certificate Usage, bekommt den Wert 3, der ein dediziertes Server-Zertifikat beschreibt (DANE-EE Domain-issued certificate). Der folgende Selector 0 kennzeichnet ein komplettes Zertifikat, im Unterschied zu einer "SubjectPublicKeyInfo"-Datenstruktur. Der Matching Type 1 zeigt an, dass die folgenden Daten der SHA256-Fingerabdruck des Zertifikats sind. 0 steht für das komplette Zertifikat, 2 für einen SHA512-Hash. Damit sieht der in die DNS-Zone für example.org einzutragende TLSA-Record so aus:

_25._tcp.mail.example.org. IN TLSA 3 0 1 ( 8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1 )

Entsprechend gehen Sie für den Webserver vor. Arbeitserleichterung bieten ein Online-Generator oder die Tools hash-slinger und ldns-dane. Letzteres lässt sich besonders einfach nutzen. Es holt das Zertifikat direkt vom Server und erzeugt den TLSA-Record:

ldns-dane create www.example.org 443

Der Befehl liefert eine Ausgabe wie diese:

_443._tcp.www.example.org. 3600 IN TLSA 3 0 18cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1

Das Online-Tool auf dnsviz.net klappert die DNSSEC-Schlüsselkette für eine Site von „.“ kommend ab. Ein Klick auf den Key zeigt unter anderem seine Gültigkeit, Länge und Algorithmus.

Der TLS-Schutz per DANE funktioniert nur dann sicher, wenn DNS-Server und -Resolver auch DNSSEC benutzen. Sonst könnte ein Angreifer falsche TLSA-Hashes injizieren. Zum DNSSEC-Ertüchtigen von Resolvern liefert der Artikel Namen-Checker – DNSSEC für Clients und Client-Netze einrichten Hinweise.

Die meisten DNS-Server beherrschen inzwischen DNSSEC. Das folgende Beispiel einer DNSSEC-Signierung gilt für BIND 9.9.0, hernach kurz BIND. Alternativen sind etwa NSD, PowerDNS, Knot, Yadifa und Bundy. Um die Verwaltung von DNSSEC-Schlüsseln und den periodischen Schlüsseltausch (Key-Rollover) kann sich OpenDNSSEC kümmern.

DNSSEC erzwingt, dass autoritative DNS-Server (DNS-Zonen) und DNS-Resolver (Dienste zur Namensauflösung für Clients) auf getrennten Systemen laufen: Ein autoritativer Server kann nicht seine eigenen DNS-Daten per DNSSEC prüfen. Bei autoritativen Antworten ist nämlich in der Antwort das AA-Flag gesetzt (AA = autoritative Antwort), bei DNSSEC-validierten DNS-Antworten jedoch das AD-Flag (AD = authentisierte Daten). Die Flags schließen sich aber gegenseitig aus.

Stellen Sie zunächst mit Zonecheck, DNSCheck oder Zonemaster sicher, dass Ihre DNS-Zone fehlerfrei ist. Sonst kann die DNSSEC-Signierung oder -Validierung fehlschlagen, auch wenn die Zone bisher funktioniert hat.

In BIND 9.7 und 9.8 muss DNSSEC explizit eingeschaltet werden. Gute Praxis ist, auch bei neueren Versionen in der Konfigurationsdatei DNSSEC einzuschalten, sodass beim Blick in die Datei klar wird, dass die Funktion aktiv ist. Da Ihr DNS-Server für seine Zone autoritativ ist, schalten Sie im options-Block von /etc/named.conf den Resolver durch Einfügen einer Zeile aus:

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

Die DNSSEC-Schlüssel liegen typischerweise im Ordner /var/named/keys, den BIND alle 60 Minuten nach gültigen DNSSEC-Schlüsseln für die gehosteten Zonen durchsucht. Der Server signiert automatisch jede Zone mit allen passenden Schlüsseln. Außer bei einem Key-Rollover darf dort immer nur ein gültiges Schlüsselpaar pro Domain liegen (KSK und ZSK, siehe unten). Sonst wird die Zone mit mehreren Schlüsseln signiert, was zu sehr großen DNS-Antworten führt und DDoS-Angriffe ermöglicht. Bei BIND ist die Gültigkeitsfrist auf 30 Tage voreingestellt, sodass die Signaturen im selben Rhythmus erneuert werden müssen – was BIND auf Wunsch selbst erledigt (siehe unten).

Änderungen an der DNS-Zone müssen dagegen direkt bei der Publizierung signiert werden. Dafür bietet BIND zwei Methoden an: Dynamische Zonen und Inline-Signing. Dynamische Zonen müssen mit DNS-Updates nach RFC 2136, also etwa mit dem Tool nsupdate, geändert werden. Eine Anleitung für DANE mit dynamischen Zonen finden Sie hier.

Zonen mit Server-Adressen sind meistens statisch, sodass Sie sie wie gewohnt per Editor pflegen können. Das Signieren erledigt BIND, sobald es die Datei(en) erneut einliest. Das ist jedoch nur bei statischen Zonen erlaubt. Die Funktion aktivieren Sie durch Einfügen einer Zeile in der Zonendefinition in named.conf:

zone "example.org" IN {
type master;
file "masters/example.org";
# automatische DNSSEC-Verwaltung anschalten
auto-dnssec maintain;
# Inline-Signing aktivieren
inline-signing yes;
...

Die zusätzlich eingefügte Zeile mit auto-dnssec maintain schaltet das automatische Aktualisieren der Signaturen ein, sodass Sie das nicht selbst alle 30 Tage erledigen müssen.

Nun prüfen Sie mit dem Befehl named-checkconf -z, ob Konfigurations- und Zonendateien fehlerfrei sind. Das Tool meldet Probleme mit Zeilennummer und Grund, was die Fehlerbeseitigung erleichtert. Stimmt alles, lassen Sie BIND per rndc reload seine Konfiguration neu laden.

Pro Zone braucht BIND einen Zone-Signing-Key (ZSK) und einen Key-Signing-Key (KSK), die üblicherweise unter /var/named/keys liegen:

dnssec-keygen -a RSASHA256 -b 2048 -K— /var/named/keys -n ZONE example.org
dnssec-keygen -a RSASHA256 -b 2560 -f KSK -K— /var/named/keys -n ZONE example.org
chown bind:wheel K*.private
chmod u=r,go= K*.private

Mittels chown und chmod stellen Sie sicher, dass BIND die Dateien lesen darf. Abhängig von Ihrem Server-Betriebssystem müssen Sie eventuell als User named anstatt bind einsetzen.

Sobald die Schlüssel erzeugt sind, signiert BIND die Zone nach spätestens 60 Minuten. Wer nicht warten möchte, stößt das manuell mit rndc sign example.org an. Danach sollte der Aufruf von dig @localhost dnskey example.org +dnssec +multi zeigen, dass die DNSKEY-Records publiziert und Signaturen sowie RRSIG-Records vorhanden sind. Die längliche dig-Ausgabe ersparen wir Ihnen an dieser Stelle.

Um die Vertrauenskette zu vervollständigen, müssen Sie bei einer .de-Zone über Ihren DNS-Registrar (Domain-Dienstleister) den öffentlichen Teil des KSK an die Elternzone übermitteln. Bei anderen Zonen nehmen Sie den Delegation-Signer-Record (DS).

Der öffentliche KSK mit der Endung .key liegt im Ordner /var/named/keys; sein Gegenstück mit der Endung .private bleibt unangetastet. Den DS-Record erstellen Sie aus dem öffentlichen Key-Signing-Key mit:

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

Sobald der Registrar Ihren öffentlichen KSK oder den DS-Record in der Elternzone publiziert hat, ist die Vertrauenskette komplett und eine DNS-Abfrage mittels eines DNSSEC-Resolvers zeigt das AD-Flag. Damit sind die Arbeiten auf der Server-Seite für DANE und DNSSEC abgeschlossen. (dz)