Aktionen

ISPConfig 3.0.5.4p8 Webseiten https mit letsencrypt absichern und Zertifikate automatisch erneuern

Aus znilwiki

Warning.png
Warnung: Der Artikel gilt nur für alte ISPConfig Versionen. Die neueren (z.B. 3.1.6) haben das als Feature bei den Webseiten eingebaut - man muss nur den Haken setzten

Changelog:

  • 17.12.2016 erste Version des Artikels
  • 10.02.2015 SAN Zertifikate ergänzt (Zertifikate mit mehreren Domänennamen)
  • 04.03.2016 fullchain.pem ergänzt
  • 23.09.2016 Alles an certbot angepasst

Die kostenlosen Zertifikate von https://letsencrypt.org/ sind für mich als private Person eine feine Sache.
Im Gegensatz zu den Zertifakten von https://startssl.com/ werden die Zertifikate tatsächlich von allen Browsern als gültig aktzeptiert.
Der Firefox mag die StartSSL Zertifikate nicht und auch in vielen Kundenumgebungen gelten diese als "unsicher".

Der Vorteil bei StartSSL ist aber das die Zertifikate 1 Jahr gültig sind.
Bei Let's Encrypt sind es nur 3 Monate ... da sollte man unbedingt die automatische Erneuerung nutzen damit man es nicht vergisst.

Nun, ich musste ein wenig probieren aber nun habe ich eine lauffähige, dauerhafte Lösung für mich gefunden.



1 Ausgangslage

  • Ubuntu 14.04.x LTS
  • Apache 2.4.7 (Ubuntu)
  • ISPConfig 3.0.5.4p8

Webseite/Domäne die ich Absichern will:

remote.znil.net




2 Apache vorbereiten

Für die nachfolgenden Punkte sollte die folgenden beiden Erweiterungen von Apache aktiv sein:

sudo -i
a2enmod rewrite
a2enmod ssl

Wahrscheinlich sind die beiden schon aktiv, den Befehl noch einmal auszuführen schadet aber auch nicht.
Danach den Apache neu starten:

service apache2 restart




3 Vorbereitung der Webseite

Wir rufen die Webseite im ISPCpnfig Konfigurator auf:

Auf dem Reiter Domain setzen wir den Haken bei SSL:

ISPConfig-LetsEncrypt-001.png



Auf dem Reiter SSL füllt Ihr die oberen Felder nach belieben aus (Muss etwas drin stehen, wird aber später nicht mehr genutzt)
und setzen unten die SSl Action auf Create certificate

ISPConfig-LetsEncrypt-002.png



Auf dem Reiter Options kopiert Ihr folgendes in das Feld Apache Directives:

# Verzeichnis für Let's Encrypt Webroot Methode
<IfModule mod_headers.c>
    <LocationMatch "/.well-known/acme-challenge/*">
        Header set Content-Type "text/plain"
    </LocationMatch>
</IfModule>
# Immer Umleiten auf https
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</IfModule>

Den 2. Teil mit der Umleitung auf https könnt Ihr auch weglassen.
Ich habe es immer drin - denn wenn ich schon eine Seite per SSL absichere will acuh nur noch über das sichere Protokoll darauf zugreifen.

Dann speichern wir!

Jetzt dauert es einen Moment bis ISPConfig im Hintergrund die Änderungen verarbeitet hat (ein bis 5 Minuten),
wenn wir dann unsere Webseite aufrufen bekommen wir eine Zertifikatswarnung und das Zertifikat ist halt ein selbstsigniertes:

ISPConfig-LetsEncrypt-004.png
ISPConfig-LetsEncrypt-003.png




4 Let's Encrypt installieren

Wir öffnen eine SSH Sitzung auf unseren Webserver und wechseln zum root:

sudo -i


Falls nicht vorhanden installieren wir zunächst git nach:

apt-get install git


Dann können wir letsencrypt installieren:

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

Der letzte Aufruf sorgt dafür das sich letsencrypt richtig einrichtet und ggf. benötigte Pakete nachinstalliert.
Diesen Check macht das Programm bei jedem Aufruf - aber nur beim ersten mal dauert es so lange.
Danach wird er nur prüfen und entsprechend schneller starten.



5 Erstes Zertifikat anfordern

