TLS – Schritt für Schritt erklärt

Wenn eine URL wie z.B. https://example.com über den Browser aufgerufen wird, erfolgt dieser Aufruf verschlüsselt. Zuständig dafür ist die Transport Layer Security kurz TLS. Wie genau die Aushandlung von TLS funktioniert, kann sich Byte für Byte auf der Webseite tls.ulfheim.net angeschaut werden.

The Illustrated TLS Connection

Auf der Seite wird in aller Ausführlichkeit der Verbindungsaufbau von TLS erläutert. Dabei wird wie es die Seite verspricht, jedes einzelne Byte entsprechend erklärt. Das Projekt, dessen Quelltext auf GitHub zu finden ist, ist unter der MIT-Lizenz lizenziert und damit freie Software.

Let’s Encrypt unter Ubuntu und Nginx einrichten

Vor einigen Tagen habe ich damit begonnen alle von mir betriebenen Webseiten auf TLS umzustellen. Dabei nutzte ich Zertifikate der Zertifizierungsstelle Let’s Encrypt. Let’s Encrypt ging dabei im letzten Jahr in Betrieb und liefert kostenlose Zertifikate für TLS. Die CA wird dabei unter anderem von der EFF und Mozilla unterstützt. Im Gegensatz zu anderen Lösungen ist der Prozess bei Let’s Encrypt hochgradig automatisiert, so das die Einrichtung schnell von statten geht.

Der offizielle Client hört dabei auf den Namen Certbot (früher Let’s Encrypt Client) und implementiert das ACME-Protokoll (Automated Certificate Management Environment) über welches der Prozess abgewickelt wird. Neben dem offiziellen Client gibt es viele weitere Clients welche das ACME-Protokoll implementieren. Um Let’s Encrypt unter Ubuntu zu nutzen, muss im ersten Schritt der Client installiert werden:

apt-get install letsencrypt

Nachdem der Client installiert wurde, kann mit der Erzeugung der Zertifikate begonnen werden. Im Gegensatz zu Apache wird unter Nginx die automatische Einrichtung nicht unterstützt. Aus diesem Grund werden nur die Zertifikate mit dem Client erzeugt. Dies geschieht mit dem Befehl:

letsencrypt certonly

Damit wird der interaktive Modus gestartet in welchem das Zertifikat erzeugt werden kann. Zuerst wird nach einer Mailadresse gefragt, mit welcher das Recovery in Notfällen möglich ist. Anschließend müssen die allgemeinen Geschäftsbedingungen akzeptiert werden. Nun wird nach den Domains gefragt, für welche ein Zertifikat erstellt werden soll. Hier kann man mehrere Domains per Komma bzw. Leerzeichen getrennt angeben – allerdings scheint dies in der aktuellen Version nicht zu funktionieren. Stattdessen wird nur für die erste angegebene Domain ein Zertifikat erzeugt. Standardmäßig benötigt Certbot während der Generierung der Zertifikate Zugriff auf den Port 80. Hintergrund für dieses Verhalten ist das der Client kurz einen Webserver aufsetzt um die Kommunikation mit der CA durchzuführen.

Abgelegt werden die erzeugten Zertifikate dabei im Ordner /etc/letsencrypt/. In diesem Ordner liegen neben den Stammzertifikaten auch die eigentlichen Zertifikate für die einzelnen Domains. Nun kann dieses Zertifikat in Nginx eingebunden werden. Dazu muss die Konfigurationsdatei der jeweiligen Seite (z.B. /etc/nginx/sites-available/example) geöffnet werden. Im ersten Schritt wurde dazu in der Konfiguration eine Weiterleitung eingerichtet:

server {
        listen 80;
        listen [::]:80;

        server_name .example.org;

        return 301 https://$host$request_uri$is_args$args;
}

Diese Weiterleitung sorgt dafür das eine Verbindung über unverschlüsseltes HTTP automatisch auf die verschlüsselte Variante umgeleitet wird. Weiter geht es mit der Konfiguration der verschlüsselten Verbindung:

server {
        listen   443 ssl;
        listen [::]:443 ssl;

        ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;

        ...

Jedes erzeugte Zertifikat von Let’s Encrypt ist 90 Tage lang gültig, so das ein automatischer Prozess eingerichtet werden sollte um die Zertifikate automatisch zu erneuern. Mit dem Befehl:

letsencrypt renew --agree-tos

kann dabei der Erneuerungsprozess angestoßen werden. Möchte man das ganze ohne Risiko testen, so sollte der Parameter –dry-run angefügt werden.

letsencrypt renew --agree-tos --dry-run

Bei der Erneuerung der Zertifikate kann es nun vorkommen das man den Nginx-Server vorher beenden muss. Das ganze kann man in ein Skript gießen:

#!/bin/sh
service nginx stop
letsencrypt renew --agree-tos
service nginx start

Dieses Skript kann man nun zum Beispiel einmal in der Nacht per Cronjob ausführen. Der Client überprüft dabei ob eine Erneuerung notwendig ist und führt diese dann automatisch durch.

Certificate pinning im Browser

Beim sogenannten Certificate pinning werden Zertifikate, welche für die Verschlüsselung von Webseiten und anderen Diensten genutzt werden, lokal gespeichert. Dies hat den Vorteil, das dass Zertifikat nicht einfach unbemerkt durch ein anderes Zertifikat ausgetauscht werden kann und erschwert damit das abhören von SSL/TLS-Verbindungen.

Certificate Patrol
Preis: Kostenlos

Leider ist diese Funktionalität in den gängigen Browsern nicht vorhanden. Mit dem Firefox-AddOn Certificate Patrol kann man ein solches Certificate pinning im Browser nachrüsten. Zertifikate müssen dabei einmalig akzeptiert werden – anschließend wird man informiert, wenn sich das Zertifikat ändert. Damit ist es für einen Angreifer wesentlich schwieriger geworden, dem Nutzer falsche Zertifikate unterzuschieben.

SSL und TLS Zertifikate testen

Wer seine Domains mit Zertifikaten für SSL bzw. TLS ausgerüstet, um den Aufruf per HTTPS zu ermöglichen, fragt sich am Ende wie sinnvoll das ganze konfiguriert ist.

Eine Auswertung für heise.de

Eine Auswertung für heise.de

Mit dem SSL-Test von Qualys kann man das unter ssllabs.com/ssltest/ herausfinden. Nach dem Test erfolgt eine Auswertung, welche mit einer Gesamtnote bewertet wird. Anschließend finden sich in tabellarischer Form die Einzelergebnisse.

testssl.sh

Einen Server auf seine SSL-Fähigkeiten zu überprüfen ist für den Laien nicht ohne weiteres möglich. Durch das Bash-Skript testssl.sh sieht dies nun anders aus.

testssl.sh in Aktion

testssl.sh in Aktion

Das freie, unter der GPL2 lizenzierte Skript, dient dazu die Sicherheit der SSL-Implementation eines entfernten Servers zu testen. Die Syntax für den Test ist dabei einfach gehalten:

./testssl.sh example.com

Daneben verfügt “testssl.sh” über weitere Optionen, wie man der Dokumentation entnehmen kann. Dem Autor des Skriptes kann auf Twitter gefolgt werden.