{"id":115,"date":"2017-09-13T01:24:05","date_gmt":"2017-09-12T23:24:05","guid":{"rendered":"http:\/\/blog.0link.net\/?p=115"},"modified":"2017-09-13T01:58:11","modified_gmt":"2017-09-12T23:58:11","slug":"letsencrypt-kostenloses-ssl-zertifikat-auf-dem-server","status":"publish","type":"post","link":"https:\/\/blog.0link.net\/index.php\/2017\/09\/13\/letsencrypt-kostenloses-ssl-zertifikat-auf-dem-server\/","title":{"rendered":"LetsEncrypt &#8211; kostenloses SSL-Zertifikat auf dem Server"},"content":{"rendered":"<h4>Vorwort<\/h4>\n<p>Lange habe ich \u00fcberhaupt keinen Sinn und Zweck in Zertifikaten gesehen &#8211; geht ja auch ohne. Mittlerweile kommt man bei Facebook und Google als Seitenbetreiber nicht mehr um verschl\u00fcsselte Verbindungen herum. Wenn man es mal genau betrachtet &#8230; jede Seite auf der ich irgendetwas pers\u00f6nliches eingebe (Newsletter-Anmeldung, irgendwelche Login-Daten, usw.) sollte entsprechend meine Daten sch\u00fctzen, wir lassen uns ja auch bei der Eingabe der PIN am Bankautomat nicht \u00fcber die Schulter gucken.<\/p>\n<h4>Meine\u00a0ersten Zertifikate<\/h4>\n<p>Wie so ziemlich jeder, der irgendwann in die Welt der Zertifikate eintaucht, stand ich vor der ersten H\u00fcrde &#8230; sie kosten Geld. Einziger Ausweg waren damals self-signed-Zertifikate. Unter Linux kein gro\u00dfes Problem, schnell ist eins erstellt und muss dann in die jeweilige Serveranwendung eingebunden werden. Eine kleine &#8222;Ern\u00fcchterung&#8220; stellt sich beim ersten Test der mit self-signed gesicherten Webseite schon ein &#8230; der Browser warnt uns, das es ein Zertifkat gibt, er aber nicht wei\u00df, ob man ihm vertrauen kann. Das speichern einer Ausnahmeregel gestatten eigentlich alle Browser, so dass es uns nicht weiter belastet. Wenn man aber Dienste f\u00fcr m\u00f6glicherweise unbekannte Dritte anbietet, ist das schon etwas st\u00f6rend.<\/p>\n<h4>Die Alternativen<\/h4>\n<p>Heute gibt es schon mehrere Anbieter, die kostenlose Zertifikate anbieten. Die Leistungen sind unterschiedlich, was Anzahl Domains, G\u00fcltigkeit und vor allem das Handling angeht. Es ist schon wenig komfortabel, wenn man alle 30 Tage sein Zertifikat manuell verl\u00e4ngern muss und dann auch in allen Anwendung neu einbinden muss.<\/p>\n<p>Deshalb sticht der Anbieter <a href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\" rel=\"noopener\">LetsEncrypt<\/a> heraus &#8230; er bietet kostenlose Zertifikate f\u00fcr bis zu 100 Domains und mit einer Laufzeit von 90 Tagen an. Der Clou &#8230; dank einer Software l\u00e4sst sich das Renewal sogar automatisieren. Das macht es jetzt schon recht einfach seine Webseiten und Mailserver mit einem SSL-Zertifikat zu sichern.<\/p>\n<h4>Voraussetzungen<\/h4>\n<p>Wir kennen uns etwas mit Linux aus und wissen grunds\u00e4tzlich, wie wir selbst Skripte erstellen und haben auch schon den Apache auf unserem Server selbst eingerichtet. Vielleicht haben wir auch schon mit self-signed-Zertifikaten gearbeitet, dann ist vor allem die Apache-Konfig mit SSL nichts Neues.<\/p>\n<p>Ziel ist nun das Ganze mit einem LetsEncrypt-Zertifikat zu versehen, dass sich selbst aktualisiert. Die folgenden Schritte sollten unter Ubuntu 14\/16 und Raspbian Wheezy\/Jessie funktionieren. Python muss auch installiert sein, da der Certbot darauf aufbaut.<\/p>\n<h4>Das Setup<\/h4>\n<p>Zuerst m\u00fcssen wir den so genannten <a href=\"https:\/\/certbot.eff.org\/\" target=\"_blank\" rel=\"noopener\">Certbot<\/a> laden und installieren, der f\u00fcr uns das Zertifikat anfordern und aktualisieren kann &#8230;<\/p>\n<pre>root@server:~# wget https:\/\/dl.eff.org\/certbot-auto\r\nroot@server:~# mkdir \/usr\/local\/sbin\/certbot\r\nroot@server:~# mv .\/certbot-auto \/usr\/local\/sbin\/certbot\/<\/pre>\n<p>Damit haben wir nun den Certbot betriebsbereit auf dem System. Er bietet viele Automatisierungen f\u00fcr das Ausstellen des Zertifikates und sogar f\u00fcr das Konfigurieren von Apache an. Letzteres habe ich nie ausprobiert, da ich es nicht so gerne mag, wenn irgendwer in meinen Konfigurationen Sachen \u00e4ndert. Gerade, wenn man ein komplexes Gebilde mit verschiedenen SNI-basierten VirtualHosts hat und vielleicht auch noch mehrere Zertifikate verwaltet, traue ich dabei keinem Automatismus.<\/p>\n<h4>Zertifikat ausstellen<\/h4>\n<p>Ich habe mir daf\u00fcr ein Skript in <code>\/usr\/local\/sbin\/certbot-sign.sh<\/code> erstellt. Wenn ich die Domains im Zertifikat \u00e4ndern muss, dann gebe ich die \u00c4nderung in der Datei ein und wei\u00df so immer, was im Zertifikat sein sollte.<\/p>\n<pre>#!\/bin\/bash\r\n\/usr\/local\/sbin\/certbot\/certbot-auto certonly --standalone --rsa-key-size 4096 -d server.tld -d mail.server.tld -d ssl.server.tld --pre-hook \"service apache2 stop\" --post-hook \"service apache2 start\"<\/pre>\n<p>Das Skript wird als root gestartet und startet den Certbot ohne Konfigurationsskript (&#8211;standalone) und fordert EIN Zertifkat f\u00fcr ALLE Domains, die jeweils mit -d angegeben werden. Der Apache wird gestoppt und im Anschluss wieder gestartet (&#8211;pre-hook \/ &#8211;post-hook), denn der Certbot braucht den Port 80, damit bei der Zertifikaterstellung gepr\u00fcft werden kann, ob denn der Server auch wirklich unter dem Domainnamen erreicht werden kann.<\/p>\n<p>Wenn ich eine neue Domain hinzuf\u00fcge, schreibe ich ein weiteres -d einfach vor das &#8211;pre-hook und starte es manuell per sudo. Das Zertifikat wird dann neu erstellt. Das L\u00f6schen einer Domain geht auf diesem Wege auch. Wissenswert ist, dass die erste Domain der Stammname f\u00fcr das Zertifikat ist, womit der Certbot unter \/etc\/letsencrypt die Zertifikate und eine Konfig anlegt.<\/p>\n<h4>Einbinden im Apache<\/h4>\n<p>Das Einbinden im Apache ist recht einfach. Wenn nicht schon geschehen, weil ein self-signed-Zertifikat eingesetzt wurde, muss das Modul mod_ssl installiert und im Apache geladen sein.<\/p>\n<p>Dann braucht es eine Grundkonfig f\u00fcr mod_ssl, damit das Zertifikat schon bei der ersten Verbindung zum Apachen zur Verf\u00fcgung steht. Bei mir sieht es in <code>\/etc\/apache2\/sites-available\/default-ssl.conf<\/code> so aus &#8230;<\/p>\n<pre>&lt;IfModule mod_ssl.c&gt;\r\n\t&lt;VirtualHost <span class=\"moz-txt-underscore\"><span class=\"moz-txt-tag\">_<\/span>default<span class=\"moz-txt-tag\">_<\/span><\/span>:443&gt;\r\n\t\tServerAdmin webmaster@server.tld\r\n\t\tDocumentRoot \/var\/www\/html\r\n\r\n\t\tSSLEngine On\r\n\t\tSSLCertificateFile      \/etc\/letsencrypt\/live\/server.tld\/fullchain.pem\r\n\t\tSSLCertificateKeyFile   \/etc\/letsencrypt\/live\/server.tld\/privkey.pem\r\n\r\n\t\t&lt;FilesMatch \"\\.(cgi|shtml|phtml|php)$\"&gt;\r\n\t\t\t\t\t\tSSLOptions +StdEnvVars\r\n\t\t&lt;\/FilesMatch&gt;\r\n\r\n\t\t&lt;Directory \/usr\/lib\/cgi-bin&gt;\r\n\t\t\t\t\t\tSSLOptions +StdEnvVars\r\n\t\t&lt;\/Directory&gt;\r\n\r\n\t\tBrowserMatch \"MSIE [2-6]\" \\\r\n\t\t\t\t\t\tnokeepalive ssl-unclean-shutdown \\\r\n\t\t\t\t\t\tdowngrade-1.0 force-response-1.0\r\n\r\n\t\t# MSIE 7 and newer should be able to use keepalive\r\n\t\tBrowserMatch \"MSIE [17-9]\" ssl-unclean-shutdown\r\n\t&lt;\/VirtualHost&gt;\r\n&lt;\/IfModule&gt;<\/pre>\n<p>Jetzt\u00a0m\u00fcssen wir noch den einzelnen Webseiten eine Konfiguration f\u00fcr SSL verpassen. Wir nehmen an, dass wir einen VirtualHost unter ssl.server.tld in der Datei ssl.conf eingerichtet haben &#8230;<\/p>\n<pre>&lt;VirtualHost *:80&gt;\r\n\tServerName ssl.server.tld\r\n\tServerAdmin webmaster@server.tld\r\n\tDocumentRoot \/var\/www\/ssl\r\n\r\n\tRewriteEngine On\r\n\tRewriteCond %{HTTPS} off\r\n\tRewriteRule (.*) https:\/\/%{HTTP_HOST}%{REQUEST_URI} [R=301,L]   ## umleiten auf ssl\r\n\r\n\tErrorLog ${APACHE_LOG_DIR}\/error.log\r\n\tCustomLog ${APACHE_LOG_DIR}\/access.log combined\r\n\r\n&lt;\/VirtualHost&gt;\r\n\r\n&lt;VirtualHost *:443&gt;\r\n\tServerName ssl.server.tld\r\n\tServerAdmin webmaster@server.tld\r\n\tDocumentRoot \/var\/www\/ssl\r\n\r\n\tSSLEngine On\r\n\tSSLCertificateFile      \/etc\/letsencrypt\/live\/server.tld\/cert.pem\r\n\tSSLCertificateKeyFile   \/etc\/letsencrypt\/live\/server.tld\/privkey.pem\r\n\tSSLCertificateChainFile \/etc\/letsencrypt\/live\/server.tld\/chain.pem\r\n\r\n&lt;\/VirtualHost&gt;\r\n\r\n&lt;Directory \/var\/www\/domain1&gt;\r\n\tOptions FollowSymLinks\r\n\tAllowOverride None\r\n\tOrder deny,allow\r\n\tRequire all granted\t\r\n&lt;\/Directory&gt;\r\n<\/pre>\n<p>Die im oberen Block f\u00fcr Port 80 eingef\u00fcgten Rewrite-Optionen bewirken, dass auch Besucher auf dem Port 80 auf den SSL-Port 443 umgeleitet werden. Wir lassen also keine ungesicherte Kommunikation mehr zu.<\/p>\n<p>Jetzt noch den Apache neu starten und es sollte dann die Seite ssl.server.tld mit https: und einem g\u00fcltigen Zertifikat erscheinen.<\/p>\n<h4>Zertifikat aktuell halten<\/h4>\n<p>Hier werden uns ein weiteres Skript und ein Eintrag im Crontab helfen. Theoretisch m\u00fcsste man das Renewal nur exakt 90 Tage nach dem letzten lauf durchf\u00fchren. Seien wir ehrlich &#8230; so wird es keiner machen. Zuerst das Skript in \/usr\/local\/sbin\/certbot-renew.sh anlegen &#8230;<\/p>\n<pre>#!\/bin\/bash\r\n\/usr\/local\/sbin\/certbot\/certbot-auto renew --standalone --pre-hook \"service apache2 stop\" --post-hook \"service apache2 start\"<\/pre>\n<p>Alte Bekannte sind die hooks &#8230; die wieder den Apache kurzzeitig abschalten. Da sich der Certbot die Domains im Zertifikat unter \/etc\/letsencrypt gemerkt hat, brauchen wir sie hier nicht angeben.<\/p>\n<p>Das Skript schreiben wir jetzt in\u00a0\/etc\/crontab so dass es regelm\u00e4\u00dfig das Wohl unseres Zertifikates pflegt &#8230;<\/p>\n<pre>[...]\r\n@weekly\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 root\u00a0\u00a0\u00a0 \/usr\/local\/sbin\/certbot-renew.sh\r\n[...]<\/pre>\n<p>Warum lasse ich den Job nun w\u00f6chentlich (d.h. Sonntags 0 Uhr) erledigen? Theoretisch w\u00fcrde monatlich ja auch reichen, aber ich hatte folgende Rechnung:<\/p>\n<ul>\n<li>ich erstelle\u00a0mein Zertifikat\u00a0am 1. des Monats<\/li>\n<li>@monthly l\u00e4uft am Monatsersten 0:00 Uhr<\/li>\n<li>beim\u00a0ersten Lauf von certbot-renew.sh ist das Zertifikat noch 60 Tage g\u00fcltig<\/li>\n<li>beim zweiten Lauf noch 30 Tage &#8211; da macht der certbot von sich aus noch keine Neuanforderung, macht er erst bei 15 Tagen<\/li>\n<li>beim dritten Lauf ist es jetzt der Ablauftag. Geht nun irgendwas schief, sehe ich morgens zwar die Fehlermeldung in meinem Posteingang, habe aber im ung\u00fcnstigsten Fall schon ein abgelaufenes Zertifikat.<\/li>\n<\/ul>\n<p>Also lasse ich w\u00f6chentlich pr\u00fcfen. Das dauert nur ein paar Sekunden und dem Apache schadet ein w\u00f6chentlichen Neustart auch nicht. Soweit mein Setup f\u00fcr den Apache mit LetsEncrypt.<\/p>\n<h4>meine Erfahrung mit LetsEncrypt<\/h4>\n<p>Ich bin ein Fan von diesen Zertifkaten geworden und habe das System\u00a0auf verschiedenen Rechnern laufen. Bisher hatte ich nur einmal das Problem, dass ich beim &#8222;re-sign&#8220; (also das Hinzuf\u00fcgen einer Domain) die neue Domain an den Anfang der Kette geschrieben habe und dann ein neues\u00a0Zertifikat mit einer neuen Stammdomain hatte.<\/p>\n<p>Das ist aber kein unl\u00f6sbares Problem. Mit dem Befehl<\/p>\n<pre>root@server:~# \/usr\/local\/sbin\/certbot\/certbot-auto certificates<\/pre>\n<p>erh\u00e4lt man eine \u00dcbersicht der Zertifikate. In dieser \u00dcbersicht sieht man neben dem Stammnamen (den brauchen wir) auch die Restg\u00fcltigkeit und den Speicherort. Das zu l\u00f6schende Zertifikat kann man dann mit dem Befehl<\/p>\n<pre>sudo \/usr\/local\/sbin\/certbot\/certbot-auto delete --cert-name server.tld<\/pre>\n<p>vom System entfernen.<\/p>\n<h4>Weitere Anwendungen<\/h4>\n<p>Ich setze die Zertifikate auch im Mailserver postfix\/dovecot ein. Die Konfiguration habe ich auf Basis des <a href=\"https:\/\/thomas-leister.de\/mailserver-unter-ubuntu-16.04\/\" target=\"_blank\" rel=\"noopener\">Blog von Thomas Leister<\/a> erstellt.<\/p>\n<h4>Links<\/h4>\n<ul>\n<li>LetsEncrypt |\u00a0<a href=\"https:\/\/letsencrypt.org\/\" target=\"_blank\" rel=\"noopener\">https:\/\/letsencrypt.org\/<\/a><\/li>\n<li>Certbot |\u00a0<a href=\"https:\/\/certbot.eff.org\/\" target=\"_blank\" rel=\"noopener\">https:\/\/certbot.eff.org\/<\/a><\/li>\n<li>Thomas Leister | <a href=\"https:\/\/thomas-leister.de\/mailserver-unter-ubuntu-16.04\/\" target=\"_blank\" rel=\"noopener\">https:\/\/thomas-leister.de\/mailserver-unter-ubuntu-16.04\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Vorwort Lange habe ich \u00fcberhaupt keinen Sinn und Zweck in Zertifikaten gesehen &#8211; geht ja auch ohne. Mittlerweile kommt man bei Facebook und Google als Seitenbetreiber nicht mehr um verschl\u00fcsselte Verbindungen herum. Wenn man es mal genau betrachtet &#8230; jede Seite auf der ich irgendetwas pers\u00f6nliches eingebe (Newsletter-Anmeldung, irgendwelche Login-Daten, usw.) sollte entsprechend meine Daten &hellip; <a href=\"https:\/\/blog.0link.net\/index.php\/2017\/09\/13\/letsencrypt-kostenloses-ssl-zertifikat-auf-dem-server\/\" class=\"more-link\"><span class=\"screen-reader-text\">LetsEncrypt &#8211; kostenloses SSL-Zertifikat auf dem Server<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/posts\/115"}],"collection":[{"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":10,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"predecessor-version":[{"id":130,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/posts\/115\/revisions\/130"}],"wp:attachment":[{"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.0link.net\/index.php\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}