Worum geht's hier?

In zwei Jahrzehnten als Vollzeitnerd hat sich der ein oder andere Text angesammelt, mit denen ich unseren Azubis versucht habe, Grundlagen über unseren Job (TCP/IP, aber auch bevorzugt Telefonie) zu erklären.

Das stelle ich hier, wann immer ich so einen Text nochmal irgendwo finde, zusammen. Diese Texte haben nicht den Anspruch, zu 100% exakt zu sein (sondern manches ist des besseres Verständnisses wegen vereinfacht worden). 

Heute:

TLS/SSL und HTTPS

Ein Großteil der Kommunikation im Internet funktioniert heute über TLS-Verschlüsselung, auch SSL genannt. Ich erkläre das Prinzip hier am Beispiel von HTTP vs. HTTPS, das Prinzip ist aber bei anderen Protokollen sehr ähnlich.

Um zu verstehen, worum es geht, gucken wir uns erstmal die unverschlüsselte Kommunikation an:

Unverschlüsseltes HTTP (HyperText Transfer Protocol)

Wenn ich die Webseite www.vollzeitnerd.de explizit mit http: davor aufrufe, dann schickt mein Browser an den Webserver folgende Anfrage:

GET / HTTP/1.1
Host: www.vollzeitnerd.de
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: de-DE,de;q=0.9
 

Die erste Zeile definiert den Abfragetyp (die beiden wichtigsten sind GET für in der Regel Seiten-Aufrufe und POST für z.B. abgeschickte Formulare mit Inhalt) und das Protokoll samt Version. Hinter dem GET steht auch die REQUEST URI, also die aufgerufene Webseite (in dem Fall nur: /). Da könnte auch z.B. GET /erklaerbaer/irgendwas/tolles-thema HTTP/1.1 stehen.

Dann kommt die Frage nach dem Hostnamen, den ich im Browser eingetippt habe. Da mein Provider nicht nur mich als Kunde hat, braucht der Webserver diese Angabe, um zu gucken, welche Webseite er überhaupt aufrufen will. Hostname und REQUEST-URI zusammen sind also das, was ich in der Adressleiste meines Browsers übertragen habe.

Wichtig ist jetzt noch der "Accept-Teil", mein Browser akzeptiert verschiedene Formate (z.B. HTML) als Antwort und ist auch bereit, ein per gzip komprimiertes Ergebnis zu bekommen (d.h. das spart Bandbreite).

Der Server antwortet jetzt mit:

HTTP/1.1 200 OK
Date: Sat, 01 Jan 2000 11:49:40 GMT
Server: Apache
Content-Language: de
Expires: Sat, 01 Jan 2020 11:49:40 GMT
Cache-Control: max-age=604800
Pragma: public
Vary: Accept-Encoding
Content-Length: 6846
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8

<html><head><title>Home - Vollzeitnerd.de</title>

Erstmal ein Status-Code: 200 OK. Der bekanteste Fehlercode ist z.B. 404 Not found, bei einer Fehlkonfiguration auf dem Server könnte auch ein 500 Internal Server Failure kommen. Leitet der Server mich woanders hin um (z.B. weil die Webseite https erzwingen und mich darum auf https + www.vollzeitnerd.de umleiten will) wäre das 301 Moved Permanently. Die Statuscodes sind nicht zufällig ähnlich wie die Antworten auf ein SIP-INVITE, sondern viele Protokolle ähneln sich mit Absicht, was sich bewährt hat, muss man ja nicht nochmal erfinden (HTTP ist aber von beiden Standards eindeutig der ältere).

Hier jedenfalls ist es ein 200 OK, also kommt eine Webseite. Es kommen ein paar Angaben zum Stand der Webseite und zu Caching ("expire")-Angaben, und dann kommt die eigentliche Webseite im Klartext. An der Stelle habe ich geschummelt, im Original war der Inhalt wie angefordert gzip-komprimiert (dann ist er mit bloßem Auge nicht erkennbar, aber keineswege sicherer). Beides, sowohl die Anfrage vom Browser (die ja auch - wenn es z.B. "POST" statt "GET" gewesen wäre, auch Feldinhalte, z.B. Zugangsdaten beinhalten würde) als auch die Antwort vom Server (die ja neben Text auch z.B. Cookies mit Transaktions-Token enthält, mit denen man eine Login-Session übernehmen kann) geht also völlig unverschlüsselt durch die Leitung und kann einfach so mitgelesen werden.