Nun sind wir bereit unser erstes Zertifikat anzufordern.
Meine Domäne in diesem Beispiel heißt - wie am Anfang erwähnt:

remote.znil.net

Die zugehörigen Ordner zu der Domäne liegen dann also unter

Webseite    :    /var/www/remote.znil.net/web/
Zertifikate :    /var/www/remote.znil.net/ssl/

Mit dem folgenden Aufruf fordern wir ein Zertifikat für unsere Domäne mit dem obigen Pfad an:

/opt/certbot/letsencrypt-auto certonly --webroot --rsa-key-size 4096 -w /var/www/remote.znil.net/web/ -d remote.znil.net

Erklärung:

certonly                           = nur Zertifikat Anfordern, es aber nicht in Apache installieren
--webroot                          = vorhandenen Webserver nutzen (keinen eigenen starten)
--rsa-key-size 4096                = SSL Schlüssel mit 4096 statt 2048 Bits erzeugen (= länger = sicherer)
-w /var/www/remote.znil.net/web/   = Pfad zum Webstammverzeichnis der Domäne inklusive abschließenden /
-d remote.znil.net                 = Name der dazu gehörigen externen Domäne


Beim nun allerersten Aufruf fragt er euch nach eurer Email-Addresse. Gebt da eine echte Adresse an damit mit Ihr bei Problemen acuh informiert werden könnt!
Danach müsst Ihr die Nutzungsbedingungen einmalig akzeptieren.
Beides geschieht nur bei der ersten Anforderung auf eurem Server!

Das angeforderte Zertifikat liegt nun unter

/etc/letsencrypt/live/name.euerer.domain

bei diesem Beispiel also unter

ls -l /etc/letsencrypt/live/remote.znil.net/

Ausgabe:

root@web01:# ls -l /etc/letsencrypt/live/remote.znil.net/
insgesamt 0
lrwxrwxrwx 1 root root 39 Dez 17 21:15 cert.pem -> ../../archive/remote.znil.net/cert1.pem
lrwxrwxrwx 1 root root 40 Dez 17 21:15 chain.pem -> ../../archive/remote.znil.net/chain1.pem
lrwxrwxrwx 1 root root 44 Dez 17 21:15 fullchain.pem -> ../../archive/remote.znil.net/fullchain1.pem
lrwxrwxrwx 1 root root 42 Dez 17 21:15 privkey.pem -> ../../archive/remote.znil.net/privkey1.pem

Nun müssen wir dieses Zertifikat nur noch nutzen!



6 Zertifikat in Webseite einbauen

Für jede Webseite legt ISPConfig eine Datei unter

/etc/apache2/sites-available/

an. Meine Webseite heißt

remote.znil.net

dann müssen wir folgende Datei bearbeiten:

nano /etc/apache2/sites-available/remote.znil.net.vhost


In der Datei sucht nach den folgenden Zeilen:

               <IfModule mod_ssl.c>
               SSLEngine on
               SSLProtocol All -SSLv2 -SSLv3
               SSLCertificateFile /var/www/clients/client0/web4/ssl/remote.znil.net.crt
               SSLCertificateKeyFile /var/www/clients/client0/web4/ssl/remote.znil.net.key
               </IfModule>

und ändert diese wie folgt ab:

              <IfModule mod_ssl.c>
               SSLEngine on
               SSLProtocol All -SSLv2 -SSLv3
               # SSLCertificateFile /var/www/clients/client0/web4/ssl/remote.znil.net.crt
               # SSLCertificateKeyFile /var/www/clients/client0/web4/ssl/remote.znil.net.key
               SSLCertificateFile /etc/letsencrypt/live/remote.znil.net/cert.pem
               SSLCertificateKeyFile /etc/letsencrypt/live/remote.znil.net/privkey.pem
               SSLCACertificateFile /etc/letsencrypt/live/remote.znil.net/fullchain.pem
               </IfModule>

remote.znil.net müsst Ihr dabei natürlich durch euren eigenen Webseitennamen ersetzen!
Und ja, wir ersetzen die 2 Einträge damit durch 3 neue Einträge! Ohne den 3. Eintrag SSLCACertificateFile kann es Probleme geben!

Im Anschluß müsst Ihr den Apache seine Konfiguration neu einlesen lassen:

service apache2 reload



