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

Schlagwort: DNSSEC (Seite 3 von 3)

TLSA- und DANE-Records manuell prüfen: Schritt für Schritt mit OpenSSL

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:

openssl s_client -starttls smtp -connect smtp.kernel-error.de:25 \
  -servername smtp.kernel-error.de 2>/dev/null | \
  openssl x509 -outform PEM > /tmp/server.crt

Das Zertifikat liegt jetzt in /tmp/server.crt.

Hash berechnen

Welchen Hash man berechnen muss, hängt vom TLSA-Record ab. Die drei Felder im Record bestimmen das:

Usage0 = CA, 1 = End-Entity (Kette muss gültig sein), 2 = Trust Anchor, 3 = End-Entity (keine Kettenprüfung)
Selector0 = ganzes Zertifikat, 1 = nur Public Key (SPKI)
Matching Type0 = 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):

# Selector 0 (Full Certificate), SHA-256
openssl x509 -in /tmp/server.crt -outform DER | openssl sha256
# Ausgabe: SHA2-256(stdin)= 94c8e1bd...

Bei Selector 1 (nur SPKI, Public Key) und SHA-256:

# Selector 1 (SPKI), SHA-256
openssl x509 -in /tmp/server.crt -noout -pubkey | \
  openssl pkey -pubin -outform DER | openssl sha256

Den berechneten Hash mit dem Wert aus dem TLSA-Record vergleichen. Stimmen sie überein, ist der Record korrekt.

Schnelltest mit posttls-finger

Wer nicht alles von Hand machen will: posttls-finger (Teil von Postfix) prüft den kompletten DANE-Ablauf in einem Schritt:

posttls-finger -t30 -T180 -c -L verbose,summary kernel-error.de

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.

Wer DANE für den eigenen Mailserver einrichten will, findet die Anleitung unter Postfix mit DANE und DNSSEC absichern. Die Grundlagen zu DANE und TLSA-Records erklärt der Beitrag DNSSEC und DANE: TLS-Zertifikate mit TLSA-Records absichern. Fragen? Einfach melden.

dnssec validator Browser Plugin

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.

https://www.dnssec-validator.cz/pages/download.html
Ist in jedem Fall noch mal einen Klick wert.

Perfect Forward Secrecy für Postfix und Dovecot konfigurieren

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
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_options = no_ticket

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 = ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20:!aNULL:!eNULL
ssl_cipher_suites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

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.

Siehe auch: Post-Quantum TLS für E-Mail

Fragen? Einfach melden.

Postfix mit DANE und DNSSEC absichern

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:

postconf -e "smtp_dns_support_level = dnssec"
postconf -e "smtp_tls_security_level = dane"

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:

openssl x509 -in postfix.pem -noout -pubkey \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256

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:

posttls-finger -t30 -T180 -c -L verbose,summary kernel-error.de

Die entscheidende Zeile in der Ausgabe:

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.


Update August 2014: Ich habe Mailgraph um DANE-Graphen erweitert, um den Anteil verifizierter Verbindungen zu visualisieren.

Siehe auch: TLSA/DANE-Records prüfen, TLSA- und DANE-Records manuell prüfen: Schritt für Schritt mit OpenSSL, Postfix und DANE: „Server certificate not verified" debuggen, Postfix: Eingehende E-Mails ohne TLS ablehnen

Fragen? Einfach melden.

Version bei BIND nicht anzeigen lassen: Schritt-für-Schritt-Anleitung

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:

$ dig -c CH -t txt version.bind +short @dns1.telekom.de
"SORRY"

Sorry finde ich gut liebe Telekom.

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!

Siehe auch: DNSSEC einrichten

Fragen? Einfach melden.

DNSSEC und DANE: TLS-Zertifikate mit TLSA-Records absichern

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:

openssl x509 -in server.pem -noout -pubkey \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256

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.

Prüfen

Mit dig lässt sich der TLSA-Record abfragen:

dig TLSA _443._tcp.www.kernel-error.de +short
3 1 1 a321...f7

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:

echo | openssl s_client -connect www.kernel-error.de:443 2>/dev/null \
  | openssl x509 -noout -pubkey \
  | openssl pkey -pubin -outform DER \
  | openssl dgst -sha256

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.

Siehe auch: DNSSEC einrichten

Fragen? Einfach melden.

DKIM Schüssel getauscht

Nachdem nun alle etwas nervös wegen zu kurzer DKIM Keys sind (512Bit), diese lassen sich wohl bei Amazon in knapp 72 Stunden knacken. Habe ich dann meine Schlüssel auch einmal getauscht. Diese hatten bisher eine Länge von 1024 Bit, mit diesen wäre ich also noch locker auf der sicheren Seite denn noch kann es ja nicht schaden sie auf 2048Bit aufzubohren. Fast alle Systeme können mit diesen inzwischen umgehen. Die Leistung aktueller Systeme sollte heute ebenfalls nicht sonderlich unter diesen Schlüssellänge leiden.

Die Schlüssel sind schnell erstellt:

$ dkim-genkey -b 2048 -s kernel-error.de -d kernel-error.de

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:

kernel-error.de._domainkey IN TXT ( "v=DKIM1; g=*; k=rsa; "
                    "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1V7WG+ZchvAxfJ2wi9jn7vWVs2mDkk66cqrKjTETdbuPwL"
                    "CX4N4IXTemT7SMS2Z+gTxcPNnUCorcMsXigNlGJK4Oq8GNx0fcxbXB+vq522FpM6FY8FVTfhL7bqLg5ajp9k0boJnSRv"
                    "F4wY3nci6E7CYCdP9XjHVoOciJdlrGFMo8rYGGiI9Ubgvue8etqgPCV2T8BKEZgys7kabPyaujSHmqrPbBkjb/F+QPJH"
                    "WqcyD7ywfT5vUkrj40Qiwsr7HxGk9aYCAHwyvdP4dvXd5xfMH2QlRKbrMjIQfKJfD5cfTiAl7YgFBFO1n7Wfj5syB6FE"
                    "bRZR9HO+rusv0hojiViQIDAQAB" )

Schnell noch mit einer Testmail an: check-auth@verifier.port25.com prüfen ob alles korrekt ist.

Fertig….

----------------------------------------------------------
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.

 

Siehe auch: DKIM einrichten

Fragen? Einfach melden.

Mehr als nur A-Records

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:

GPG im DNS: http://www.kernel-error.de/dnssec/gpg-im-dns

SSH-Key im DNS: http://www.kernel-error.de/dnssec/ssh-key-im-dns

Fragen? Einfach melden.

SSH Host Keys per SSHFP im DNS veröffentlichen

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:

dig +short server.example.de SSHFP
1 1 47890EECC9A2893061734B07B8F60CAA1A856148
1 2 B2518AD49CC2ADF517D3F6A9FAAF4017ABC2C3E3...
3 1 3DD9DE0DCF1523341B45A53F1D57043609E26C62
4 2 D4E5F6A7B8C9...

Wichtig: Bei der DNSSEC-validierten Abfrage muss das ad-Flag (Authenticated Data) gesetzt sein — sonst ist die Antwort nicht vertrauenswürdig:

dig +dnssec server.example.de SSHFP | grep flags
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 1

Verbindungsaufbau mit SSHFP

Ohne SSHFP-Records im DNS meldet OpenSSH:

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:

Host *
    VerifyHostKeyDNS yes
    StrictHostKeyChecking yes

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 einrichten: Zonen signieren mit BIND

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:

  1. Er antwortet auf die Delegation-Anfrage mit seinem eigenen Nameserver.
  2. 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.

Schematische Darstellung der DNSSEC-Vertrauenskette: Root-KSK signiert TLD, TLD signiert Domain.

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:

$ dig +short kernel-error.org DS @a0.org.afilias-nst.info
12345 13 2 A1B2C3D4...

Prüfen ob alles funktioniert

Mit dig +dnssec eine signierte Domain abfragen. Das ad-Flag (Authenticated Data) in der Antwort zeigt, dass die DNSSEC-Validierung erfolgreich war:

$ dig +dnssec kernel-error.org @8.8.8.8
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

Grafisch lässt sich die gesamte Vertrauenskette mit DNSviz darstellen — einfach die eigene Domain einsetzen:

Stolpersteine

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:

Handgezeichneter DNSSEC-Masterplan: Reihenfolge fuer Key-Rollover und Zonenuebergaenge mit TTL-Wartezeiten.

Was man auf DNSSEC aufbauen kann

Wenn die Zone signiert ist, lassen sich darüber weitere Sicherheitsmechanismen verteilen:

Wer einen DNSSEC-validierenden Resolver sucht — dns.kernel-error.de bietet DNS over TLS und DNS over HTTPS mit DNSSEC-Validierung., DNSSEC: KSK auf 4096 Bit aktualisieren und SHA-512 vorbereiten, OPENPGPKEY: GPG-Schlüssel direkt im DNS veröffentlichen


Chronik

Dieser Beitrag wurde 2010 veröffentlicht und dokumentiert meine DNSSEC-Einführung über mehrere Jahre:

  • November 2010 — Erste Signierung von kernel-error.org (NSEC3RSASHA1, 4096 Bit).
  • Februar 2011 — DS-Record für kernel-error.org endlich in der .org-Zone veröffentlicht. DENIC kündigt Signierung der .de-TLD an.
  • Februar 2011 — kernel-error.de signiert, über DENIC-Testbed validierbar.
  • Juni 2011 — DENIC signiert .de offiziell, DS-Records in der Root-Zone.
  • Februar 2012 — kernel-error.com ebenfalls signiert. Alle drei Domains komplett.
  • Mai 2012 — GPG-Keys und SSHFP-Records im DNS hinterlegt.
  • August 2013 — DANE/TLSA-Records für alle TLS-Dienste eingerichtet.
  • 2024 — Algorithmus-Wechsel auf ECDSAP256SHA256 (Algorithmus 13). Anleitung oben entsprechend aktualisiert.

Siehe auch: DNSSEC und DANE

Fragen? Einfach melden.

Neuere Beiträge »

© 2026 -=Kernel-Error=-RSS

Theme von Anders NorénHoch ↑