Secure Socket Layer (SSL), Transport Layer Security (TLS), Hypertext Transfer Protocol Secure (HTTPS) - was denn jetzt?

Wollen wir die Übertragung jetzt verschlüsseln, dann kommt "Transport Layer Security" (TLS) zum Einsatz. TLS ist der Nachfolger von SSL (Secure Socket Layer), die letzte verbreitete Version von SSL war 3.0 und gilt als veraltet, danach kam theoretisch SSL 3.1 und wurde in TLS 1.0 umbenannt. Inzwischen sind wir bei TLS Version 1.3 angekommen (d.h. SSL ist de facto ausgestorben), aber der alte Name SSL ist halt immer noch verbreitet und wird als Synonym zu TLS verwendet.

SSL/TLS ist erstmal das Protokoll für die verschlüsselte Übertragung. Wenn man das jetzt für Webseiten (HTTP-Aufrufe) nutzen will, nimmt man als Protokoll "HTTPS", also HTTP+SSL/TLS. 

Nach dem gleichen Schema arbeitet auch IMAPS (IMAP+SSL/TLS, also verschlüsseltes IMAP) usw.

In der Praxis werden diese drei Begriffe SSL, TLS und HTTPS munter durcheinander geworfen.

Verschlüsselung

Eine TLS-gesicherte Übertragung besteht aus zwei Bestandteilen: Der eigentlichen Verschlüsselung und dem SSL-Zertifikat. Fangen wir mit der Verschlüsselung an.

Ganz vereinfacht funktioniert die Verschlüsselung so:

  • Alice und Bob haben beide einen private und einen public key. Mit dem public key kann jeder Nachrichten verschlüsseln, die dann der Inhaber des private keys (und zwar nur der) entschlüsseln kann. 
  • Sie beginnen den SSL-Handshake, d.h. sie tauschen Informationen übereinander aus. Dazu gehört die Identität des jeweils anderen ("SSL-Zertifikat"), aber auch der jeweilige public Key.
  • Wenn Alice jetzt etwas an Bob schickt (z.B. der Browser an den Server die aufzurufene URL), dann kennt sie Bobs public key und verschlüsselt die Daten damit. Bob, also der Server, empfängt die Nachricht, kann sie mit dem nur ihm bekannten PrivateKey entschlüsseln und lesen.
  • Und bei der Antwort macht Bob das ganze genau andersherum.
  • Die Daten entsprechen 1:1 dem, was auch bei http übertragen wäre. Nur dass es eben verschlüsselt ist.

Die Identätitsprüfung (SSL-Zertifikat) passiert in der Praxis nur in eine Richtung (der Server weist per Zertifikat nach, dass er vertrauenswürdig ist). Technisch möglich wäre aber auch, dass der Client per Zertifikat seinerseits nachweist, dass er überhaupt befugt ist, die Seite aufzurufen.

Das SSL-Zertfikat

Die Verschlüsselung ist erstmal völlig vom SSL-Zertifikat unabhängig. Auch bei einer Webseite, bei der der Browser Zertifikatswarnungen anzeigt (die hat ja bestimmt jeder schon mal gesehen) ist die Übertragung so gesichert und es kann niemand anderes mitlesen. 

Das Zertifikat kommt jetzt ins Spiel, damit Bob auch nachweisen kann, dass er überhaupt Bob ist. Es dient ausschließlich der Identitätsprüfung.

Wenn ich in meinem Browser die Webseite meiner Hausbank aufrufe, dann gibt es verschiedene Angriffspunkte, wie man meinen Browser umlenken könnte: Man könnte in meinem Netzwerk einen böswillen zusätzlichen DHCP-Server gestartet haben und lenkt meinen Internet-Verkehr auf einen anderen Router um, nennt mir manipulierte Nameserver (die eine falsche IP zurückmelden) oder nennt mir einen manupulierten Proxy-Server. Oder man könnte mit irgend einem Trojaner meine Hosts-Datei um schädliche Einträge erweitert haben. Oder oder oder.