Wenn Ihr nun eure Webseite aufruft so sollte diese sich mit dem letsencrypt Zertifikat melden:

ISPConfig-LetsEncrypt-005.png50x50.pngISPConfig-LetsEncrypt-006.png




7 Automatische Erneuerung in 3 Varianten




7.1 Variante 1: Die einfachste!

Habe ich erst kürzlich beim Umzug meines Servers entdeckt als ich die mal die ganze Anleitung auf der Let's Encrypt Webseite gelesen habe. Ich behaupte einfach mal das diese bei der ursprünglichen Erstellung dieses Artikel noch nicht funktionierte:

Die dort beschriebene Methode deckt alle Szenarien ab - man muss nur damit leben das alle paar Monate(!) der Webserver mal kurz für eine Minute angehalten wird.



7.2 Variante 2: Automatische Erneuerung des Zertifikates

Warning.png
Warnung: Ihr dürft bei Angabe von --renew-by-default keinen neuen Domänennamen hinzufügen oder einen weglassen! Kommt eine weitere Domäne hinzu müsst Ihr erst wieder eine Anforderung wie in den Abschnitten zuvor machen. Im Dialog könnt Ihr dann Expand wählen und der neue Name wird mit eingebaut

Nun läuft das Zertifikat nach genau 90 Tagen wieder ab.
Um es zu erneuern reicht - im Prinzip - der erneute Aufruf des Befehls mit dem wir das Zertifikat auch schon angefordert haben.
Jedoch wird dabei ein Menü erscheinen welches auch fragt ob Ihr das alte überschreiben wollt (falls es denn noch gültig ist).
Um das zu verhindern kann man noch den Parameter

--renew-by-default

setzen. Der ist extra für Cron-Jobs gedacht und setzt vorraus das es zu keinen Nachfragen kommt.
Beim ersten Aufruf auf dem Server MUSS es also ohne diesen Parameter sein.

Warning.png
Warnung: Falls Ihr den Aufruf von Hand testen wollt - Überteibt es nicht! Wenn Ihr das 5 mal in 7 Tagen macht obwohl die Zertifikate noch gültig sind seit Ihr erst einmal gesperrt bis die 7 Tage um sind! Das machen die so um Ihre Server zu entlasten!
Neuerdings könnte Ihr ein --dry-run anhängen - dann simuliert er nur!

Der Aufruf für den Cron-Job wäre also

/opt/certbot/letsencrypt-auto certonly --webroot --rsa-key-size 4096 --renew-by-default -w /var/www/remote.znil.net/web/ -d remote.znil.net

Nun müssen wir uns noch für einen vernünftigen Zeitrahmen entscheiden.
Die meisten anderen im Internet stellen den Job auf 30 Tage ... nun das Ding ist 90 Tage gültig ...
Ich habe mich für folgendes enstchieden:

  • Das Zertifikat habe ich am 17. des Monats angefordert
  • Erneuerung also alle 2 Monate am 16.
  • Um 5:30 Uhr wenn es keinen stört!

Daraus ergibt sich folgender Eintrag in der crontab:

crontab -e

und dann

30 5 16 */2 * /opt/certbot/letsencrypt-auto certonly --webroot --rsa-key-size 4096 --renew-by-default -w /var/www/remote.znil.net/web/ -d remote.znil.net > /dev/null




7.3 Variante 3: Automatische Erneuerung bei Reverse Proxy Webseiten

Viele meiner Subdomains hosten gar keine Webseiten sondern leiten den Datenverkehr nur um auf einen anderen Dienst.
Hier kommen wir mit der Methode nicht weiter da letsencrypt es nie schaffen wird seine Daten zu lesen.
In diesem Fall ist es am einfachsten beim Aufruf statt des Apache den in letsencrypt Webserver zu nehmen.
Nachteil ist das dazu der eigentliche Apache kurz angehalten werden muss - was ich aber alle 2 Monate mal kurz verschmerzen kann

Die erste Anforderung sähe dann wie folgt aus:

service apache2 stop && /opt/certbot/letsencrypt-auto certonly --standalone --rsa-key-size 4096 -d remote.znil.net && service apache2 start

Und die automatische Erneuerung in der crontab entsprechend so:

30 5 16 */2 * service apache2 stop && /opt/certbot/letsencrypt-auto certonly --standalone --rsa-key-size 4096 --renew-by-default -d remote.znil.net && service apache2 start > /dev/null




