Es gibt inzwischen viele Webtools die TLSA-Records prüfen. Aber wer es einmal von Hand gemacht hat, versteht was dabei passiert. Der Ablauf ist immer gleich: Zertifikat vom Server holen, Hash berechnen, mit dem DNS-Record vergleichen.
Zertifikat holen
Verbindung zum Mailserver aufbauen und das Zertifikat per STARTTLS abholen:
Welchen Hash man berechnen muss, hängt vom TLSA-Record ab. Die drei Felder im Record bestimmen das:
Usage
0 = CA, 1 = End-Entity (Kette muss gültig sein), 2 = Trust Anchor, 3 = End-Entity (keine Kettenprüfung)
Selector
0 = ganzes Zertifikat, 1 = nur Public Key (SPKI)
Matching Type
0 = exakter Vergleich, 1 = SHA-256, 2 = SHA-512
Am häufigsten sieht man 3 1 1 (End-Entity, nur Public Key, SHA-256) oder 3 0 1 (End-Entity, ganzes Zertifikat, SHA-256). Zuerst den TLSA-Record aus dem DNS holen um zu sehen was erwartet wird:
dig _25._tcp.smtp.kernel-error.de TLSA +short
Dann den passenden Hash berechnen. Bei Selector 0 (ganzes Zertifikat) und Matching Type 1 (SHA-256):
In der Ausgabe steht am Ende entweder Verified TLS connection established (DANE-Prüfung bestanden) oder eine Fehlermeldung mit dem konkreten Problem. Das Tool löst die MX-Records auf, holt den TLSA-Record, baut die TLS-Verbindung auf und vergleicht alles automatisch.
Veraltet: Das DNSSEC Validator Browser-Plugin wird nicht mehr gepflegt und ist in aktuellen Firefox-/Chrome-Versionen nicht mehr verfügbar. DNSSEC-Validierung sollte auf dem DNS-Resolver stattfinden, nicht im Browser.
Na schau mal einer an… Das Browser Plugin für den DNSSEC Validator kann nun auch DANE / TLSA und er zeigt es angenehm übersichtlich an.
Perfect Forward Secrecy (PFS) sorgt dafür, dass jede TLS-Verbindung einen eigenen temporären Schlüssel verwendet. Selbst wenn jemand den privaten Schlüssel des Servers in die Hände bekommt, kann er damit früher aufgezeichnete Verbindungen nicht entschlüsseln. Für E-Mail ist das besonders relevant, weil Mailverkehr gern auf Vorrat mitgeschnitten wird.
PFS bekommt man durch ECDHE- oder DHE-Schlüsselaustausch. Moderne OpenSSL-Versionen und aktuelle Postfix/Dovecot-Releases machen das Richtige von Haus aus. Trotzdem lohnt sich ein Blick auf die Konfiguration, um sicherzustellen, dass keine veralteten Protokolle oder Cipher-Suiten aktiv sind.
Postfix
Die relevanten Einstellungen in der main.cf:
# Eingehend (smtpd)
smtpd_tls_security_level = may
smtpd_tls_protocols = >=TLSv1.2
smtpd_tls_mandatory_protocols = >=TLSv1.2
smtpd_tls_mandatory_ciphers = medium
# Ausgehend (smtp)
smtp_tls_security_level = dane
smtp_tls_protocols = >=TLSv1.2
smtp_tls_mandatory_protocols = >=TLSv1.2
smtp_tls_mandatory_ciphers = medium
# Cipher-Präferenz beim Server
tls_preempt_cipherlist = yes
>=TLSv1.2 schaltet TLS 1.0 und 1.1 ab. tls_preempt_cipherlist = yes lässt den Server die Cipher-Reihenfolge bestimmen, nicht den Client. Postfix sortiert AEAD-Ciphers (GCM, CHACHA20) automatisch nach vorn, PFS-Ciphers haben Vorrang. Die medium-Stufe schließt alles unterhalb von 128-Bit-Verschlüsselung aus.
Für den ausgehenden Versand ist smtp_tls_security_level = dane die beste Wahl. Damit prüft Postfix TLSA-Records per DANE. Gibt es keinen TLSA-Record, fällt Postfix auf opportunistisches TLS zurück. Wer zusätzlich MTA-STS auswertet, deckt auch Server ohne DNSSEC ab.
Dovecot
In /usr/local/etc/dovecot/conf.d/10-ssl.conf (FreeBSD) bzw. /etc/dovecot/conf.d/10-ssl.conf (Linux):
ssl = required erzwingt TLS für alle Verbindungen. ssl_min_protocol = TLSv1.2 schließt alte Protokolle aus. ssl_prefer_server_ciphers = yes gibt dem Server die Kontrolle über die Cipher-Wahl. no_ticket deaktiviert TLS Session Tickets, die PFS untergraben können wenn der Ticket-Key kompromittiert wird.
Eine explizite Cipher-Liste ist bei aktuellem OpenSSL nicht nötig. Die Defaults bevorzugen ECDHE mit AEAD. Wer es trotzdem einschränken will:
ssl_cipher_list gilt für TLS 1.2, ssl_cipher_suites für TLS 1.3. Bei TLS 1.3 ist PFS immer aktiv, da gibt es keine Cipher-Suiten ohne Schlüsselaustausch mehr.
Testen
# Postfix (STARTTLS auf Port 25)
openssl s_client -starttls smtp -connect smtp.kernel-error.de:25 2>/dev/null | grep -E "Protocol|Cipher|Server Temp Key"
# Postfix (Implicit TLS auf Port 465)
openssl s_client -connect smtp.kernel-error.de:465 2>/dev/null | grep -E "Protocol|Cipher|Server Temp Key"
# Dovecot (STARTTLS auf Port 143)
openssl s_client -starttls imap -connect imap.kernel-error.de:143 2>/dev/null | grep -E "Protocol|Cipher|Server Temp Key"
# Dovecot (Implicit TLS auf Port 993)
openssl s_client -connect imap.kernel-error.de:993 2>/dev/null | grep -E "Protocol|Cipher|Server Temp Key"
Entscheidend ist die Zeile Server Temp Key. Steht dort X25519, ECDH P-256 oder DH 2048, ist PFS aktiv. Mit OpenSSL 3.5+ und entsprechender Konfiguration sieht man dort auch X25519MLKEM768 für Post-Quantum-Schlüsselaustausch.
Meine Domains sind schon lange per DNSSEC gesichert. Für den Webserver hatte ich auch schnell TLSA-Records veröffentlicht, damit die TLS-Verbindung per DANE abgesichert ist. Seit Postfix 2.11 beherrscht auch der MTA die Prüfung von TLSA-Records — damit lässt sich ausgehende E-Mail-Verschlüsselung kryptographisch verifizieren, ohne sich auf das CA-System verlassen zu müssen.
Postfix konfigurieren
Zwei Zeilen in der main.cf reichen, damit Postfix beim Versand TLSA-Records prüft:
smtp_dns_support_level = dnssec weist den SMTP-Client an, DNSSEC-validierte DNS-Antworten zu verlangen. smtp_tls_security_level = dane aktiviert die TLSA-Prüfung — Postfix sucht automatisch nach TLSA-Records für den Zielserver. Gibt es keinen TLSA-Record oder kein DNSSEC, fällt Postfix auf opportunistisches TLS zurück. Die Kommunikation mit Servern ohne DANE leidet also nicht. Details stehen in der Postfix DANE-Dokumentation.
TLSA-Record erstellen
Der TLSA-Record enthält einen Hash des TLS-Zertifikats (oder des Public Keys), den der Empfänger-Mailserver im DNS veröffentlicht. So erzeugt man den SHA-256-Hash des Public Keys aus dem Zertifikat:
Den Hash trägt man als TLSA-Record in die DNS-Zone ein — für Port 25 (SMTP) und optional Port 465 (Implicit TLS):
_25._tcp.smtp.kernel-error.de. 3600 IN TLSA 3 1 1 8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1
_465._tcp.smtp.kernel-error.de. 3600 IN TLSA 3 1 1 8cb0fc6c527506a053f4f14c8464bebbd6dede2738d11468dd953d7d6a3021f1
Die Felder 3 1 1 bedeuten: DANE-EE (End Entity, kein CA-Vertrauen nötig), SPKI (nur Public Key, nicht das ganze Zertifikat), SHA-256. Der TTL von 3600 Sekunden ist bewusst kurz — bei einem Zertifikatswechsel soll der alte Record schnell ablaufen. Mehr zum Aufbau von TLSA-Records steht in RFC 7672.
Testen
Mit posttls-finger (Teil von Postfix) lässt sich prüfen, ob die DANE-Verifikation funktioniert:
Verified TLS connection established to smtp.kernel-error.de[...]:25:
TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)
Verified statt Untrusted — der TLSA-Record stimmt mit dem Zertifikat überein, die Verbindung ist DANE-verifiziert. Im Postfix-Log sieht man denselben Unterschied:
smtp[3779]: Verified TLS connection established to mx02.example.de[...]:25
smtp[3779]: Untrusted TLS connection established to smtp2.example.de[...]:25
Verified = DANE-geprüft und in Ordnung. Untrusted = TLS aktiv, aber kein gültiger TLSA-Record vorhanden — die Verschlüsselung funktioniert trotzdem, nur ohne kryptographische Verifikation des Zertifikats.
Warum DANE besser ist als das CA-System
DANE verankert das Vertrauen im DNS statt bei Certificate Authorities. Der Domaininhaber veröffentlicht den Hash seines Zertifikats selbst — DNSSEC schützt den Record vor Manipulation. Keine CA kann ein falsches Zertifikat für die Domain ausstellen und damit die Verbindung aufbrechen. Das Ganze kostet nichts außer einem DNS-Record und funktioniert für jeden, der DNSSEC betreibt.
Zum Vergleich: Das damalige „E-Mail made in Germany“ (EmiG) setzte auf eine TÜV-Zertifizierung, die sich nur große Provider leisten konnten. Sicherheit nur für Unternehmen mit Budget — das ist das Gegenteil von dem, was ich unterstütze.
Es gibt viele gute Gründe warum man die Version seines DNS Servers unkenntlich machen sollte. Viele Roboter und noch mehr Scriptkiddies suchen nach Versionen mit Sicherheitslöchern. Natürlich sollte man seine Version immer auf dem aktuellen Stand der Sicherheitsupdates halten… Denn noch kommt es vor dass man auch mal ein paar Tage auf einer „kaputten“ Version läuft. Dieses muss man ja nicht jedem unter die Nase reiben, hm?
Beim Bind ist es extrem einfach. Man reißt einfach mit dem Editor seiner Wahl die named.conf auf und wandert zum Options-Bereich. Dort ergänst man einfach die Option version:
options
{
[Zeugs und andere Optionen]
version "unknown";
[noch mehr Zeugs und andere Optionen]
};
Nun einfach Bind seine Konfiguration neu laden lassen:
$ rndc reconfig
Schon wird keine Version mehr angezeigt. Testen kann man alles wie immer mit dig:
Bock auf ein kleines Spiel? Wer mir zuerst sagt auf welchem Schiff mein primärer DNS Server stehen müsste, der bekommt eine Dose Dr Pepper Cola geschenkt.
Update 26.11.2013 19:53
Glückwunsch Dome, du bekommst die Dose. Bekomme ich ein Foto wie alles ausschaut nachdem DHL das Paket (oder besser Maxibrief *grübel*) bei dir abgegeben hat? Ich löse aber mal nicht, dann können die anderen noch mitspielen!
Meine Domain ist per DNSSEC gesichert, der Webserver bietet TLS an. Mit DANE (DNS-based Authentication of Named Entities) lässt sich beides verbinden: Die Checksumme des TLS-Zertifikats wird als TLSA-Record im DNS veröffentlicht — DNSSEC schützt diesen Record vor Manipulation.
Warum DANE?
Das klassische CA-System hat ein grundsätzliches Problem: Jede der hunderten Certificate Authorities kann ein Zertifikat für jede Domain ausstellen. Wird eine CA kompromittiert oder handelt fahrlässig, können gefälschte Zertifikate im Umlauf sein — der Browser merkt nichts. DANE löst das, indem der Domaininhaber selbst festlegt, welches Zertifikat gültig ist. Der Hash steht im DNS, DNSSEC garantiert die Integrität. Keine CA kann das unterlaufen.
Unterstützt ein Client DANE, prüft er beim TLS-Handshake, ob der TLSA-Record zum angebotenen Zertifikat passt. Das funktioniert auch mit selbstsignierten Zertifikaten — solange der Hash stimmt und DNSSEC aktiv ist, wird dem Zertifikat vertraut. Die Spezifikation steht in RFC 6698.
TLSA-Record erstellen
Der TLSA-Record enthält einen Hash des Public Keys (SPKI) aus dem Zertifikat. Mit OpenSSL erzeugt:
Den Hash trägt man als TLSA-Record in die DNS-Zone ein. Für den Webserver (Port 443):
_443._tcp.www.kernel-error.de. 3600 IN TLSA 3 1 1 a321...f7
Die drei Zahlen 3 1 1 bedeuten:
3 — DANE-EE (End Entity): Das Zertifikat wird direkt geprüft, kein CA-Vertrauen nötig
1 — SPKI (Subject Public Key Info): Nur der Public Key wird gehasht, nicht das ganze Zertifikat. Vorteil: Bei Erneuerung mit demselben Key bleibt der TLSA-Record gültig
1 — SHA-256 als Hash-Algorithmus
Der TTL von 3600 Sekunden ist bewusst kurz gewählt — bei einem Zertifikatswechsel mit neuem Key soll der alte Record schnell ablaufen.
Ob der Record auch zum tatsächlich ausgelieferten Zertifikat passt, prüft man mit OpenSSL — Hash vom Server-Zertifikat erzeugen und mit dem DNS-Record vergleichen:
Stimmen die Hashes überein, ist alles korrekt. Komfortabler geht es mit posttls-finger (Teil von Postfix) — das Tool prüft TLSA-Record und Zertifikat in einem Schritt.
DANE für E-Mail
DANE funktioniert nicht nur für Webserver. Für E-Mail ist es sogar wichtiger — SMTP hat kein Vertrauensmodell wie Browser, opportunistisches TLS kann trivial per Downgrade-Angriff ausgehebelt werden. Mit DANE und TLSA-Records auf Port 25 wird die Verschlüsselung kryptographisch verifizierbar. Wie man das mit Postfix einrichtet, steht im Beitrag Postfix mit DANE und DNSSEC absichern. Zur Visualisierung des DANE-Anteils im Mailverkehr habe ich damals Mailgraph um DANE-Graphen erweitert.
Wie gewohnt habe ich dann den TXT-RECORD in mein Zonenfile gekippt. Beim signieren der Zone per DNSsec sprang mich aber folgende Fehlermeldung an:
dnssec-signzone: error: dns_rdata_fromtext: kernel-error.de:25: ran out of space
Na nu? Ach so… ja klar! Der TXT-RECORD ist zu lang. Da gibt es ja eine Beschränkung…. Fast vergessen! Mehr als 255 Zeichen sind ja nicht zulässig. Ich musste den DKIM TXT-RECORD also in ein multi-line TXT-RECORD umwandeln. Nicht weiter kompliziert, einfach Klammer auf, Klammer zu und alles brav mit Anführungszeichen trennen. Damit sieht mein Zoneneintrag nun wie folgt aus:
----------------------------------------------------------
DKIM check details:
----------------------------------------------------------
Result: pass (matches From: kernel-error@kernel-error.com)
ID(s) verified: header.d=kernel-error.com
Canonicalized Headers:
To:'20'<check-auth@verifier.port25.com>;'0D''0A'
Subject:'20'check-auth@verifier.port25.com'0D''0A'
MIME-Version:'20'1.0'0D''0A'
Content-Type:'20'text/plain;'20'charset=UTF-8;'0D''0A'
'20'format=flowed'0D''0A'
Content-Transfer-Encoding:'20'7bit'0D''0A'
Date:'20'Fri,'20'09'20'Nov'20'2012'20'11:33:48'20'+0100'0D''0A'
From:'20'Sebastian'20'van'20'de'20'Meer'20'<kernel-error@kernel-error.com>;'0D''0A'
Message-ID:'20'<c580aed4c89d48c1a93fea35ee80fe30@vandemeer.de>;'0D''0A'
DKIM-Signature:'20'v=1;'20'a=rsa-sha256;'20'c=simple/simple;'20'd=kernel-error.com;'0D''0A'
'09's=kernel-error.com;'20't=1352457228;'0D''0A'
'09'bh=v55t4Oe0VsnE3Xa3exogjgnS10dkjG1rhPQxGz4STJo=;'0D''0A'
'09'h=To:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:'0D''0A'
'09''20'Date:From:Message-ID;'0D''0A'
'09'b=
Canonicalized Body:
check-auth@verifier.port25.com'0D''0A'
DNS record(s):
kernel-error.com._domainkey.kernel-error.com. 300 IN TXT "v=DKIM1; g=*; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlhidIl+KZgelAOOVYiGHi+uGxEnpjmhXH2IVZNpH69ZsWYTYd1OgXIvWQnAiQ4rRCyvbjcrKaFnXJUpda9eGJeqlr3hE4YhOPLS34K86+8Gr17+WOofkdc3STmlqAI60r1+bQQh8rCWb1YPXIssinq3ll8GVDwAEmh3Bm8zSWz2Ntc+W/maURTlZbMGaRoi+lwhBzr+DnNYL+mPs3UVQoE9ei2Z/bjNQzdpzWeriFgfk56muVZNTvmn8LxkugMhoHMohCr/vkr99xTVmIeMFwMerB2B/JOpeADIf4Wsz6OJQR3GaBA91MX9T2nFncvW3pL03O4wYYVCGnFqz8gbcQIDAQAB"
NOTE: DKIM checking has been performed based on the latest DKIM specs
(RFC 4871 or draft-ietf-dkim-base-10) and verification may fail for
older versions. If you are using Port25's PowerMTA, you need to use
version 3.2r11 or later to get a compatible version of DKIM.
Dass mein DNS-Server DNSsec http://www.kernel-error.de/dnssec beherscht und so meine Zonen schützt, das wissen ja fast alle. Wie man damit nun seinen GPG Schlüssel verteilen kann und/oder die SSH-Fingerprints einzelner Hosts gegen den DNS Server validieren lassen kann…. Dieses findet sich nun hier:
OpenSSH kann die Fingerprints seiner Host Keys als SSHFP-Records im DNS veröffentlichen. Beim Verbindungsaufbau prüft der Client dann automatisch, ob der Fingerprint des Servers mit dem DNS-Eintrag übereinstimmt — ein wirksamer Schutz gegen Man-in-the-Middle-Angriffe. Ist die Zone zusätzlich per DNSSEC gesichert, kann der DNS-Record selbst nicht gefälscht werden. Die Spezifikation steht in RFC 4255.
Client konfigurieren
Damit OpenSSH beim Verbindungsaufbau SSHFP-Records prüft, muss VerifyHostKeyDNS aktiviert werden. Global für alle Benutzer in /etc/ssh/ssh_config:
VerifyHostKeyDNS yes
Oder nur für die aktuelle Sitzung:
ssh -o "VerifyHostKeyDNS=yes" server.example.de
SSHFP-Records erzeugen
Am einfachsten direkt auf dem Server mit ssh-keygen — das erzeugt die fertigen DNS-Records für alle vorhandenen Host Keys:
ssh-keygen -r server.example.de.
Ausgabe (Beispiel mit RSA, ECDSA und Ed25519):
server.example.de. IN SSHFP 1 1 47890eecc9a2893061734b07b8f60caa1a856148
server.example.de. IN SSHFP 1 2 b2518ad49cc2adf517d3f6a9faaf4017abc2c3e3...
server.example.de. IN SSHFP 3 1 3dd9de0dcf1523341b45a53f1d57043609e26c62
server.example.de. IN SSHFP 3 2 e1c76bd66b5a0641789b0b37be5b80ae3f6395c1...
server.example.de. IN SSHFP 4 1 a1b2c3d4e5f6...
server.example.de. IN SSHFP 4 2 d4e5f6a7b8c9...
Aufbau des SSHFP-Records
Ein SSHFP-Record besteht aus zwei Zahlen und dem Fingerprint:
hostname IN SSHFP [Algorithmus] [Hash-Typ] [Fingerprint]
Algorithmus:
1 — RSA
3 — ECDSA
4 — Ed25519 (empfohlen, ab OpenSSH 6.7)
DSS (2) ist seit OpenSSH 7.0 standardmäßig deaktiviert und sollte nicht mehr verwendet werden.
Hash-Typ: 1 = SHA-1, 2 = SHA-256. Beide sollten veröffentlicht werden — ältere Clients verstehen nur SHA-1, neuere bevorzugen SHA-256.
Prüfen
Mit dig lässt sich prüfen, ob die Records im DNS angekommen sind:
DNS lookup error: data does not exist
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)?
Mit SSHFP-Records und DNSSEC:
debug1: found 4 secure fingerprints in DNS
debug1: matching host key fingerprint found in DNS
secure bedeutet: Die DNS-Antwort wurde per DNSSEC validiert. Ohne DNSSEC steht dort insecure — der Fingerprint wurde zwar gefunden, aber der DNS-Antwort selbst kann nicht vertraut werden. Für echte Sicherheit braucht man beides: SSHFP-Records und DNSSEC.
Strenge Prüfung erzwingen
Optional: OpenSSH anweisen, die Verbindung nur aufzubauen, wenn der Host Key erfolgreich validiert wurde:
Damit wird die Verbindung abgelehnt, wenn kein passender SSHFP-Record gefunden wird oder die DNSSEC-Validierung fehlschlägt. Das ist die sicherste Einstellung — setzt aber voraus, dass alle Zielserver SSHFP-Records haben.
Kleiner Aufwand, viel mehr Sicherheit. Fragen? Einfach melden.
DNSSEC (Domain Name System Security Extensions) schützt DNS-Antworten vor Fälschung. Ein anfragender Resolver kann damit prüfen, ob die gelieferten Zonendaten tatsächlich vom autorisierten Nameserver stammen und unterwegs nicht verändert wurden. DNSSEC wurde als Mittel gegen Cache Poisoning entwickelt — Serverauthentifizierung findet nicht statt.
Die Vertrauenskette
Was mich beim ersten Lesen zu DNSSEC durcheinandergebracht hat, war das Umherwerfen mit Begriffen: KSK, ZSK, DNSKEY, RRSIG, DS. Im Grunde ist es einfach:
Der KSK (Key Signing Key) hat eine Aufgabe: den ZSK unterschreiben. Der KSK wird als DS-Record in der übergeordneten Zone hinterlegt. Der ZSK (Zone Signing Key) hat auch nur eine Aufgabe: die eigentlichen Zonendaten unterschreiben.
Es beginnt bei der Root-Zone. Die Root-Server wissen, welche Nameserver für die TLDs zuständig sind. Die TLD-Server wissen, welche Nameserver für die einzelnen Domains zuständig sind. Jede Ebene signiert ihre Zone und veröffentlicht den DS-Record der Ebene darunter. So entsteht eine durchgehende Kette vom Root-KSK bis zu meiner Zone.
Will ein Angreifer dafür sorgen, dass www.kernel-error.org auf seinen Server zeigt, hat er zwei Möglichkeiten:
Er antwortet auf die Delegation-Anfrage mit seinem eigenen Nameserver.
Er antwortet mit gefälschter Absenderadresse schneller als der echte Server.
Mit DNSSEC kann der Resolver beide Angriffe erkennen — die gefälschte Antwort hat keine gültige Signatur.
DNSSEC in BIND aktivieren
Auf dem autoritativen Nameserver muss DNSSEC-Validierung aktiv sein. In modernen BIND-Versionen (ab 9.16) reicht im options-Block:
options {
dnssec-validation auto;
};
auto bedeutet, dass BIND den eingebauten Root-Trust-Anchor nutzt und diesen bei KSK-Rollovers automatisch aktualisiert (RFC 5011). Der alte dnssec-enable yes wurde in BIND 9.18 entfernt — DNSSEC ist seitdem immer aktiv.
Zone signieren — der moderne Weg
Seit BIND 9.16 gibt es dnssec-policy. Damit übernimmt BIND die Schlüsselerzeugung, das Signieren und den Key-Rollover vollautomatisch:
zone "kernel-error.org" {
type primary;
file "kernel-error.org";
dnssec-policy default;
inline-signing yes;
};
Die default-Policy verwendet ECDSAP256SHA256 (Algorithmus 13) — schneller und sicherer als das früher übliche NSEC3RSASHA1 mit 4096-Bit-Schlüsseln. inline-signing yes bedeutet: BIND signiert die Zone im Speicher, die Zonendatei auf der Platte bleibt unsigniert und lässt sich wie gewohnt bearbeiten.
Zone manuell signieren
Wer mehr Kontrolle will oder eine ältere BIND-Version hat, kann die Schlüssel von Hand erzeugen. KSK erstellen:
$ dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE kernel-error.org
Kkernel-error.org.+013+12345
ZSK erstellen:
$ dnssec-keygen -a ECDSAP256SHA256 -n ZONE kernel-error.org
Kkernel-error.org.+013+67890
Die öffentlichen Teile (*.key) in die Zonendatei einbinden und signieren:
$ cat Kkernel-error.org.+013+*.key >> kernel-error.org
$ dnssec-signzone -S -K /pfad/zu/keys -o kernel-error.org kernel-error.org
Verifying the zone using the following algorithms: ECDSAP256SHA256.
Zone signing complete:
Algorithm: ECDSAP256SHA256: ZSKs: 1, KSKs: 1 active, 0 stand-by
kernel-error.org.signed
Dann BIND anweisen, die signierte Zonendatei zu laden. Nach jeder Änderung an der Zone muss neu signiert werden — oder man nutzt inline-signing, dann entfällt das.
DS-Record beim Registrar einreichen
Der öffentliche KSK muss als DS-Record in der übergeordneten Zone landen. Bei der DENIC (.de) und den meisten TLD-Registries gibt es dafür ein Webinterface beim Registrar. Man schickt den öffentlichen KSK hin, der Registrar erstellt daraus einen DS-Record und veröffentlicht ihn neben den NS-Records.
Ob der DS-Record gesetzt ist, lässt sich prüfen, indem man die TLD-Nameserver direkt fragt:
DNSSEC-Signaturen machen DNS-Antworten deutlich größer als die 512 Bytes, die klassisches DNS über UDP erlaubt. EDNS (RFC 6891) hebt dieses Limit auf. Das ist seit 1999 spezifiziert, aber manche Firewalls und Billig-Router haben damit immer noch Probleme — sie filtern große UDP-Pakete oder EDNS-Optionen.
Wichtig: Gehen die Schlüssel verloren oder die signierte Zonendatei brennt ab, hat man ein Problem. Vor jeder großen Änderung (Key-Rollover, Algorithmus-Wechsel) immer die längste TTL der Zone abwarten. Sonst sind gecachte Antworten mit der alten Signatur noch gültig, während die neue Signatur schon aktiv ist — die Zone wird temporär nicht validierbar.
Meinen „analogen“ DNSSEC-Masterplan dazu habe ich mir damals aufgezeichnet:
Was man auf DNSSEC aufbauen kann
Wenn die Zone signiert ist, lassen sich darüber weitere Sicherheitsmechanismen verteilen:
DANE/TLSA — TLS-Zertifikate per DNS verifizieren, unabhängig von CAs.