In all diesen Fällen würde ich die Webseite meiner Hausbank aufrufen, aber auf dem Server eines Bösewichtes rauskommen. Der gibt mir seinen PublicKey, ich gebe ihm meinen, wir verschlüsseln die Kommunikation, und die Verbindung ist völlig abhörsicher. HTTPS hätte technisch erstmal einwandfrei funktioniert. Und doch würde ich im Vertrauen darauf, dass ich mit meiner Bank rede (was ich nicht tue) Zugangsdaten einem fremden geben.

Um das zu verhindern, gibt es das SSL-Zertifikat. Damit kann der Server meiner Bank beweisen, dass er er ist. Und der Bösewicht kann es nicht, weil er kein SSL-Zertifikat für den DOmainnamen meiner Bank vorweisen kann, das mein Browser akzeptiert (d.h. beim Aufruf des falschen Servers unter richtigem Namen wird mein Browser eine Warnung anzeigen).

Das SSL-Zertifkat besteht aus folgenden Komponenten:

  • Es ist besteht wieder aus einem privaten Teil (den nur der Server kennt ... wird der entwendet, könnte sich ein Bösewicht damit ausweisen) und einem öffentlichen Teil (den der Server vorlegt als Beweis seiner Vertrauenswürdigkeit)
  • Es trägt einen (oder mehrere) CommonNames, also Namen, auf die es ausgestellt ist, in sich. In der Regel der Domainname in den Schreibweisen mit und ohne www. Wenn der Domainname im Zertifikat von dem abweicht, was ich im Browser eingegeben habe, dann verhindert der Browser die Kommunikation. Auch, wenn die Abweichung minimal (z.B. im Zertifikat ist nur die Schreibweise mit www, und ich rufe es ohne auf) ist.
  • Es hat ein Gültigkeitsdatum. Ist das abgelaufen, wird es vom Client nicht mehr akzeptiert. Auch das wird ähnlich kleinlich gehandhabt (und wie beim Personalausweis auch: Wenn ich ziemlich sicher bin, dass ich mit der richtigen Person rede und der Ausweis ansonsten passt, dann sind drei Tage "drüber" noch nicht zwingend kein Grund zur Sorge). Durch das Gültigkeitsdatum wird verhindert, dass abhanden gekommene Zertifikate ewig missbraucht werden können.
  • Es ist von einer vertrauenswürdigen Stelle (Certificate Authority, CA) ausgestellt bzw. signiert (dazu gleich mehr)

Wenn diese drei Bedingungen erfüllt sind (CommonName passt, Gültigkeit passt, Aussteller vertrauenswürdig), dann wird die Verbindung aufgebaut (und je nach Browser mit einem grünen Schloss signalisiert), denn dann kann man sicher sein, dass man mit dem richtigen Gegenüber spricht. (Als viertes Kriterium gibt es noch Listen, wo bereits ausgestellte Zertifikate zurückgezogen, also öffentlich für ungültig erklärt werden können. In wie weit die Browser diese Listen aber berücksichtigen, ist nicht einheitlich geregelt).

Wenn eines oder mehr Kriterien nicht stimmen, gibt es mindestens mal eine Fehlermeldung. Und weil Leute es sich angewöhnt haben, Fehlermeldungen einfach wegzuklicken, wird es immer schwieriger (und für ITler, die wissen was sie tun, immer nervigier), wenn man sich bewusst darüber hinwegsetzen will.

Scheinbar vertrauenswürdiges Zertifikat

Ein großes Problem sind Tippfehler, Phishing-Mails, manipulierte Google-Suchergebnisse usw., die das Opfer dazu bringen, eine falsche Domain aufzurufen:

  • Varianten mit einem Tippfehler drin (www.spakrasse-koeln-bonn.de z.B.), der schnell übersehen wird
  • Varianten, die plausibel aussehen (aber gar nichts zu tun haben mit der Seite, die ich aufrufen will), z.B. "www.stadtsparkasse-koeln-bonn.de"
  • Varianten, die ein Sonderzeichen enthalten (was dank IDN-Domains ja möglich ist), was in deutschen Browsern aber nicht dargestellt wird. 

In all diesen Fällen landet der Benutzer auf einer Seite, von der er glaubt es wäre in diesem Fall die Sparkasse KölnBonn. Und der Betreiber dieser Seite könnte sie auch problemlos und legal mit einem SSL-Zertifikat ausstatten, was zu einem "grünen Schloss" und keiner Warnung des Browsers führt, denn rein technisch ist das ja das Ziel, was man aufgerufen hat.