8 SAN-Zertifikate bzw. ein Zertifikat für mehrere Webseiten gleichzeitig

SAN-Zertifikate sind Zertifikate die gleichzeitig für mehrere Domänennamen gültig sind.
Zum Beispiel das für meinen Test-Exchange-Server:

ISPConfig-LetsEncrypt-007.png ISPConfig-LetsEncrypt-008.png


Jede Menge Domänennamen und für jedes dieser Domänen ist das zertifikat gültig.

Nun gibt es bei letsencrypt die Einschränkung das diese Domänennamen auch überpüft werden müssen/können.
Das bedeutet das man halt keine internen Domänenenamen in das Zertifikat aufnehmen kann.
Auch Wildcard-Zertifikate werden - im Moment - nicht ünterstützt.

Im nachfolgenden will ich nun ein Zertifikat für die folgenden Subdomänen anfordern:

grafana.znil.net
ispconfig.znil.net
livecam01.znil.net
login.znil.net
nzb.znil.net
pfsense.znil.net
support.znil.net
zabbix.znil.net

Diese sollen alle in ein einziges Zertifikat.
Für die Anforderung habe ich mich für diue Version über den interen Webserver des letsencrypt-Skripts entschieden das sehr viele Reverse-Porxy-Domänen dabei sind.
Die erste Anforderung würde wie folgt laufen:

service apache2 stop
/opt/certbot/letsencrypt-auto certonly --standalone --rsa-key-size 4096 -d grafana.znil.net -d ispconfig.znil.net -d livecam01.znil.net -d login.znil.net -d nzb.znil.net -d pfsense.znil.net -d support.znil.net -d zabbix.znil.net
service apache2 start

Wie Ihr seht wird einfach für jede Subdomäne / jeden Namen einfach ein -d Domänenname angehängt.
Die Ausgabe ist wie folgt:

Updating letsencrypt and virtual environment dependencies.......
Running with virtualenv: /root/.local/share/letsencrypt/bin/letsencrypt certonly --standalone --rsa-key-size 4096 -d grafana.znil.net -d ispconfig.znil.net -d livecam01.znil.net -d login.znil.net -d nzb.znil.net -d pfsense.znil.net -d support.znil.net -d zabbix.znil.net

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/grafana.znil.net/fullchain.pem. Your cert
   will expire on 2016-03-24. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

Er speichert das Zertifikat also unter dme Namen des ersten -d Eintrages in der Liste.
Das Zertifikat können wir nun wie gewohnt allen Webseiten die darin aufgeführt werden zuweisen.
Wenn wir es uns dann im Browser ansehen sieht es wie folgt aus:

ISPConfig-LetsEncrypt-009.png ISPConfig-LetsEncrypt-010.png



Das Erneuern per crontab dazu sieht zum Beispiel so aus:

30 5 25 */2 * service apache2 stop && /opt/certbot/letsencrypt-auto certonly --standalone --rsa-key-size 4096 --renew-by-default -d grafana.znil.net -d ispconfig.znil.net -d livecam01.znil.net -d login.znil.net -d nzb.znil.net -d pfsense.znil.net -d support.znil.net -d zabbix.znil.net && service apache2 start > /dev/null




9 Für und Wieder der Methode

Wer das so macht wie ich dem muss bewusst sein das bei jeder Änderung in ISPConfig an der Webseite die gemachten Änderungen überschrieben werden!
Ich hatte es auch zunächst hiermit versucht: https://github.com/alexalouit/ISPConfig-letsencrypt
Es aber nicht zum laufen bekommen.
Naja .. und ich lege jede seite in ISPConfig an ... und danach nutze ich die Oberfläche eigentlich nicht mehr dafür.
Und mit dem Cronjob pro Webeite kann ich leben.
Was mich nicht daran hindern soll das ich es in ein paar Wochen eventuell eleganter hinbekommen und den Artikel hier dann ändere.



10 Kommentare


jacob.maxa@gmail.com

35 Monaten zuvor
Punktzahl 0++

