Erste Schritte mit Let’s Encrypt

Let’s Encrypt ist eine neue Zertifizierungsstelle (CA) welche gratis Zertifikate ausstellt. Dieses ist vor einiger Zeit in die öffentliche Beta gegangen. Ich wurde aber schon zur geschlossenen Beta eingeladen weshalb mein Zertifikat unter den ersten 120 zu finden ist https://crt.sh/?id=11766203. Die CA stellt nur Zertifikate aus welche 90 Tage gültig sind, was einen dazu zwingt, den ganzen Vorgang zu automatisieren. Hat den Vorteil, man muss sich nicht mehr darum kümmern und alles passiert vollautomatisch mit viel Magie 🙂

Let’s Encrypt also lasst uns verschlüsseln

Es gibt viele Vorteile von Let’s Encrypt (LE) vor allem dass alles voll automatisiert passiert. Allerdings finde ich dass alte Zertifikat System etwas einfacher. Man sendete seinen Certificate Signing Request (CSR) an die CA welche einem eine Mail sendet, an die bei dem Domain Registrar hinterlegte Email und nach einer kurzen Überprüfung wird einem das Zertifikat erstellt. Bei LE muss man der CA vertrauen, dass sie keinen Unfug mit dem Code treibt. Bis ich dieses Zertifikat damals bekam, dauerte es mehrere Stunden. Es fehlt bis heute noch eine vernünftige Dokumentation über die Software. Da meine Seite mit HPKP abgesichert ist, muss ich hergehen und den vorhandenen Private Key nehmen.

Erstmal installieren wie den LE Client von Github https://github.com/letsencrypt/letsencrypt

git clone https://github.com/letsencrypt/letsencrypt.git
cd letsencrypt
./letsencrypt-auto --help

Jetzt kopieren wir die OpenSSL Konfiguration. Dies wird aber nur benötigt, wenn man mehrere Domains und Subdomains in einem Zertifikat haben möchtet.

cp /etc/ssl/openssl.cnf /etc/letsencrypt/example.com.cnf
nano /etc/letsencrypt/example.com.cnf

Tipp: Crtl+W in nano um nach [ req ] zu suchen und wir entfernen das # davor.

req_extensions = v3_req

Wir suchen nun nach [ v3_req ] und schreibe folgendes rein.

subjectAltName  =  @alt_names

Danach fügen wir wie unten gezeigt, alle Domains welche mit dem SAN/SNI Zertifikat abgedeckt werden sollen rein.

[ alt_names ]
DNS.1 = www.example.com
DNS.2 = cdn.example.com
DNS.3 = example.org
DNS.4 = www.example.org

Solltest du noch kein HPKP nutzen, kannst du hiermit dein Zertifikat erstellen.

openssl genrsa  -out example.com.key  4096

Nun erstellen wir den CSR und schauen ob alles stimmt.

openssl req -new -key example.com-0000.key -out example.com-0000.csr -config example.com.cnf
openssl req -in example.com-0000.csr -noout -text

##########################

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=XX, ST=XX, L=XXXX, O=XXXXXX, CN=example.com/emailAddress=admin@example.com
	[...]
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Key Usage:
                Digital Signature, Non Repudiation, Key Encipherment
            X509v3 Subject Alternative Name:
                DNS:example.com, DNS:www.example.com, DNS: cdn.example.com, DNS: example.org, DNS: www.example.org
	[...]

Wenn schon HPKP verwendet wird, können wir hiermit überprüfen ob die Hashsummen zu unseren alten und jenen in den Headern passen.

openssl req -in example.com.csr -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64

Der Server von Let’s Encrypt erwartet die Daten im DER Format. Da unsere noch im PEM sind, müssen wir diese einmal umwandeln und prüfen die Ausgabe.

openssl req -inform pem -in example.com.csr -out example.com.csr_der -outform der
openssl req -inform der -in example.com.csr_der -text

Nun richten wir Nginx so ein, das es die Anfragen vom Server auf Port 80 durchlässt.

nano /etc/nginx/sites-enabled/example.com

listen 80
location ~ /.well-known/acme-challenge/(.*) {
        root /PATH/TO/WEB/ROOT;
        default_type application/jose+json;
}

mkdir -p /PATH/TO/WEB/ROOT/.well-known/acme/challenge/

Nun kommt der spannende Teil: Wir senden alles zur CA zur Überprüfung.

./letsencrypt-auto --agree-tos -vvv --csr /etc/ssl/example.com/example.com.csr_der --webroot-path /PATH/TO/WEB/ROOT/ auth

Während der Überprüfung, wird man aufgefordert bestimmte Daten in /PATH/TO/WEB/ROOT/.well-known/acme-challgenge/ bereit zu stellen. Die erforderlichen Befehle liefert der Client, wir benötigen nur eine eigene zweite Bash um sie auszuführen.

Nun stellen wir Nginx noch richtig ein. Vorher noch die Datei erstellen welche für die Forward Secrecy zuständig ist.

openssl dhparam -out /etc/ssl/dhparam.pem 4096
server {
        listen 443 default ssl http2;
        listen [::]:443 default ssl http2;
        server_name example.com;
        ##############
        ssl on;
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/example.com/privkey.pem;
        ssl_dhparam /etc/ssl/dhparam.pem;

        ssl_stapling on;
        ssl_stapling_verify on;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

        ssl_session_timeout 5m;
        resolver 8.8.8.8 8.8.4.4 valid=300s;
        ssl_prefer_server_ciphers on;
        ssl_session_tickets off;
        ssl_session_cache shared:SSL:10m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

Let's Encrypt Zertifikat

Ihr solltet bei Qualys SSL Test nun ein A+ haben https://www.ssllabs.com/ssltest/

Hier könnt ihr auch euren Erfolg einmal testen https://ssldecoder.org/

Euer Zertifikat wird dann wie jedes andere hier zu finden sein https://crt.sh/?Identity=%25&iCAID=7395