committed by
GitHub
1 changed files with 190 additions and 0 deletions
@ -0,0 +1,190 @@ |
|||
# Über HTTPS |
|||
|
|||
Es ist leicht anzunehmen, dass HTTPS etwas ist, was einfach nur „aktiviert“ wird oder nicht. |
|||
|
|||
Aber es ist viel komplexer als das. |
|||
|
|||
!!! tip "Tipp" |
|||
Wenn Sie es eilig haben oder es Ihnen egal ist, fahren Sie mit den nächsten Abschnitten fort, um Schritt-für-Schritt-Anleitungen für die Einrichtung der verschiedenen Technologien zu erhalten. |
|||
|
|||
Um **die Grundlagen von HTTPS** aus Sicht des Benutzers zu erlernen, schauen Sie sich <a href="https://howhttps.works/" class="external-link" target="_blank">https://howhttps.works/</a> an. |
|||
|
|||
Aus **Sicht des Entwicklers** sollten Sie beim Nachdenken über HTTPS Folgendes beachten: |
|||
|
|||
* Für HTTPS muss **der Server** über von einem **Dritten** generierte **„Zertifikate“** verfügen. |
|||
* Diese Zertifikate werden tatsächlich vom Dritten **erworben** und nicht „generiert“. |
|||
* Zertifikate haben eine **Lebensdauer**. |
|||
* Sie **verfallen**. |
|||
* Und dann müssen sie vom Dritten **erneuert**, **erneut erworben** werden. |
|||
* Die Verschlüsselung der Verbindung erfolgt auf **TCP-Ebene**. |
|||
* Das ist eine Schicht **unter HTTP**. |
|||
* Die Handhabung von **Zertifikaten und Verschlüsselung** erfolgt also **vor HTTP**. |
|||
* **TCP weiß nichts über „<abbr title="Domäne, Bereich, Wirkungsraum">Domains</abbr>“**. Nur über IP-Adressen. |
|||
* Die Informationen über die angeforderte **spezifische Domain** befinden sich in den **HTTP-Daten**. |
|||
* Die **HTTPS-Zertifikate** „zertifizieren“ eine **bestimmte Domain**, aber das Protokoll und die Verschlüsselung erfolgen auf TCP-Ebene, **ohne zu wissen**, um welche Domain es sich handelt. |
|||
* **Standardmäßig** bedeutet das, dass Sie nur **ein HTTPS-Zertifikat pro IP-Adresse** haben können. |
|||
* Ganz gleich, wie groß Ihr Server ist oder wie klein die einzelnen Anwendungen darauf sind. |
|||
* Hierfür gibt es jedoch eine **Lösung**. |
|||
* Es gibt eine **Erweiterung** zum **TLS**-Protokoll (dasjenige, das die Verschlüsselung auf TCP-Ebene, vor HTTP, verwaltet) namens **<a href="https://en.wikipedia.org/wiki/Server_Name_Indication" class="external-link" target="_blank"><abbr title="Server Name Indication – Angabe des Servernamens">SNI</abbr></a>**. |
|||
* Mit dieser SNI-Erweiterung kann ein einzelner Server (mit einer **einzelnen IP-Adresse**) über **mehrere HTTPS-Zertifikate** verfügen und **mehrere HTTPS-Domains/Anwendungen** bedienen. |
|||
* Damit das funktioniert, muss eine **einzelne** Komponente (Programm), die auf dem Server ausgeführt wird und welche die **öffentliche IP-Adresse** überwacht, **alle HTTPS-Zertifikate** des Servers haben. |
|||
* **Nachdem** eine sichere Verbindung hergestellt wurde, ist das Kommunikationsprotokoll **immer noch HTTP**. |
|||
* Die Inhalte sind **verschlüsselt**, auch wenn sie mit dem **HTTP-Protokoll** gesendet werden. |
|||
|
|||
Es ist eine gängige Praxis, **ein Programm/HTTP-Server** auf dem Server (der Maschine, dem Host usw.) laufen zu lassen, welches **alle HTTPS-Aspekte verwaltet**: Empfangen der **verschlüsselten HTTPS-Requests**, Senden der **entschlüsselten HTTP-Requests** an die eigentliche HTTP-Anwendung die auf demselben Server läuft (in diesem Fall die **FastAPI**-Anwendung), entgegennehmen der **HTTP-Response** von der Anwendung, **verschlüsseln derselben** mithilfe des entsprechenden **HTTPS-Zertifikats** und Zurücksenden zum Client über **HTTPS**. Dieser Server wird oft als **<a href="https://en.wikipedia.org/wiki/TLS_termination_proxy" class="external-link" target="_blank">TLS-Terminierungsproxy</a>** bezeichnet. |
|||
|
|||
Einige der Optionen, die Sie als TLS-Terminierungsproxy verwenden können, sind: |
|||
|
|||
* Traefik (kann auch Zertifikat-Erneuerungen durchführen) |
|||
* Caddy (kann auch Zertifikat-Erneuerungen durchführen) |
|||
* Nginx |
|||
* HAProxy |
|||
|
|||
## Let's Encrypt |
|||
|
|||
Vor Let's Encrypt wurden diese **HTTPS-Zertifikate** von vertrauenswürdigen Dritten verkauft. |
|||
|
|||
Der Prozess zum Erwerb eines dieser Zertifikate war früher umständlich, erforderte viel Papierarbeit und die Zertifikate waren ziemlich teuer. |
|||
|
|||
Aber dann wurde **<a href="https://letsencrypt.org/" class="external-link" target="_blank">Let's Encrypt</a>** geschaffen. |
|||
|
|||
Es ist ein Projekt der Linux Foundation. Es stellt **kostenlose HTTPS-Zertifikate** automatisiert zur Verfügung. Diese Zertifikate nutzen standardmäßig die gesamte kryptografische Sicherheit und sind kurzlebig (circa 3 Monate), sodass die **Sicherheit tatsächlich besser ist**, aufgrund der kürzeren Lebensdauer. |
|||
|
|||
Die Domains werden sicher verifiziert und die Zertifikate werden automatisch generiert. Das ermöglicht auch die automatische Erneuerung dieser Zertifikate. |
|||
|
|||
Die Idee besteht darin, den Erwerb und die Erneuerung der Zertifikate zu automatisieren, sodass Sie **sicheres HTTPS, kostenlos und für immer** haben können. |
|||
|
|||
## HTTPS für Entwickler |
|||
|
|||
Hier ist ein Beispiel, wie eine HTTPS-API aussehen könnte, Schritt für Schritt, wobei vor allem die für Entwickler wichtigen Ideen berücksichtigt werden. |
|||
|
|||
### Domainname |
|||
|
|||
Alles beginnt wahrscheinlich damit, dass Sie einen **Domainnamen erwerben**. Anschließend konfigurieren Sie ihn in einem DNS-Server (wahrscheinlich beim selben Cloud-Anbieter). |
|||
|
|||
Sie würden wahrscheinlich einen Cloud-Server (eine virtuelle Maschine) oder etwas Ähnliches bekommen, und dieser hätte eine <abbr title="Sie ändert sich nicht">feste</abbr> **öffentliche IP-Adresse**. |
|||
|
|||
In dem oder den DNS-Server(n) würden Sie einen Eintrag (einen „`A record`“) konfigurieren, um mit **Ihrer Domain** auf die öffentliche **IP-Adresse Ihres Servers** zu verweisen. |
|||
|
|||
Sie würden dies wahrscheinlich nur einmal tun, beim ersten Mal, wenn Sie alles einrichten. |
|||
|
|||
!!! tip "Tipp" |
|||
Dieser Domainnamen-Aspekt liegt weit vor HTTPS, aber da alles von der Domain und der IP-Adresse abhängt, lohnt es sich, das hier zu erwähnen. |
|||
|
|||
### DNS |
|||
|
|||
Konzentrieren wir uns nun auf alle tatsächlichen HTTPS-Aspekte. |
|||
|
|||
Zuerst würde der Browser mithilfe der **DNS-Server** herausfinden, welches die **IP für die Domain** ist, in diesem Fall für `someapp.example.com`. |
|||
|
|||
Die DNS-Server geben dem Browser eine bestimmte **IP-Adresse** zurück. Das wäre die von Ihrem Server verwendete öffentliche IP-Adresse, die Sie in den DNS-Servern konfiguriert haben. |
|||
|
|||
<img src="/img/deployment/https/https01.svg"> |
|||
|
|||
### TLS-Handshake-Start |
|||
|
|||
Der Browser kommuniziert dann mit dieser IP-Adresse über **Port 443** (den HTTPS-Port). |
|||
|
|||
Der erste Teil der Kommunikation besteht lediglich darin, die Verbindung zwischen dem Client und dem Server herzustellen und die zu verwendenden kryptografischen Schlüssel usw. zu vereinbaren. |
|||
|
|||
<img src="/img/deployment/https/https02.svg"> |
|||
|
|||
Diese Interaktion zwischen dem Client und dem Server zum Aufbau der TLS-Verbindung wird als **<abbr title="TLS-Handschlag">TLS-Handshake</abbr>** bezeichnet. |
|||
|
|||
### TLS mit SNI-Erweiterung |
|||
|
|||
**Nur ein Prozess** im Server kann an einem bestimmten **Port** einer bestimmten **IP-Adresse** lauschen. Möglicherweise gibt es andere Prozesse, die an anderen Ports dieselbe IP-Adresse abhören, jedoch nur einen für jede Kombination aus IP-Adresse und Port. |
|||
|
|||
TLS (HTTPS) verwendet standardmäßig den spezifischen Port `443`. Das ist also der Port, den wir brauchen. |
|||
|
|||
Da an diesem Port nur ein Prozess lauschen kann, wäre der Prozess, der dies tun würde, der **TLS-Terminierungsproxy**. |
|||
|
|||
Der TLS-Terminierungsproxy hätte Zugriff auf ein oder mehrere **TLS-Zertifikate** (HTTPS-Zertifikate). |
|||
|
|||
Mithilfe der oben beschriebenen **SNI-Erweiterung** würde der TLS-Terminierungsproxy herausfinden, welches der verfügbaren TLS-Zertifikate (HTTPS) er für diese Verbindung verwenden muss, und zwar das, welches mit der vom Client erwarteten Domain übereinstimmt. |
|||
|
|||
In diesem Fall würde er das Zertifikat für `someapp.example.com` verwenden. |
|||
|
|||
<img src="/img/deployment/https/https03.svg"> |
|||
|
|||
Der Client **vertraut** bereits der Entität, die das TLS-Zertifikat generiert hat (in diesem Fall Let's Encrypt, aber wir werden später mehr darüber erfahren), sodass er **verifizieren** kann, dass das Zertifikat gültig ist. |
|||
|
|||
Mithilfe des Zertifikats entscheiden der Client und der TLS-Terminierungsproxy dann, **wie der Rest der TCP-Kommunikation verschlüsselt werden soll**. Damit ist der **TLS-Handshake** abgeschlossen. |
|||
|
|||
Danach verfügen der Client und der Server über eine **verschlüsselte TCP-Verbindung**, via TLS. Und dann können sie diese Verbindung verwenden, um die eigentliche **HTTP-Kommunikation** zu beginnen. |
|||
|
|||
Und genau das ist **HTTPS**, es ist einfach **HTTP** innerhalb einer **sicheren TLS-Verbindung**, statt einer puren (unverschlüsselten) TCP-Verbindung. |
|||
|
|||
!!! tip "Tipp" |
|||
Beachten Sie, dass die Verschlüsselung der Kommunikation auf der **TCP-Ebene** und nicht auf der HTTP-Ebene erfolgt. |
|||
|
|||
### HTTPS-Request |
|||
|
|||
Da Client und Server (sprich, der Browser und der TLS-Terminierungsproxy) nun über eine **verschlüsselte TCP-Verbindung** verfügen, können sie die **HTTP-Kommunikation** starten. |
|||
|
|||
Der Client sendet also einen **HTTPS-Request**. Das ist einfach ein HTTP-Request über eine verschlüsselte TLS-Verbindung. |
|||
|
|||
<img src="/img/deployment/https/https04.svg"> |
|||
|
|||
### Den Request entschlüsseln |
|||
|
|||
Der TLS-Terminierungsproxy würde die vereinbarte Verschlüsselung zum **Entschlüsseln des Requests** verwenden und den **einfachen (entschlüsselten) HTTP-Request** an den Prozess weiterleiten, der die Anwendung ausführt (z. B. einen Prozess, bei dem Uvicorn die FastAPI-Anwendung ausführt). |
|||
|
|||
<img src="/img/deployment/https/https05.svg"> |
|||
|
|||
### HTTP-Response |
|||
|
|||
Die Anwendung würde den Request verarbeiten und eine **einfache (unverschlüsselte) HTTP-Response** an den TLS-Terminierungsproxy senden. |
|||
|
|||
<img src="/img/deployment/https/https06.svg"> |
|||
|
|||
### HTTPS-Response |
|||
|
|||
Der TLS-Terminierungsproxy würde dann die Response mithilfe der zuvor vereinbarten Kryptografie (als das Zertifikat für `someapp.example.com` verhandelt wurde) **verschlüsseln** und sie an den Browser zurücksenden. |
|||
|
|||
Als Nächstes überprüft der Browser, ob die Response gültig und mit dem richtigen kryptografischen Schlüssel usw. verschlüsselt ist. Anschließend **entschlüsselt er die Response** und verarbeitet sie. |
|||
|
|||
<img src="/img/deployment/https/https07.svg"> |
|||
|
|||
Der Client (Browser) weiß, dass die Response vom richtigen Server kommt, da dieser die Kryptografie verwendet, die zuvor mit dem **HTTPS-Zertifikat** vereinbart wurde. |
|||
|
|||
### Mehrere Anwendungen |
|||
|
|||
Auf demselben Server (oder denselben Servern) könnten sich **mehrere Anwendungen** befinden, beispielsweise andere API-Programme oder eine Datenbank. |
|||
|
|||
Nur ein Prozess kann diese spezifische IP und den Port verarbeiten (in unserem Beispiel der TLS-Terminierungsproxy), aber die anderen Anwendungen/Prozesse können auch auf dem/den Server(n) ausgeführt werden, solange sie nicht versuchen, dieselbe **Kombination aus öffentlicher IP und Port** zu verwenden. |
|||
|
|||
<img src="/img/deployment/https/https08.svg"> |
|||
|
|||
Auf diese Weise könnte der TLS-Terminierungsproxy HTTPS und Zertifikate für **mehrere Domains**, für mehrere Anwendungen, verarbeiten und die Requests dann jeweils an die richtige Anwendung weiterleiten. |
|||
|
|||
### Verlängerung des Zertifikats |
|||
|
|||
Irgendwann in der Zukunft würde jedes Zertifikat **ablaufen** (etwa 3 Monate nach dem Erwerb). |
|||
|
|||
Und dann gäbe es ein anderes Programm (in manchen Fällen ist es ein anderes Programm, in manchen Fällen ist es derselbe TLS-Terminierungsproxy), das mit Let's Encrypt kommuniziert und das/die Zertifikat(e) erneuert. |
|||
|
|||
<img src="/img/deployment/https/https.svg"> |
|||
|
|||
Die **TLS-Zertifikate** sind **einem Domainnamen zugeordnet**, nicht einer IP-Adresse. |
|||
|
|||
Um die Zertifikate zu erneuern, muss das erneuernde Programm der Behörde (Let's Encrypt) **nachweisen**, dass es diese Domain tatsächlich **besitzt und kontrolliert**. |
|||
|
|||
Um dies zu erreichen und den unterschiedlichen Anwendungsanforderungen gerecht zu werden, gibt es mehrere Möglichkeiten. Einige beliebte Methoden sind: |
|||
|
|||
* **Einige DNS-Einträge ändern**. |
|||
* Hierfür muss das erneuernde Programm die APIs des DNS-Anbieters unterstützen. Je nachdem, welchen DNS-Anbieter Sie verwenden, kann dies eine Option sein oder auch nicht. |
|||
* **Als Server ausführen** (zumindest während des Zertifikatserwerbsvorgangs), auf der öffentlichen IP-Adresse, die der Domain zugeordnet ist. |
|||
* Wie oben erwähnt, kann nur ein Prozess eine bestimmte IP und einen bestimmten Port überwachen. |
|||
* Das ist einer der Gründe, warum es sehr nützlich ist, wenn derselbe TLS-Terminierungsproxy auch den Zertifikats-Erneuerungsprozess übernimmt. |
|||
* Andernfalls müssen Sie möglicherweise den TLS-Terminierungsproxy vorübergehend stoppen, das Programm starten, welches die neuen Zertifikate beschafft, diese dann mit dem TLS-Terminierungsproxy konfigurieren und dann den TLS-Terminierungsproxy neu starten. Das ist nicht ideal, da Ihre Anwendung(en) während der Zeit, in der der TLS-Terminierungsproxy ausgeschaltet ist, nicht erreichbar ist/sind. |
|||
|
|||
Dieser ganze Erneuerungsprozess, während die Anwendung weiterhin bereitgestellt wird, ist einer der Hauptgründe, warum Sie ein **separates System zur Verarbeitung von HTTPS** mit einem TLS-Terminierungsproxy haben möchten, anstatt einfach die TLS-Zertifikate direkt mit dem Anwendungsserver zu verwenden (z. B. Uvicorn). |
|||
|
|||
## Zusammenfassung |
|||
|
|||
**HTTPS** zu haben ist sehr wichtig und in den meisten Fällen eine **kritische Anforderung**. Die meiste Arbeit, die Sie als Entwickler in Bezug auf HTTPS aufwenden müssen, besteht lediglich darin, **diese Konzepte zu verstehen** und wie sie funktionieren. |
|||
|
|||
Sobald Sie jedoch die grundlegenden Informationen zu **HTTPS für Entwickler** kennen, können Sie verschiedene Tools problemlos kombinieren und konfigurieren, um alles auf einfache Weise zu verwalten. |
|||
|
|||
In einigen der nächsten Kapitel zeige ich Ihnen einige konkrete Beispiele für die Einrichtung von **HTTPS** für **FastAPI**-Anwendungen. 🔒 |
Loading…
Reference in new issue