HTTPS unter nginx/Ubuntu

Dieser Artikel zeigt Euch, wie man eine eigene Webseite unter Ubuntu Server 20.04 LTS mit Hilfe des nginx Web-Servers und Let’s Encrypt einfach und kostenlos mit HTTPS absichern kann.

Diskussion

Transport Layer Security (kurz TLS) ist ein Verschlüsselungsverfahren zum sicheren Übertragen von Daten über öffentliche Netzwerke. Bekannter ist es immer noch unter dem alten Namen SSL (Secure Sockets Layer). TLS ist die Grundlage für das Übertragungsprotokoll HTTPS, einer Erweiterung des HTTP-Protokolls, das die Übertragung von Daten verschlüsselt.

Wenn Du in Deinem Web-Browser eine Webseite aufrufst, dann wird sie dir entweder per HTTPS oder aber HTTP übermittelt. Du erkennst das am Präfix der URL. Lautet dieser http://, dann ist es eine HTTP-Verbindung, lautet er https://, dann ist es eine HTTPS-Verbindung.

Da HTTP-Verbindungen in allen modernen Web-Browsern mittlerweile als potentiell unsicher gekennzeichnet werden, gibt es kaum noch öffentliche Webseiten ohne HTTPS. Aber warum ist das so?

  1. HTTPS verschlüsselt den Datenverkehr zwischen dem Web-Browser des Anwenders und deiner Webseite. Niemand außer euch beiden kann also sehen, welche Daten ihr untereinander austauscht. Und was fast noch wichtiger ist, niemand kann diese Daten ändern. Der letzte Aspekt wird leider viel zu oft unterschätzt. Das Argument, dass die eigene Website nur statischen Inhalt anzeigt und keine Benutzerdaten erfragt, geht hier ins Leere. Stell dir vor, jemand fängt alle Anfragen für Deine Webseite ab und lenkt sie stattdessen auf eine andere Webseite mit kriminellem Inhalten um. Das ist nicht schön, mit HTTPS kannst Du dies zuverlässig unterbinden.

  2. Die Datenschutzgrundverordnung (DSGVO) verpflichtet Webseiten-Betreiber, das eigene Angebot nach dem aktuellen Stand der Technik zu schützen (siehe Art. 32 DSGVO Sicherheit der Verarbeitung). HTTPS als ein Baustein in der Sicherheitsarchitektur kann ohne Zweifel als aktueller Stand der Technik betrachtet werden.

  3. Die Unterstützung von HTTP/2 setzt in der Regel den Einsatz von TLS voraus.

  4. Die Google-Suche bewertet Webseiten mit HTTPS tendenziell höher als Webseiten ohne HTTPS. Das hat natürlich Auswirkung auf das Suchergebnis unter Google.

Wen das nicht überzeugt, dem sei die Webseite https://doesmysiteneedhttps.com ans Herz gelegt.

Die Nutzung von HTTPS für die eigene Webseite muss nichts kosten und kann mit sehr geringem Aufwand implementiert werden. Im weiteren Verlauf dieses Blog-Artikels zeige ich euch, wie einfach das gehen kann.

Let’s Encrypt

Die Grundlage von HTTPS sind TLS-Zertifikate, die von einer vertrauenswürdigen Zertifizierungsstelle ausgegeben werden. Let’s Encrypt (zu deutsch: Lasst uns verschlüsseln) ist eine Zertifizierungsstelle, die kostenlose TLS-Zertifikate anbietet. Diese sind nur drei Monate gültig und werden durch Automation regelmäßig erneuert. Hauptsponsoren dieses Projekts sind unter anderem die Electronic Frontier Foundation (EFF), die Mozilla Foundation, Facebook, Google Chrome und Cisco Systems.

Grundlage für die automatische Bereitstellung und Aktualisierung von Zertifikaten durch Let’s Encrypt ist das sogenannte ACME-Protokoll (Automatic Certificate Management Environment Protocol), ein standardisiertes Internetprotokoll, das unter anderem prüft, ob der Anfragende auch wirklich die Kontrolle über eine Domäne hat.

Als Betreiber einer oder mehrerer Webseiten benötigt man lediglich einen ACME-kompatiblen Client und schon kann man bei Let’s Encrypt neue TLS-Zertifikate erfragen, und das kostenlos. Klingt gut, oder?

Los geht’s

Voraussetzung:

Wir werden jetzt folgendes tun:

  1. Die aktuelle Stable-Version von nginx unter Ubuntu Server 20.04 LTS installieren und so konfigurieren, dass eine Webseite unter http://www.beispiel.de abrufbar ist.

  2. Den ACME-Client Certbot installieren und nginx so konfigurieren, dass unsere Webseite auch unter https://www.beispiel.de abrufbar ist.

  3. Die nginx-Konfiguration weiter absichern, indem wir veraltete Protokolle und kryptografische Verfahren deaktivieren.

nginx installieren

Der nginx Web-Server ist ein Open Source-Projekt der amerikanischen Firma F5 Networks und unter der BSD-Lizenz lizenziert. Ursprünglich ein Projekt des russischen Software-Entwicklers Igor Sysoev, um den wachsenden Skalierungsbedarf der russischen Suchmaschine Rambler abzusichern, ist nginx heute nach Apache der weltweit zweit populärste Web-Server im Einsatz. nginx wird besonders gern als Reverse Proxy und zur Lastenverteilung (Load balancer) eingesetzt, nicht selten auch in Kombination mit dem altehrwürdigen Apache Web-Server.

Die Installation des offiziellen Ubuntu-Pakets für nginx werden wir nicht nutzen, da diese Version veraltet ist. Solltest Du nginx bereits installiert haben, kannst Du die Installation mit folgendem Befehl wieder entfernen:

$ sudo apt remove nginx nginx-common nginx-full nginx-core

Wir wollen die aktuelle Stable-Version von nginx installieren. Dazu musst Du zunächst das apt-Repository von nginx in Deinem Ubuntu-Server registrieren:

$ echo "deb http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list

Als nächstes musst Du den offiziellen nginx-Signaturschlüssel importieren. Dieser wird für die Überprüfung des Installationspakets aus dem soeben registrierten apt-Repository benötigt.

$ wget http://nginx.org/keys/nginx_signing.key | sudo apt-key add nginx_signing.key

Ist es auch der richtige Signaturschlüssel?

$ sudo apt-key fingerprint ABF5BD827BD9BF62

Das Ergebnis sollte so aussehen:

pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]
      573B FD6B 3D8F BC64 1079  A6AB ABF5 BD82 7BD9 BF62
uid           [ unknown] nginx signing key <signing-key@nginx.com>

Jetzt kannst Du nginx installieren:

$ sudo apt update && sudo apt install nginx

Der erste Befehl aktualisiert die Paketlisten auf unserem Ubuntu-Server, der zweite Befehl installiert nginx mit all seinen Abhängigkeiten.

Zum Starten von nginx tippe folgendes ein:

$ sudo systemctl start nginx

Für einen Autostart beim Booten Deines Servers tippe folgendes ein:

$ sudo systemctl enable nginx

nginx installiert eine Standard-Webseite, die auf alle HTTP-Anfragen reagiert.

Überprüfe dies zunächst lokal:

$ wget -S --spider localhost

Läuft nginx, dann bekommst Du eine Meldung wie diese hier:

Spider mode enabled. Check if remote file exists.
--2021-12-08 16:39:00--  http://localhost/
Resolving localhost (localhost)... ::1, 127.0.0.1
Connecting to localhost (localhost)|::1|:80... failed: Connection refused.
Connecting to localhost (localhost)|127.0.0.1|:80... connected.
HTTP request sent, awaiting response...
  HTTP/1.1 200 OK
  Server: nginx/1.20.2
  Date: Wed, 08 Dec 2021 15:39:00 GMT
  Content-Type: text/html
  Content-Length: 612
  Last-Modified: Tue, 16 Nov 2021 14:44:02 GMT
  Connection: keep-alive
  ETag: "6193c3b2-264"
  Accept-Ranges: bytes
Length: 612 [text/html]
Remote file exists and could contain further links,
but recursion is disabled -- not retrieving.

Für einen externen Test öffne die URL http://www.beispiel.de in Deinen Web-Browser. Das Ergebnis sollte wie folgt aussehen:

nginx Standard-Webseite

nginx Standard-Webseite

Eine neue Webseite anlegen

Schauen wir uns zunächst die Installation von nginx genauer an:

  • Alle Konfigurationsdateien liegen standardmäßig unter /etc/nginx/.

  • Die Standardkonfigurationsdatei lautet /etc/nginx/nginx.conf.

  • Alle Konfigurationsdateien mit der Dateiendung .conf, die im Unterverzeichnis /etc/nginx/conf.d/ liegen, werden automatisch unterhalb des http-Blocks in die Standardkonfigurationsdatei /etc/nginx/nginx.conf eingebettet. Mit anderen Worten, für jede neue Webseite sollte man im Unterverzeichnis /etc/nginx/conf.d/ eine extra Konfigurationsdatei anlegen.

  • Die Konfiguration der Standard-Webseite aus dem vorherigen Abschnitt ist in der Datei /etc/nginx/conf.d/default.conf gespeichert.

  • Die Log-Datei für die Fehleranalyse liegt unter /var/log/nginx/error.log.

