Layer 8Ehrlicher Tech-Support

Falsches Zertifikat, obwohl der Name stimmt: SNI fehlt

Liegen mehrere HTTPS-Namen auf einer IP, entscheidet die SNI-Erweiterung, welches Zertifikat kommt. Fehlt sie, liefert der Server das Standardzertifikat.

Aufwand:
ca. 20 Min.
Voraussetzung:
OpenSSL auf der Kommandozeile, Der genaue Hostname und die IP-Adresse der Gegenstelle
Gilt für:
TLS 1.2 und TLS 1.3, RFC 6066 in der Fassung vom Januar 2011

Das Symptom

Die Seite läuft. Zwei Wochen später meldet ein einzelnes Gerät, ein Skript oder ein alter Kartenleser, das Zertifikat gehöre zu einem anderen Namen – und zwar zu einem, den man noch nie gesehen hat. Oft ist es der Name des Hosters, manchmal der einer völlig fremden Kundendomain auf demselben Server. Alle anderen Geräte im Haus zeigen dieselbe Seite anstandslos an.

Der Reflex ist, das Zertifikat neu auszustellen. Danach ist der Fehler unverändert, nur das Ausstellungsdatum ist neuer.

Die „Layer 8“-Wahrheit

Das Zertifikat ist nicht falsch. Es ist nur nicht das, das gemeint war. TLS hat eine Reihenfolgen-Eigenart, die man einmal verstanden haben muss: Der Server schickt sein Zertifikat, bevor der Client ihm mitgeteilt hat, mit welchem Namen er ihn eigentlich meint. Der HTTP-Host-Header, der genau diese Information trüge, kommt erst in der verschlüsselten Anfrage – also zu spät. RFC 6066 Abschnitt 3 beginnt deshalb mit der ehrlichsten Feststellung des ganzen Dokuments: TLS bietet keinen Mechanismus, mit dem ein Client dem Server den Namen des Servers mitteilen kann, den er kontaktiert. Server Name Indication ist die nachgereichte Antwort darauf, und ihr erklärter Zweck ist genau der Massenbetrieb: sichere Verbindungen zu Servern, die mehrere virtuelle Server unter einer einzigen Netzwerkadresse beherbergen.

Fehlt die Erweiterung, muss der Server raten, und er rät nach Konfiguration: Standard-Host, erster virtueller Host, irgendetwas. RFC 6066 Abschnitt 3 räumt ihm für den Fall eines unbekannten Namens ausdrücklich zwei Wege ein – Abbruch mit einem unrecognized_name(112) auf Fatal-Ebene oder Fortsetzen des Handshakes; ein Alert auf Warning-Ebene ist NOT RECOMMENDED, weil das Clientverhalten darauf unvorhersehbar ist. In der Praxis setzen die meisten Server fort. Deshalb scheitert die Verbindung nicht dort, wo die Ursache liegt, sondern erst eine Stufe später. Derselbe Abschnitt beschreibt das präzise: Weicht der von der Anwendung verwendete Servername vom Namen der gewählten Anmeldeinformation ab, wird das erst bei der Endpunkt-Identifizierung durch die Client-Anwendung sichtbar. Der Handshake war sauber. Der Name war es nicht.

Zwei Fallen bleiben. Die erste heißt IP-Adresse: RFC 6066 Abschnitt 3 verbietet literale IPv4- und IPv6-Adressen im Feld HostName. Wer zum Testen per IP verbindet, sendet also standardkonform überhaupt keinen Namen und provoziert genau den Fehler, den er untersuchen will – ein Diagnoseartefakt, das für einen echten Serverfehler gehalten wird. Die zweite heißt OpenSSL: Seit Version 1.1.1 füllt s_client die SNI von sich aus mit dem an -connect übergebenen Namen, sofern dieser wie ein DNS-Name aussieht, und ohne -connect mit „localhost“. Wer den SNI-losen Fall nachstellen will, muss das mit -noservername ausdrücklich erzwingen. Und wenn eine Sitzung, die eben noch lief, beim Wiederaufnehmen plötzlich einen vollständigen Handshake macht: Ein Server, der die Erweiterung implementiert, darf eine Sitzung nicht wiederaufnehmen, wenn die server_name-Erweiterung einen anderen Namen enthält. Auch das ist kein Defekt, sondern der Standard bei der Arbeit.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Prüfen, ob die Gegenstelle überhaupt mehrere Namen bedient

    Das Problem tritt nur dort auf, wo hinter einer IP-Adresse mehrere Zertifikate liegen. Der schnellste Test ist ein Vergleich: einmal mit gesetztem Servernamen verbinden, einmal ohne. Kommen zwei verschiedene Zertifikate zurück, hängt die Auswahl an SNI – und damit ist die Ursache gefunden.

    openssl s_client -connect 203.0.113.10:443 -servername www.example.de -brief </dev/null
    openssl s_client -connect 203.0.113.10:443 -noservername -brief </dev/null
    
  2. 2.

    Das ausgelieferte Zertifikat lesen, nicht raten

    Entscheidend sind Subject und die Subject Alternative Names des ersten Zertifikats. Steht dort ein ganz anderer Name oder der Standardname des Hosters, hat der Server die Auswahl ohne SNI getroffen. Die Manpage weist darauf hin, dass -showcerts die Liste so anzeigt, wie der Server sie gesendet hat, und dass dies keine verifizierte Kette ist.

    openssl s_client -connect 203.0.113.10:443 -servername www.example.de </dev/null \
      | openssl x509 -noout -subject -ext subjectAltName
    
  3. 3.

    Verstehen, was OpenSSL von sich aus sendet

    Ohne eigenes Zutun ist SNI meist schon gesetzt, und das verfälscht die Diagnose. Die Manpage zu -servername hält fest: Wird -servername nicht angegeben, wird die TLS-SNI-Erweiterung mit dem an -connect übergebenen Namen gefüllt, sofern dieser einem DNS-Namensformat folgt; fehlt auch -connect, wird SNI auf „localhost“ gesetzt. Das ist seit OpenSSL 1.1.1 das Standardverhalten. Wer den Fall ohne SNI nachstellen will, braucht deshalb ausdrücklich -noservername.

  4. 4.

    Auf der Serverseite den Standardfall festlegen

    Ein Server, der mehrere Namen auf einer Adresse bedient, beantwortet jede Anfrage ohne passenden Servernamen mit irgendeinem Zertifikat – in aller Regel dem des ersten oder als Standard markierten virtuellen Hosts. RFC 6066 Abschnitt 3 überlässt dem Server ausdrücklich die Wahl zwischen Abbruch mit unrecognized_name(112) auf Fatal-Ebene und Fortsetzen des Handshakes. Welche der beiden Varianten der eigene Server wählt, ist eine Konfigurationsentscheidung und keine Eigenschaft von TLS.

  5. 5.

    Alte Clients als das behandeln, was sie sind

    RFC 6066 Abschnitt 3 formuliert das Senden der Erweiterung als Empfehlung: Es ist RECOMMENDED, dass Clients eine server_name-Erweiterung im ClientHello mitsenden, wann immer sie einen Server über einen unterstützten Namenstyp auffinden. Eine Pflicht ist es nicht. Wo ein sehr altes Gerät, ein eingebettetes System oder eine schlanke Bibliothek keine SNI sendet, hilft kein Serverzertifikat der Welt – dort bleibt nur eine eigene IP-Adresse für diesen Namen oder ein Client, der die Erweiterung beherrscht.

