Kostenloses SSL: Let's encrypt! (NGINX)


Neuer Blog -> Neue Technik. Warum den Blog nicht auch gleich via SSL ausliefern und endlich mal ein bisschen Sicherheit reinbringen?

SSL dient dazu die Daten zwischen Webserver und Client zu verschlüsseln, sodass kein Anderer auf dem Weg die Daten einfach so mitlesen kann.

Mittlerweile gehört es (anscheinend) zum guten Ton, sich ein bisschen Mühe zu geben und den Transportweg zu verschlüsseln. Für ein Privatprojekt sah ich es aber bisher nicht ein, Geld dafür zu bezahlen. Doch in den letzten Jahren fielen die Preise für die Zertifikate ziemlich in den Keller und mit Let's Encrypt gibt es nun endlich auch eine kostenlose Alternative.

Um die Zertifikate erstellen zu können, muss zuerst deren GitRepo ausgechecked werden und in's Verzeichnis gewechselt werden.

git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt

Dann muss das Tool nur noch mit den richtigen Parametern gestartet werden:
(Beim ersten Aufruf installiert das Script alle Dependencies und kompiliert notwendige Binaries.)

./letsencrypt-auto certonly --rsa-key-size 4096 -d flazer.de -d www.flazer.de

Mit -d können beliebig viele Domains hinzugefügt werden (laut Webseite liegt das derzeitige Maximum bei 100 pro Zertifikat).

Achtung: Damit Let's Encrypt überprüfen kann, ob die Domain auch wirklich auf den Server zeigt, bastelt es sich einen eigenen kleinen Host, der auf Port 80 lauscht. Dazu muss NGINX ausgeschaltet sein.

Ich hatte das Problem, dass beim Kompilieren von Python der Installer abbrach, da nicht genügend RAM auf meinem kleinen Server zur Verfügung stand und auch kein Swap vorhanden war.
Also kurz ein Ausflug in dieses Thema, falls da auch mal wer drüber stolpert:

sudo su
mkdir -p /var/cache/swap # Ordner erstellen
dd if=/dev/zero of=/var/cache/swap/swap0 bs=1M count=4096 # 4Gb große Datei erzeugen
chmod 0600 /var/cache/swap/swap0 # Rechte Anpassen: Keiner darf, außer root
mkswap /var/cache/swap/swap0 # Swap formatieren
swapon /var/cache/swap/swap0 # Swap einbinden
swapon -s # Zustand des Swaps überprüfen

Wenn alles geklappt hat, dann liegen nun unter /etc/letsencrypt/live/_DOMAIN_NAME/ vier Dateien:

  • cert.pem
  • chain.pem
  • fullchain.pem
  • privkey.pem

NGINX benötigt zwei der Zertifikatsdateien (fullchain.pem & privkey.pem) in der jeweiligen Serverkonfiguration.

server {
    listen 443 ssl default_server;
    server_name flazer.de;

    ssl_certificate /etc/letsencrypt/live/flazer.de/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/flazer.de/privkey.pem;

    ...
}

Danach muss der Webserver neugestartet werden:

/etc/init.d/nginx restart

Die Zertifikate sind allerdings nur 90 Tage gültig!
Da man jetzt nicht wirklich Bock hat, alle drei Monate neue, gültige Zertifikate erstellen zu müssen, kann man das auch super via Cron laufen lassen.
Also erstmal ein Script dafür zusammenschrauben:

#!/bin/sh
service nginx stop  # stop nginx
/opt/letsencrypt/letsencrypt-auto renew -nvv --standalone --agree-tos > /var/log/letsencrypt/renew.log 2>&1
LE_STATUS=$?
service nginx start # start nginx
if [ "$LE_STATUS" != 0 ]; then
    echo Automated renewal failed:
    cat /var/log/letsencrypt/renew.log
    exit 1
fi

Speichern kann man das natürlich wo man will. Ich hab's einfach zum "Rest" unter /opt/letsencrypt gelegt.
Zum Testen emfpiehlt es sich als Parameter noch --dry-run anzuhängen, um das Erstellen der Zertifikate lediglich zu simulieren. Dabei wird mit dem Stagingserver von Let's Encrypt gesprochen und die bereits erstellten Zertifikate nicht angefasst.
Den Krempel schreibt man dann noch in die crontab und lässt es jeden Monat einmalig laufen. Das Tool überprüft selbstständig, ob das Zertifikat demnächst abläuft und requested erst dann ein Neues:

sudo su
crontab -e
0 0 1 * * /opt/letsencrypt/auto-renewal.sh

Update:

Daniel wies mich darauf hin, dass ich beim Certtest auf SSLlabs lediglich ein B-Rating für meine SSL-Config bekomme. Und schickte mir eine Anleitung, um ein "A" zu erreichen:

openssl dhparam -out /etc/nginx/dhparams.pem 2048

Dann die Nginx-Config (/etc/nginx/nginx.conf) anpassen:

# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE

ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_dhparam /etc/nginx/dhparams.pem;

Nicht vergessen, Nginx neuzustarten, damit die Änderungen auch wirksam werden!

Jetzt ist alles cool und wir freuen uns!

Quellen:
letsencrypt.org/getting-started
wiki.ubuntuusers.de/Swap/
weakdh.org/sysadmin.html