Wir möchten jetzt unsere eigene Webseite mit der Bindung http://www.beispiel.de anlegen. Die Standardwebseite von nginx besitzt ja eine Catch-All-Konfiguration, und die lässt sich nicht wirklich auf https umstellen.

Zunächst kopierst Du die Standard-Webseite:

$ sudo cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/de.beispiel.conf

Anschließend öffnest Du die Datei:

$ sudo nano /etc/nginx/conf.d/de.beispiel.conf

Dort änderst Du den folgenden Bereich

server {
    listen       80;
    server_name  localhost;

wie folgt ab:

server {
    listen       80;
    server_name  www.beispiel.de;

Speichere Deine Änderung und starte nginx neu:

$ sudo systemctl restart nginx

Wir haben jetzt einen neuen Webseite (einen sogenannten Virtual Host) für die Domäne www.beispiel.de angelegt. Da wir faul sind, haben wir dieselbe HTML-Seite verwendet, wie die Standard-Webseite von nginx. Ein erneuter Test mit http://www.beispiel.de in Deinen Web-Browser sollte also wieder die Standardausgabe von nginx zeigen.

Certbot installieren

Damit unsere Webseite auch unter https://www.beispiel.de erreichbar ist, benötigen wir jetzt ein weiteres Werkzeug namens Certbot. Certbot ist ein Open Source Werkzeug zum automatisierten Erzeugen von TLS-Zertifikaten durch Let’s Encrypt.

Eine Installation unter Ubuntu geht wie folgt:

$ sudo apt install certbot python3-certbot-nginx

Und dann kann es auch schon losgehen. Mit dem folgenden Befehl können wir das HTTPS-Protokoll für unsere Beispielseite aktivieren:

$ sudo certbot --nginx

Beim aller ersten Einsatz von Certbot musst Du zunächst ein paar Fragen beantworten. Certbot fragt Dich nach Deiner E-Mail-Adresse zur Registrierung bei Let’s Encrypt. Bei Problemen (z.B. bei nicht durchgeführter Erneuerung eines Zertifikats) oder Missbrauch wirst Du automatisch von Let’s Encrypt per E-Mail benachrichtigt.

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel):

Anschließend möchte Certbot, dass Du Dir die Nutzungsbedingungen (Terms of Service) von Let’s Encrypt durchliest und diesen zustimmst.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
agree in order to register with the ACME server at
https://acme-v02.api.letsencrypt.org/directory
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(A)gree/(C)ancel:

Die nächste Frage kann man getrost mit No beantworten.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: n

Und jetzt kommt der interessante Teil. Certbot listet nun alle Webseiten unter nginx auf und Du musst entscheiden, bei welchen Du HTTPS aktivieren möchtest. In unserem Beispiel wird nur eine Webseite angezeigt, nämlich unsere zuvor eingerichtete Seite www.beispiel.de:

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: www.beispiel.de
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

Bestätige mit der Eingabetaste und Certbot beginnt damit, ein neues TLS-Zertifikat von Let’s Encrypt zu erfragen. Das sieht dann in etwa so aus.

Obtaining a new certificate
Performing the following challenges:
http-01 challenge for www.beispiel.de
Waiting for verification...
Cleaning up challenges
Deploying Certificate to VirtualHost /etc/nginx/conf.d/de.beispiel.conf

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

Während des Konfigurationsvorgangs wirst Du gefragt, ob Du eine automatische Umleitung von http auf https einrichten möchtest. In der Regel kann man hier mit 2 antworten.

Die Konfiguration schließt mit folgenden Meldungen ab:

Redirecting all traffic on port 80 to ssl in /etc/nginx/conf.d/de.beispiel.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://www.beispiel.de

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=www.beispiel.de
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/www.beispiel.de/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/www.beispiel.de/privkey.pem
   Your cert will expire on 2021-05-25. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - Your account credentials have been saved in your Certbot
   configuration directory at /etc/letsencrypt. You should make a
   secure backup of this folder now. This configuration directory will
   also contain certificates and private keys obtained by Certbot so
   making regular backups of this folder is ideal.
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Certbot hat folgendes gemacht:

  • Eine neue Datei /etc/letsencrypt/options-ssl-nginx.conf angelegt, in der globale TLS-Einstellungen für potentiell alle Webseiten hinterlegt sind.

  • Die TLS-Konfiguration für unsere Beispielseite in der Datei /etc/nginx/conf.d/de.beispiel.conf hinterlegt. Dort sind auch Verweise auf die TLS-Zertifikate sowie ein Verweis auf die globale TLS-Einstellungen definiert.

  • Einen CronJob unter /etc/cron.d/certbot eingerichtet, der zweimal am Tag die TLS-Zertifikate überprüft. Liegt das Ablaufdatum für ein TLS-Zertifikat weniger als 30 Tage in der Zukunft, wird es automatisch erneuert.

Ein erster Test mit https://www.beispiel.de in Deinem Web-Browser sollte die gewohnte Standard-Webseite von nginx anzeigen. Ein zweiter Test mit http://www.beispiel.de sollte erfolgreich auf https://www.beispiel.de umleiten.

TLS absichern

Wer sich die Ausgabe von Certbot genau anschaut, entdeckt die folgende Infozeile:

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=www.beispiel.de

Und genau das machen wir jetzt auch. SSL Labs ist eine Webseite, welche die TLS-Konfiguration für eine beliebige öffentliche Webseite überprüfen kann.

Für unsere Beispielseite www.beispiel.de gibt SSL Labs folgendes Ergebnis aus:

nginx frisch installiert

nginx frisch installiert

Das sieht natürlich nicht so prickelnd aus. Die Probleme hier sind:

  1. Uralte TLS-Versionen 1.0 und 1.1. Diese sollten dringend deaktiviert werden.

  2. Zahlreiche veraltete kryptographische Verfahren, die von SSL Lab als unsicher (weak) markiert werden.

Wir müssen also nocheinmal ran an die nginx-Konfiguration, um unseren Web-Server besser zu schützen.

$ sudo nano /etc/letsencrypt/options-ssl-nginx.conf

Damit öffnen wir die globale TLS-Konfigurationsdatei. Die Frage ist nun, was genau müssen wir denn jetzt ändern? Hier kann uns das Mozilla-Projekt helfen. Unter der folgenden Webseite

https://ssl-config.mozilla.org/

findest Du einen SSL Configuration Generator für nginx (und andere Web-Server).

Wir wählen für unser Beispiel die Konfiguration nginx und Intermediate aus und kopieren die relevanten Teile der generierten Konfiguration in unsere bereits geöffnete Konfigurationsdatei. Das könnte dann so aussehen:

ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

Speichere die Datei options-ssl-nginx.conf und starte nginx neu:

$ sudo systemctl restart nginx

Ein abschließender Test unter SSL Labs ergibt nun folgendes Bild:

nginx abgesichert

nginx abgesichert

Auch die zusammenfassende Bewertung von SSL Lab sieht jetzt richtig gut aus:

Ein A+ Rating für unsere Webseite

Ein A+ Rating für unsere Webseite

HTTP/2

Die Konfiguration von HTTPS unter nginx hat noch einen weiteren angenehmen Nebeneffekt. nginx unterstützt in diesem Fall das HTTP/2-Protokoll. Alle modernen Web-Browser haben diesen Protokollstandard bereits implementiert und können daher ab sofort per HTTP/2 mit deiner Webseite kommunizieren. Allerdings muss Du dafür Deine Konfiguration noch einmal anpassen, da das nginx-Plugin von Certbot HTTP/2 noch nicht unterstützt:

$ sudo nano /etc/nginx/conf.d/de.beispiel.conf

Dort änderst Du folgende Einstellung

listen 443 ssl;

wie folgt ab:

listen 443 ssl http2;

Speichere Deine Änderung und starte nginx neu:

$ sudo systemctl restart nginx

Voilà. Deine Webseite sollte jetzt auch auf http/2-Anfragen antworten.

Artikelhistorie

  • 25.02.2021
    • Erstveröffentlichung
  • 02.07.2021
    • Zusätzlicher Hinweis auf sites-available und sites-enabled.
  • 08.12.2021
    • Update auf Ubuntu Server 20.04 LTS
    • Einige zusätzliche Infos und kleinere Korrekturen
Das könnte dich auch interessieren:
  1. HTTPS unter Apache/Ubuntu
  2. Postfix unter Ubuntu-Server
  3. PostgreSQL 14 unter Ubuntu-Server
  4. UniFi Network Controller unter Ubuntu
  5. Ubuntu Server 18.04 installieren
Teile diesen Artikel
comments powered by Disqus