Häufige Fragen (FAQ)

?Warum braucht TLS diese Erweiterung überhaupt?

Weil der Server sein Zertifikat schickt, bevor irgendein Hostname übertragen wurde. RFC 6066 Abschnitt 3 benennt das Problem im ersten Satz: „TLS does not provide a mechanism for a client to tell a server the name of the server it is contacting.“ Der HTTP-Host-Header steht erst in der bereits verschlüsselten Anfrage – zum Zeitpunkt der Zertifikatsauswahl kennt der Server also nur die IP-Adresse und den Port. Der Abschnitt nennt als Zweck der Erweiterung ausdrücklich, sichere Verbindungen zu Servern zu ermöglichen, die mehrere virtuelle Server unter einer einzigen Netzwerkadresse betreiben.

?Warum meldet der Browser dann einen Namensfehler und keinen SNI-Fehler?

Weil die Prüfung an einer ganz anderen Stelle stattfindet. RFC 6066 Abschnitt 3 beschreibt das genau: Gibt es eine Abweichung zwischen dem von der Client-Anwendung verwendeten Servernamen und dem Namen der vom Server gewählten Anmeldeinformation, wird diese Abweichung sichtbar, wenn die Client-Anwendung die Endpunkt-Identifizierung durchführt. Der Handshake selbst ist zu diesem Zeitpunkt technisch einwandfrei gelaufen – nur passt das ausgelieferte Zertifikat nicht zu dem Namen, den man aufgerufen hat. Deshalb sieht der Fehler nach einem falschen Zertifikat aus, obwohl die Ursache im ClientHello liegt.

?Kann ich eine IP-Adresse als SNI senden?

Nach dem Standard nicht. RFC 6066 Abschnitt 3 sagt zum Feld HostName wörtlich: „Literal IPv4 and IPv6 addresses are not permitted in ‚HostName‘.“ Der Abschnitt hält außerdem fest, dass HostName den vollqualifizierten DNS-Namen des Servers enthält, als ASCII-Bytefolge ohne abschließenden Punkt, und dass internationalisierte Domainnamen über A-Labels abgebildet werden. Wer per IP-Adresse verbindet, sendet daher regulär gar keinen Servernamen – und bekommt genau deshalb das Standardzertifikat des Servers.

?Was tut ein Server, der den gesendeten Namen nicht kennt?

RFC 6066 Abschnitt 3 lässt ihm zwei Wege: Hat der Server die ClientHello-Erweiterung verstanden, kennt aber den Servernamen nicht, „SHOULD“ er entweder den Handshake mit einem unrecognized_name(112) auf Fatal-Ebene abbrechen oder den Handshake fortsetzen. Ein Alert auf Warning-Ebene ist ausdrücklich NOT RECOMMENDED, weil das Verhalten des Clients auf Warnungen unvorhersehbar ist. Setzt der Server fort, bekommt man ein Zertifikat – nur eben irgendeines.

?Warum bricht eine wiederaufgenommene Sitzung plötzlich?

Weil der Servername Teil der Sitzungsidentität ist. Nach RFC 6066 Abschnitt 3 soll der Client bei der Wiederaufnahme dieselbe server_name-Erweiterung senden wie im vollständigen Handshake, und ein Server, der die Erweiterung implementiert, „MUST NOT“ die Wiederaufnahme akzeptieren, wenn die Erweiterung einen anderen Namen enthält – er führt stattdessen einen vollständigen Handshake durch. Beim Wiederaufnehmen darf der Server die Erweiterung im ServerHello nicht mitsenden.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

  1. [2]
    openssl-s_client – Manpage der OpenSSL-Dokumentation

    docs.openssl.org · abgerufen am

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigNET::ERR_CERT_AUTHORITY_INVALID

Browser: NET::ERR_CERT_AUTHORITY_INVALID

Der Browser warnt, das Zertifikat stamme von keiner vertrauenswürdigen Stelle? Oft schneidet Software mit oder es ist selbst signiert.