Da gibt es verschiedene Ansätze, mit dem Problem umzugehen. Einerseits verhindern die Browser z.B. teilweise "unsichtbare IDN-Domain-Schreibweisen". Andererseits gab/gibt es sog. EV-Zertifikate (Exteded Validation), bei denen die ausstellende Organisation strengere Kriterien stellt (der Domainname muss zum Firmennamen lt. Handelsregister passen und man muss sich als gesetzlicher Vertreter dieser Firma auch ausweisen usw.) und die dann in Browsern optisch hervorgehoben ist (der Firmenname des Zertifikatsinhabers stand dann deutlich neben der URL). Seit 2019 ist diese optische Hervorhebung der EV-Zertifikate aus den Browsern nach und nach verschwunden (weil sie ohnehin von Anwendern nicht wahrgenommen bzw. verstanden wurde), so dass EV-Zertifikate im Prinzip heute unnötig sind.

Zertifikats-Aussteller

Damit das Zertifikat auf den eigenen Server kommt, gibt es folgende Wege:

Manuell durch CA

Man erstellt mit z.B. "OpenSSL" auf dem Server ein Certificate Signing Request (CSR), also eine Anforderungsdatei. Die schickt man dem Anbieter, von dem man das SSL-Zertifikat bekommt (Certificate Authority selbst, oder ein Wiederverkäufer), der prüft die Idendität (meist genügt dafür eine Mail an eine Adresse wie z.B. ssl-admin@ der zu signiererenden Domain - wer die einrichten kann, wird wohl befugt sein) und stellt dann die Zertifikatsdatei (private/public key) aus, mit der das Zertifikat signiert ist.

Die Certificate Authority wiederum hat ihr Stamm-Zertifikat in allen Browsern einbauen lassen. Dein Browser weiß also, welcher CA er vertraut. Und alle von dieser CA signierten Zertifikate gelten aus vertrauenswürdig. Das ist wie bei der Passkontrolle im Ausland, wenn mein Reisepass von der Bundesrepublik Deutschland ausgestellt ist (und die auf der Liste der "vertrauenswürdigen Pass-Aussteller" steht, die in dem Einreiseland gilt), dann darf ich da einreisen. Und beim Pass muss nicht irgend eine Bundesbehörde jeden Ausweis selbst abstempeln, sondern sie delegieren das z.B. an die Stadt Köln (und die dürfen mit ihrem Dienstsiegel den Pass signieren); beim SSL-Zertifikat sieht das genauso aus, es gibt ganz viele Anbieter von Zertifikaten, die nicht selbst als CA im Browser hinterlegt sind, aber die über ein "Zwischenzertifikat" dafür befugt wurden, selbst welche auszustellen. 

Automatisch / lets encrypt

In den letzten Jahren (zu recht) sehr beliebt geworden ist "Let's Encrypt". Früher waren SSL-Zertifikate noch teuer und manueller Aufwand, bis 2015 mit Let's Encrypt dem ein Ende gesetzt wurde. Einerseits hat man die Prüfung über das eigene sog. ACME-Protokoll (Automatic Certificate Management Environment) komplett automatisiert, andererseits werden die Zertifikate kostenlos ausgestellt. Das hat dazu geführt, dass der lukrative SSL-Zertifikats-Markt zusammengebrochen, aber dafür die Verbreitung von HTTPS um ein Vielfaches gestiegen ist.

Manuell durch den Administrator

Wenn einem die Erreichbarkeit von Dritten nicht wichtig ist, kann ein Administrator sich bzw. seinen Systemen auch einfach selbst ein SSL-Zertifikat ausstellen (man verzichtet auf den Signatur-Bereich). Wie eingangs schon beschrieben ändert das an der Sicherheit der Verschlüsselung nichts, es verhindert halt nur ein Erkennen von Man-in-the-middle-Angriffen.

Damit die z.B. Mitarbeiter nicht auf ein unnötiges "Bestätigen von Fehlermeldungen" konditioniert werden, könnte man sowohl sein eigenes Zertifikat, aber auch sein eigenes CA-Rootzertifikat auf den PCs der Mitarbeiter einspielen. Damit würden seine Zertifikate als vertrauenswürdig akzeptiert.

