Wofür benötige ich ein Zertifikat?
SSL Zertifikate sorgen dafür, dass die Daten zwischen dem Browser und dem Internetdienst oder der Webseite verschlüsselt übertragen werden und während der Übertragung nicht verändert werden oder mitgelesen werden können. Wenn man sich auf einem Onlineshop zum Beispiel in sein Kundenkonto einloggen will, möchte man ja nicht, dass jemand den Verkehr abfängt und meine Daten dann nutzen kann und wenn ihr zum Beispiel krserv.de aufruft, dann wollt ihr ja auch nicht, dass ihr auf eine andere Seite geleitet werdet, die so aussieht wie meine, aber jemand anderes dahinter steckt, der Böses im Schilde führt. Deshalb sollte man immer darauf achten, ob der Browser eine Zertifikatswarnung ausgibt, oder ein Hinweis in der Adressleiste des Browsers zu sehen ist.
Vorraussetzungen
Bevor wir nun loslegen und ein Zertifikat erstellen, gibt es noch ein paar Vorraussetzungen. Es muss ein Webserver (z.B. Apache oder Nginx) bereits laufen und über HTTP (Port 80) erreichbar sein. In meinem Beispiel nutze ich Nginx. Es sollte auch bereits eine Domain eingerichtet sein und ein A/AAAA Record zeigt auf die IP Adresse des Servers. Diese HTTP Verbindung wird benötigt, um mit acme.sh Zertifikate zu erstellen und damit sichergestellt ist, dass die Domain auch zum Server gehört.
acme.sh installieren und Zertifikate erstellen
Ich nutze schon seit geraumer Zeit acme.sh, da dies ein Let’s Encrypt Client ist, der rein als Bash-Skript läuft und daher auch keinerlei Abhängigkeiten benötigt. Das macht die Sache dann später recht einfach. Die Einrichtung mache ich als root User, indem ich als erstes den Nutzer mit sudo su wechsel.
Schritt 1: Unprivilegierten Benutzer anlegen
acme.sh sollte aus Sicherheitsgründen nicht mit Root-Rechten ausgeführt werden. Daher legen wir uns zunächst einen dedizierten, unprivilegierten User an.
adduser letsencrypt
Code-Sprache: Bash (bash)
Wir werden nach einem Passwort gefragt. Wir drücken hier einfach mehrfach [Enter], um kein Passwort zu vergeben. Alle weiteren Angaben können wir ebenfalls mit [Enter] überspringen.
Damit der User später auf die Web-Verzeichnisse zugreifen kann, fügen wir ihn zur Gruppe des Webservers hinzu (hier www-data für Debian/Ubuntu-Systeme).
usermod -a -G www-data letsencrypt
Code-Sprache: Bash (bash)
Der neue User muss nach der Zertifikatserneuerung den Webserver neu laden können, ohne dafür ein Passwort zu benötigen. Dies erledigen wir mit visudo.
visudo
Code-Sprache: Bash (bash)
Wir fügen am Ende der Datei die folgende Zeile hinzu und speichern die Änderung:
letsencrypt ALL=NOPASSWD: /bin/systemctl reload nginx.service
Code-Sprache: Bash (bash)
Der Befehl muss natürlich angepasst werden, wenn ein anderer Webserver genutzt wird.
Schritt 2: acme.sh installieren
Nun beginnen wir mit der Installation von acme.sh. Als erstes wechseln wir zum User Letsencrypt:
su - letsencrypt
Code-Sprache: Bash (bash)
Für die Installation, nutzen wir ein Script. Die Mailadresse wird für Benachrichtigungen von Letsencrypt genutzt. Zusammen mit der Installation wird auch automatisch ein Cronjob eingerichtet, für die automatische Verlängerung der Zertifikate. Die Installation starten wir mit folgendem Befehl:
curl https://get.acme.sh | sh -s email=deine-email@beispieldomain.de
Code-Sprache: Bash (bash)
Anschließend wechseln wir mit exit wieder den Benutzer.
Schritt 3: Verzeichnisse und Webserver vorbereiten
Damit Letsencrypt überprüfen kann, dass es sich um deine Domain handelt, müssen wir folgendes Verzeichnis erstellen:
mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
Code-Sprache: Bash (bash)
Als nächstes erstellen wir die Verzeichnisse für die Zertifikate und setzen die entsprechenden Berechtigungen für den Webserver www-data. Da Letsencrypt dieser Gruppe angehört, kann es später auch darauf zugreifen.
mkdir -p /etc/letsencrypt/beispieldomain.de/rsa
mkdir -p /etc/letsencrypt/beispieldomain.de/ecc
chown -R www-data:www-data /var/www/letsencrypt
chown -R www-data:www-data /etc/letsencrypt
chmod -R 775 /var/www/letsencrypt
chmod -R 775 /etc/letsencrypt
Code-Sprache: Bash (bash)
Noch ein wichtiger Hinweis, an dieser Stelle. Der Webserver (z.B. Nginx) muss so konfiguriert sein, dass Anfragen an http://beispieldomain.de/.well-known/acme-challenge/ auf das Verzeichnis /var/www/letsencrypt/.well-known/acme-challenge/ zeigen. Dies erledigen wir bei Nginx mit folgendem Eintrag im Block für http (Port 80):
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
Code-Sprache: Nginx (nginx)
Schritt 4: acme.sh konfigurieren
Wir wechseln nun zum User Letsencrypt und legen für acme.sh einen Standardprovider für unsere Zertifikate fest.
su - letsencrypt
Code-Sprache: Bash (bash)
acme.sh --set-default-ca --server letsencrypt
Code-Sprache: Bash (bash)
Wir bleiben nun beim User Letsencrypt und erstellen nun unsere Zertifikate. Als erstes erstellen wir das RSA-Zertifikat (4096-Bit):
acme.sh --issue \-d beispieldomain.de \-d www.beispieldomain.de \--server letsencrypt \--keylength 4096 \-w /var/www/letsencrypt \--key-file /etc/letsencrypt/beispieldomain.de/rsa/key.pem \--ca-file /etc/letsencrypt/beispieldomain.de/rsa/ca.pem \--cert-file /etc/letsencrypt/beispieldomain.de/rsa/cert.pem \--fullchain-file /etc/letsencrypt/beispieldomain.de/rsa/fullchain.pem \--reloadcmd "sudo /bin/systemctl reload nginx.service"
Code-Sprache: Bash (bash)
Als nächstes erstellen wir das ECC-Zertifikat (ec-384):
acme.sh --issue \-d beispieldomain.de \-d www.beispieldomain.de \--server letsencrypt \--keylength ec-384 \-w /var/www/letsencrypt \--key-file /etc/letsencrypt/beispieldomain.de/ecc/key.pem \--ca-file /etc/letsencrypt/beispieldomain.de/ecc/ca.pem \--cert-file /etc/letsencrypt/beispieldomain.de/ecc/cert.pem \--fullchain-file /etc/letsencrypt/beispieldomain.de/ecc/fullchain.pem \--reloadcmd "sudo /bin/systemctl reload nginx.service"
Code-Sprache: Bash (bash)
Vergesst natürlich nicht, beispieldomain.de durch eure Domain auszutauschen und zum Ende wechseln wir wieder vom User Letsencrypt weg mit exit.
Nun haben wir die Zertifikate erstellt, aber wir sind noch nicht ganz fertig. Es gibt noch einen weiteren Schritt für die Sicherheit der SSL Verbindung mit unserem Server: der Diffie-Hellman-Parameter.
Was ist das und wozu brauchen wir das?
Stellen wir uns die Verschlüsselung wie ein sehr sicheres Türschloss vor. Unser SSL-Zertifikat ist der passende, einzigartige Schlüssel. Der Diffie-Hellman-Algorithmus ist quasi der Mechanismus, mit dem sich der Browser und unser Server sicher auf einen gemeinsamen Sitzungsschlüssel einigen, bevor überhaupt Daten fließen. Dieser Sitzungsschlüssel ist nur für die aktuelle Verbindung gültig.
Das Gute daran ist das Prinzip der „Forward Secrecy“ (Vorwärtsgeheimnis). Selbst wenn jemand in der Zukunft unseren privaten SSL-Schlüssel stehlen sollte, kann er damit nicht den Datenverkehr aus der Vergangenheit entschlüsseln, der mit diesen einmaligen Sitzungsschlüsseln gesichert war.
Warum sollten wir eigene Parameter erstellen?
Viele Webserver, auch Nginx, verwenden standardmäßig vorinstallierte, oft kürzere Diffie-Hellman-Parameter (z. B. 1024 oder 2048 Bit). Diese sind zwar praktisch, aber potenziell anfälliger für Angriffe, da sie weit verbreitet und bekannt sind.Indem wir unsere eigenen, längeren (z. B. 4096 Bit) und damit einzigartigen DH-Parameter erstellst, erhöhen wir die Sicherheit dieses „Handshakes“ erheblich. Wir bauen uns sozusagen ein individuelles, hochsicheres Schließsystem für die Schlüsselübergabe, das Angreifern das Leben extrem schwer macht.
Kurz gesagt: Mit unseren acme.sh-Zertifikaten sichern wir, dass die Verbindung verschlüsselt ist. Mit unseren eigenen DH-Parametern stellen wir sicher, dass die Aushandlung dieser Verschlüsselung so sicher wie möglich abläuft.
Die Erstellung der eigenen Parameter ist ganz einfach, kann aber je nach Leistung des Servers einen Moment dauern.
Als erstes erstellen wir den Ordner wo die Datei abgespeichert werden soll:
mkdir -p /etc/nginx/dhparams
Code-Sprache: Bash (bash)
Dann beginnen wir mit der Erstellung:
openssl dhparam -out /etc/nginx/dhparams/dhparams.pem 4096
Code-Sprache: Bash (bash)
Das war es auch schon. Nun habt ihr eure Zertifikate und eine zusätzliche Sicherheit der verschlüsselten Übertragung, welche ihr in eure Webserver-Konfiguration angeben könnt, um HTTPS (Port 443) zu nutzen:
# SSL configuration
# RSA certificates
ssl_certificate /etc/letsencrypt/beispieldomain.de/rsa/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/beispieldomain.de/rsa/key.pem;
# ECC certificates
ssl_certificate /etc/letsencrypt/beispieldomain.de/ecc/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/beispieldomain.de/ecc/key.pem;
# This should be ca.pem (certificate with the additional intermediate certificate)
# See here: https://certbot.eff.org/docs/using.html
# ECC
ssl_trusted_certificate /etc/letsencrypt/beispieldomain.de/ecc/ca.pem;
# Die folgenden Zeilen können auch zentral für mehrere Hosts angelegt werden.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384';
# Diffie-Hellman parameter for DHE ciphersuites, recommended 4096 bits
ssl_dhparam /etc/nginx/dhparams/dhparams.pem;
ssl_ecdh_curve secp521r1:secp384r1;
# Server should determine the ciphers, not the client
ssl_prefer_server_ciphers on;
# SSL session handling
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
Code-Sprache: Nginx (nginx)
Wenn ihr mehrere Domains mit Nginx verarbeitet, könnt ihr auch die Zeilen welche nach euren Zertifikaten kommen (TLS Version, Diffie-Hellman, SSL Handling, etc.) in eine Datei auslagern, sodass ihr die Zeilen nicht für jede einzelne Domain angeben müsst.
Als erstes erstellen wir das Verzeichnis:
mkdir -p /etc/nginx/snippets
Code-Sprache: Bash (bash)
Dort erstellen wir nun die Datei für die SSL Konfiguration, die wir für unsere aktuelle und alle weiteren Domains nutzen:
nano /etc/nginx/snippets/ssl.conf
Code-Sprache: Bash (bash)
Hier fügen wir nun die letzten Zeilen aus unserer obigen Konfiguration ein. Diese benötigen wir dann auch nur in der SSL.conf und können sie aus der domain.conf entfernen:
# Die folgenden Zeilen können auch zentral für mehrere Hosts angelegt werden.
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384';
# Diffie-Hellman parameter for DHE ciphersuites, recommended 4096 bits
ssl_dhparam /etc/nginx/dhparams/dhparams.pem;
ssl_ecdh_curve secp521r1:secp384r1;
# Server should determine the ciphers, not the client
ssl_prefer_server_ciphers on;
# SSL session handling
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
Code-Sprache: Nginx (nginx)
Die Datei fügen wir nun mit folgendem Befehl die Conf für unsere Domain unter die Zeilen wo wir unsere Zertifikate angeben:
include /etc/nginx/snippets/ssl.conf;
Code-Sprache: Bash (bash)
Wenn ihr jetzt eine neue Conf für eine weitere Domain erstellt, könnt ihr einfach mit include die Datei einfügen.
Wenn Fragen auftauchen sollten, schreibt mir einfach eine Mail an kontakt[at] krserv.de, oder schreibt einen Kommentar unter diesen Beitrag.
Schreibe einen Kommentar