In diesem Artikel wird dokumentiert, wie ein Let’s Encrypt[1. https://letsencrypt.org/ {en}] [2. Let’s Encrypt – Wikipedia] Zertifikat für ejabberd eingerichtet werden kann. Dabei stütze ich mich auf mein TLS-Kochbuch[3. TLS/SSL Kochbuch: Rezepte für die Verwendung von OpenSSL, HTTP Strict Transport Security (HSTS) und HTTP Public Key Pinning (HPKP)].
Die Dokumentation bezieht sich dabei auf meine konkrete Installation und ist nicht ohne Transferleistung auf andere Installationen übertragbar. Es ist also keine Schritt-für-Schritt-Anleitung! Der Artikel bietet über die Dokumentation hinaus jedoch auch Hintergrundinformationen und Wissenswertes für abweichende Konfigurationen.
Ausgangssituation
In meiner Umgebung ist ejabberd auf einem Ubuntu Server 14.04 LTS[4. Trusty Tahr – wiki.ubuntuusers.de] installiert und nutzt ein TLS-Zertifikat von CAcert[5. https://www.cacert.org/ {en}] [6. CAcert – Wikipedia].
Außer ejabberd läuft auf dem Server auch noch ein Webserver, welcher verschiedene Webseiten ausliefert.
Daneben ist bereits der Let’s Encrypt Client acme-tiny[7. Fork des acme-tiny Clients auf GitHub {en}] installiert, dessen Verwendung in Abschnitt 3.6.2 TLS-Kochbuch erläutert wird.
Der Ablauf im Überblick
Wie vorstehend bereits erwähnt, verwendet ejabberd bereits ein TLS-Zertifikat, welches nun durch ein Let’s Encrypt Zertifikat ersetzt werden soll. Der Ablauf gliedert sich dabei im Wesentlichen in zwei Teile. Zuerst wird ein Let’s Encrypt Zertifikat für den Hostnamen des ejabberd-Servers ausgestellt. Anschließend wird ejabberd konfiguriert, um zukünftig dieses Zertifikat zu nutzen.
Zur Durchführung der Domainvalidierung wird ein VirtualHost für den Hostnamen des ejabberd-Servers konfiguriert. Da sich die genaue Konfiguration je nach verwendeter Webserver-Software unterscheidet, wird hier nicht näher darauf eingegangen, sondern auf die Dokumentation des jeweiligen Webservers verwiesen.
Generierung des TLS-Zertifikats
Nun wird mit Hilfe von OpenSSL[8. OpenSSL: Cryptography and SSL/TLS Toolkit {en}] [9. OpenSSL – Wikipedia] ein privater Schlüssel und eine Zertifikatsanfrage (engl. Certificate Signing Request (CSR)) erstellt. Beide Schritte werden ausführlich in Abschnitt 3.1 TLS-Kochbuch beschrieben.
Ich persönlich generiere den privaten Schlüssel und den CSR stets offline auf einem sicheren Computer. Anschließend lade ich sie zum Server hoch. Die Zugriffsrechte auf den Schlüssel sind so eingeschränkt, dass nur root und der Benutzer, unter dem der Webserver ausgeführt wird, diesen Schlüssel lesen dürfen.
Da bereits eine Installation von acme-tiny auf dem Server existiert und bereits ein Account-Key erstellt wurde, wird dieser in dem Verzeichnis verlinkt, in dem auch der private Schlüssel und der CSR liegen.
Nun kann das TLS-Zertifikat angefordert werden. Wie dies im Detail funktioniert, wird in Abschnitt 3.6.2 im TLS-Kochbuch beschrieben.
Sind bis hier alle Schritte erfolgreich gewesen, liegen nun Schlüssel und Zertifikat in einem Verzeichnis vor.
$ python acme-tiny/acme_tiny.py --account-key /var/www/sites/ssl/account.key --csr /var/www/sites/ssl/request.csr --acme-dir /var/www/sites/public/.well-known/acme-challenge/ > /var/www/sites/ssl/cert.crt
Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying fqdn...
fqdn verified!
Signing certificate...
Certificate signed!
$ ls -l /var/www/sites/ssl/
-rw-r—– 4 root root account.key
-rw-r—– 1 root www-data cert.crt
-rw-r—– 1 root root priv.key
-rw-r—– 1 root root request.csr
Zertifikat für ejabberd präparieren
Der Dienst ejabberd erwartet, dass der private Schlüssel, das Zertifikat und die Zertifikatskette in einer Datei übergeben werden.[10. Ejabberd SSL Certificate – Raymii.org {en}] Dazu wird noch die Zertifikatskette von Let’s Encrpyt[11. Let’s Encrypt: Chain of Trust {en}] heruntergeladen und ebenfalls in /var/www/sites/ssl/ gespeichert.
Das folgende Skript zeigt, wie das Zertifikat erzeugt, die Zertifikatsdatei für ejabberd zusammengesetzt und der Dienst neugestartet wird:
#!/bin/bash
# Datum: 2016-11-13
# Autor: Joerg Kastning <webmaster(aet)my-it-brain(Punkt)de>
#
# Beschreibung:
# Dieses Skript dient der Erneuerung des TLS-Zertifikats fuer
# jabber.my-it-brain.de über Let's Encrypt mit dem Client acme-tiny-by-frezbo.
DIR='/var/www/sites/ssl'
# Erneuerung des Zertifikats
python acme-tiny-by-frezbo/acme_tiny.py --account-key ${DIR}/account.key --csr ${DIR}/request.csr --acme-dir /var/www/sites/fqdn/.well-known/acme-challenge/ > ${DIR}/cert.crt
# Erzeugung der Zertifikatsdatei fuer ejabberd
cat ${DIR}/priv.key ${DIR}/cert.crt ${DIR}/lets-encrypt-x3-cross-signed.pem >${DIR}/ejabberd_cert.pem
sudo chown root:ejabberd ${DIR}/ejabberd_cert.pem
sudo chmod 0640 ${DIR}/ejabberd_cert.pem
sudo mv ${DIR}/ejabberd_cert.pem /etc/ejabberd/ejabberd_cert.pem
# Neustart von ejabberd
sudo service ejabberd restart
Abschluss der Migration
Durch den im vorangegangenen Abschnitt dargestellten Code wird das neue Let’s Encrypt Zertifikat an der gleichen Stelle und unter dem gleichen Dateinamen wie das alte Zertifikat abgelegt. Auf diese Weise muss die Konfiguration von ejabberd nicht weiter angepasst werden. Der Dienst lädt nach einem Neustart das neue Zertifikat. Die Migration ist damit abgeschlossen.
Let’s Encrypt Zertifikate besitzen eine Gültigkeit von 90 Tagen.[12. Let’s Encrypt: Why ninety-day lifetimes for certificates? {en}] Um die Erneuerung des Zertifikats zu automatisieren, wird das Skript „SmartRenew.sh“ verwendet (siehe Abschnitt 5.4 im TLS-Kochbuch).
Quellen und weiterführende Links:
Hallo,
ich finde deinen Artikel schön und auch handlich. Leider habe ich noch eine Frage dazu:
Zuhause habe ich bei mir eine ähnliche Kombination am Laufen, habe aber immer das Problem, dass das Zertifikat von den Clients nicht akzeptiert wird. Ich vermute ein Problem mit den Domain-Namen. Daher wollte ich dich bitten, noch einmal ein paar Sachen zu prüfen und ggf zu konkretisieren.
Welche Domainnamen sind in deinem Zertifikat eingetragen? Wie ist dein XMPP Server konfiguriert?
Bei mir ist es so, dass der XMPP Server auf dem Host ejabberd. läuft, aber die XMPP Domain bedient. Das kann man so auch problemlos einstellen. Die Frage ist nun, muss das Zertifikat auf den Host ejabberd. oder auf die Domain ausgestellt sein?
Christian
Hallo Christian,
in meinem Zertifikat ist der Full Qualified Domain Name (FQDN) des Hosts eingetragen, auf welchem der Dienst ejabberd läuft. Denn ein Client verbindet sich zu diesem Host und versucht zu verifizieren, ob er mit dem richtigen Host verbunden ist.
Die Domains, welche der ejabberd bedient, stehen nicht alle in dem Zertifikat. Denn auch diese Clients verbinden sich mit meinem Host und prüfen den FQDN.
Du schreibst, dass du deinen ejabberd bei dir zuhause betreibst. Besitzt du eine statische IP-Adresse? Andernfalls spielt dynamisches DNS unter Umständen noch eine Rolle.
TLDR;
Im Zertifikat muss der Hostname (FQDN) des ejabberd-Servers stehen. Nicht der etwaiger bedienter Domains.
Hallo noch einmal,
sorry, dass ich mich erst jetzt wieder zurück melde. Ich hatte eben erst gesehen, dass eine Antwort da ist.
Mit zuhause meinte ich, dass ich den Dienst in einem vollständig von mir kontrollierten Rechner laufen lasse (ist ein virtueller Server). Dieser hat natürlich eine statische IP. Das Problem mit dyn IPs ist also auszuschließen.
Mein Rechner hat eine IP, die einen DNS A-Eintrag (vps1.) hat. Dieser Eintrag wird wiederrum von einem CNAME Eintrag (ejabberd.) referenziert, der in meinen Jabber-Clienten als Host eingetragen wird. Wenn ich nun mittels Gajim mich einloggen will, kommt folgende Fehlermeldung:
There was an error verifying the SSL certificate of your jabber server: The authenticity of the certificate could be invalid.
The certificate does not cover this domain.
Do you still want to connect to this server?
Was ich mir nun vorstellen kann, ist, dass der Client entweder die komplette Domain oder den Namen des reverse DNS Eintrags noch mit im Zertifikat erwartet.
Hallo Christian,
dazu wie sich der Client Gajim verhält kann ich leider nichts sagen. Ich verwendet für meinen Jabber-Server einen DNS-A-Record, welcher auch im TLS-Zertifikat enthalten ist. Eine Prüfung des Reverse-DNS-Eintrags führt mein Client (Pidgin) jedenfalls nicht durch.
Du könntest es versuchsweise mal mit einem anderen Client wie z.B. Pidgin versuchen und prüfen, ob sich dieser anders verhält. Darüber hinaus kannst du nur prüfen, ob dein Zertifikat korrekt zusammengesetzt wurde, die Zertifikatskette vollständig ist und tatsächlich der korrekte FQDN drin steht.
Falls du den FQDN (also ejabberd.deine-domain.de) hier mitteilen magst, kann ich mir das Zertifikat gern mal ansehen. Du kannst mich dazu auch gern über das Kontaktformular erreichen oder mir eine E-Mail an webmaster(aett)my-it-brain(Punkt)de schreiben.
MfG
Jörg