Das große Risiko dieser Vorgehensweise ist, dass es ein Angreifer, gelangt er in den Besitz des private keys des Administrators, viel einfacher allen Mitarbeitern dieser Firma Phishing-Seiten unterschieben kann.

Zertifikate für absichtliches Man-in-the-middle

Produkte mit "Layer7-Firewall-Funktionalität" überwachen die Webseiten, die ein Benutzer aufruft, nach "unerlaubtem" Inhalt (Schadcode usw.). Das ist bei Ende-zu-Ende-Verschlüsselung natürlich nur schwierig möglich. Wenn es eine Software ist, kann sie auf dem betreffenden PC natürlich alles machen. Wenn sie aber im Netzwerk dazwischen hängt (als sog. Applicance) und als Gateway/Proxy den Verkehr analysieren wollen, müssen sie die Verschlüsselung aufbrechen.

Die Firewall macht dabei den Seitenaufruf gegenüber dem Webserver (d.h. zwischen ihr und dem Webserver ist die Verbindung verschlüsselt), analysiert den Inhalt, verschlüsselt ihn wieder (mit seinem private key) und liefert ihn an den Anwender aus. Da genau dieses Szenario normalerweise das ist, was man durch SSL-Zertifikate verhindern will, muss der Administrator dabei ein CA-Rootzertifikat des Firewall-Herstellers auf den PCs installieren (damit die den Schwindel nicht bemerken). Die Nachteile liegen auf der Hand: Der Anwender hat selbst keine Möglichkeit mehr, wirklich zu erkennen ob er mit dem richtigen Gegenüber redet (alles, was er per https aufruft, bekommt er von der Firewall signiert, selbst wenn die auf eine Fälschung reingefallen wäre), und der Anwender hat keine wirksame Ende-zu-Ende-Verschlüsselung mehr - die Firewall wäre also ein perfektes Eingangstor für Schadcode. (Siehe auch Schlangenöl-Problematik).

Wildcard, MultiDomain und Server Name Indication (SNI)

Hinsichtlich des CommonNames gibt es drei Arten von Zertifikaten:

  • SingleDomain-Zertifikate (wobei ganz streng genommen bereits mit-und-ohne-www ja zwei verschiedene Domainnamen sind), wie man sie üblicherweise für eine Webseite benutzt
  • MultiDomain-Zertifikate, d.h. das Zertifikat lautet auf verschiedene (getrennte) Hostnamen. Anwendungszweck ist z.B. ein Mailserver, der auf verschiedene Hostnamen ("smtp.", "pop3.", "imap.") hört und die alle mit einem Zertifikat absichert
  • Wildcard-Zertifikate für *.beispieldomain.de, diese werden dann für Organisationen oder Provider genommen, die eine größere Anzahl an Servern/Diensten absichern wollen.

In den ersten Versionen von SSL war es technisch so, dass jede SSL-Webseite auch eine eigene IP-Adresse brauchte, denn zuerst wird im SSL-Handshake das Zertifikat übermittelt und, erst danach in dem "GET-Request" (siehe oben im http-Teil) ja der Hostname. Und da gab es ein Henne-Ei-Problem: Der Server wusste nicht, welches Zertifikat (für welche Webseite) er ausliefern soll, solange er den Hostnamen nicht kennt, also hat er das erstbeste genommen. Und der Browser verrät den Hostnamen nicht, weil das erstbeste Zertifikat den falschen CommonName hatte und darum kam es gar nicht erst dazu, das GET-Request zu senden.

Also galt die Regel: Jede IP-Adresse ein eigenes Zertifikat, und damit brauchte jede Webseite eine eigene IP. Die Alternativen wären MultiDomain-Zertfikate gewesen, aber die waren weder besonder handlich, noch besonders schön (jeder Besucher einer Webseite konnte so in der CommonName-Liste des Zertifikates sehen, welche anderen Webseiten auf diesem Server noch das gleiche Zertifikat nutzen.

Seit 2006 gibt es daher als Abhilfe "Server Name Indication" (SNI), eine Erweiterung des TLS-Protokolls. Dabei überträgt der Browser bereits im Handshake (und damit noch unverschlüsselt) den Hostnamen (aber nur den - den Rest des GET-Requestes hält er zurück, bis die Verbindung sicher ist), damit der Server das passende Zertifikat raussuchen kann.

Feedback