Vielen Dank für die Anleitung, hab Sie gerade nachgemacht und bin begeistert wie einfach das klappt. Ein Hinweis noch: Ich möchte ISPConfig nicht in der Apacheconfig rumpfuschen. Daher habe ich nicht die Pfade zu den Zertifikaten angepasst sondern im SSL Ordner der jeweiligen Seite einen symbolischen Link (ln -s) auf die Dateien im /etc/letsencrypt/live/xxx.xx Ordner gelegt und die gleichen Namen verwendet, welche ISPConfig ursprünglich für die nicht-validierten Zertifikate genommen hat. Klappt prima.

Grüße

Jacob

BLinz

35 Monaten zuvor
Punktzahl 0++

Das ist natürlich der bessere Weg, da stimme ich dir ganz zu.

Ich nutze ISPConfig inzwischen nur noch zum anlegen und löschen von Webseiten und Datenbanken ... und "pfusche" in fast jeder Konfigurationsdateien herum da ich viel Reverse Proxy etc. mache. Bei normalen Subdomains werde ich es so wie du machen, gleich mal ändern ...

mlorenz@service.de

35 Monaten zuvor
Punktzahl 0++

Der Hinweis mit den symbolischen Links ist Klasse.

Verstehe ich das richtig, das es keinen Unterschied macht zwischen den originalen Dateibezeichnungen und den PEMs?

Leider erhalte ich ich beim Aufruf meiner Domain die Meldung, es handele sich um keine sichere Verbindung. Sehe ich mir die Infos an, so ist das Zertifikat von Let's Encrypt für die Seite tld.de, nicht aber für www.tld.de ausgestellt.

luca

35 Monaten zuvor
Punktzahl 0++

Kleine Ergänzung: Um im iOS Browser Vertrauensmeldung bzgl. des Zertifikates zu erhalten, muss zusätzlich noch die fullchain.pem in der VHOST angegeben werden. Einfach an die anderen Einträge anhängen:

SSLCertificateChainFile /etc/letsencrypt/live/suesse-ponys.de/fullchain.pem

Vielen Dank für die Anleitung. Hat super funktioniert.

BLinz

35 Monaten zuvor
Punktzahl 0++
Danke, musste ich bei vielen Kunden die Proxys einsetzen auch feststellen das die fillchain.pem dazu muss. Ich habe die Anleitung oben entsprechend geändert

BLinz

35 Monaten zuvor
Punktzahl 0++
Nachtrag: Die Symbolischen Links haben auch Nachteile - wenn Ihr dann im ISP-Config das Zertifikat noch einmal speichert wird das von Let's Encrypt überschrieben. Bei der Methode des änderns der Apache-Dateien nicht.

X-Coder

34 Monaten zuvor
Punktzahl 0++

Könnte man nicht durch ein Script die Mysql dbispconfig.web_domain Tabelle direkt updaten? Dann riskiert man nicht dass bei der nächsten Änderung im Webpanel die config zerschossen wird oder die Dateien überschrieben. Das Ispconfig-Cronjob-Script müsste beim nächsten Durchlauf dann automatisch, die richtigen Dateien updaten.

Wenn ich es richtig sehe müssten ja nur die Felder ssl_request, ssl_cert, ssl_bundle und ssl_action geupdated werden.

X-Coder

34 Monaten zuvor
Punktzahl 0++

Es ist auch möglich mit der Ispconfig Remote-API, ähnlich wie es hier bereits umgesetzt wurde:

https://gith…le2ispc#L259

mlorenz@service.de

34 Monaten zuvor
Punktzahl 0++

Ich habe gestern einige Schwierigkeiten gehabt, für noch nicht abgesicherte Domains, Zertifikate zu laden. Ich wurde mit dem allzu bekannten Fehler:

.....Could not connect to .well-known

genervt. Der gesamte Topic ist unter https://comm…own/13528/22 nachzulesen. Die schlussendliche Lösung brachte dieser Post:

Here is one more idea on how to avoid redirecting to HTTPS for .well-known/acme-challenge. Add the following line: RewriteCond %{REQUEST_URI} !^/\.well\-known/acme\-challenge/ right before RewriteRule (.*) https://%{HT…REQUEST_URI}

Und das war es.
Kommentar hinzufügen
znilwiki freut sich über alle Kommentare. Sofern du nicht anonym bleiben möchtest, trage deinen Namen oder deine Email-Adresse ein oder melde dich an. Du kannst das Feld auch einfach leer lassen.