Dank des freien Dienstes Let’s encrypt ist es jedem mittlerweile Möglich seine Seiten per SSL zu sicheren. Dank des Apache Module mod_md kann der Apache Webserver nun inline die Zertifikate erstellen und warten. Ich habe mir das die Tage mal angesehen, und will Euch hier die Ergebnisse präsentieren.
Hintergrund
SSL/TLS Verschlüsselung für Webseiten (HTTPS) kostet normalerweise richtig Geld. Dank des Let’s encrypt Projektes ist es seit geraumer Zeit jedem Möglich die Seiten seines Werbeauftritts (und auch seines Mailservers) verschlüsselt über den Äther zu schicken. Im Groben und Ganzen handeln Server und Client anhand eines Schlüsselpaares Zufallszahlen aus, die dann zur Verschlüsselung der zu sendenden Daten verwendet werden. Damit der Client auch sicher sein kann, dass er mit dem richtigen Server spricht, gibt es noch eine Stelle die das überprüft (die Authority, hier eben Let’s Encrypt).
Der alte Weg
Bisher habe ich für die Erzeugung und die Pflege der Zertifikate certbot verwendet. Ein Phyton Script, welches alles Nötige zur Verfügung stellt. Gehen wir also davon aus wir hätten eine Domain example.org und wollen die „verSSLen“ so brauchen wir ein Zertifikat, das die folgenden Subdomains enthält:
- example.org
- www.example.org
- mail.example.org
Beim generieren überprüft Let’s encrypt per generierter Datei und Web-Abfrage (http://$domain/.well-known/……) ob wir auch wirklich Inhaber selbigen Webservers sind und schwub können wir das Schlüsselpaar nutzen.
Wenn das Zertifikat abzulaufen droht (90 Tage), muss man es erneuern. Das läuft eigentlich genauso ab. Das haupt Problem ist eigentlich, ich muss alles einzeln machen, und dafür sorgen, dass das .well-known Verzeichnis für alles Subdomains verfügbar ist… Teilweise echt ein gefrickel….
Der neue Weg
Beim letzten Apache Update stolperte ich über Module mod_md. Weil ich mit dem Namen nichts anfangen konnte, hab ich mir das angesehen, und war angenehm überrascht. Mit Hilfe dieses Moduls kann der Webserver selber on-the-fly Zertifikate erstellen (inklusive der Subdomains) und kümmert sich auch noch um die Erneuerung. Ich war begeistert! Immerhin betreue ich hier ein paar Seiten und alles was Arbeit spart….
Wie funktionierts?
Zunächst einmal braucht man eine Apache Version >= 2.4.30 und die Module mod_md und mod_watchdog. Zusätzlich natürlich noch einige für SSL etc.
Im folgenden gehe ich davon aus, dass wir für die oben genannten Domains einen Virtual Host anlegen. Ich zerlege gerne die Config gerne etwas. Was wir also in /usr/local/etc/apache24/Includes liegen haben, sind drei Files:
ssl.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | SSLRandomSeed startup builtin SSLRandomSeed connect builtin SSLRandomSeed startup file:/dev/urandom 512 SSLRandomSeed connect file:/dev/urandom 512 Listen 443 AddType application/x-x509-ca-cert .crt AddType application/x-pkcs7-crl .crl SSLPassPhraseDialog builtin SSLSessionCache "shmcb:/var/run/ssl_scache(512000)" SSLStaplingCache "shmcb:/var/run/ssl_stapling(32768)" SSLSessionCacheTimeout 300 SSLCipherSuite EECDH+AESGCM+AES256:EECDH+AES256:EDH+AES256 SSLProtocol -ALL -SSLv3 +TLSv1 +TLSv1.1 +TLSv1.2 SSLHonorCipherOrder on SSLUseStapling On SSLStrictSNIVHostCheck Off SSLCompression off ### MOD_MD MDStoreDir etc/apache24/md MDCertificateAgreement https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf MDomain www.example.org mail.example.org |
Die ersten Zeilen sind die „normale“ SSL Konfiguration. Zeile 29-31 sind die interessanten:
MDStoreDir
gibt an, wo die Zertifikate gespeichert werden sollen. Hilfreich, wenn man zum Beispiel auch mit nem Mailserver darauf zugreifen will.
MDCertificateAgreement
: Man muss irgendwie die Lizenz von Let’s encrypt akzeptieren. Das macht diese Zeile… 😉
MDomain
: Der ServerName des Virtual Hosts. Pro „Hauptdomain“ eine eigne Zeile. So landen nicht alle im gleichen Zertifikat. Achtung: Alle ServerAliases landen auch im Zertifikat. Deshalb steht example.org hier nicht mit drin!
example.org.conf
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <VirtualHost *:80> ServerName www.example.org ServerAlias example.org Redirect permanent / https://www.example.org/ </VirtualHost> <VirtualHost *:443> ServerName www.example.org ServerAlias example.org ServerAdmin webmaster@example.org DocumentRoot "/usr/local/www/wordpress" ErrorLog "/var/log/apache24/example.org-error.log" CustomLog "/var/log/apache24/example.org-access.log" combined Include etc/apache24/Includes/ssl.inc </VirtualHost> |
Im ersten VirtualHost biegen wir Port 80 auf 443 um. Der zweite VirtualHost hat am Schluss ein Include. In diesem File steckt alles was für SSL nötig ist aber nicht global definiert wird…
ssl.inc:
1 2 3 4 5 6 7 8 9 10 11 | SSLEngine on Header always set Strict-Transport-Security "max-age=31536000; preload" BrowserMatch ".*MSIE.*" \ nokeepalive ssl-unclean-shutdown \ downgrade-1.0 force-response-1.0 <FilesMatch "\.(cgi|shtml|phtml|php)$"> SSLOptions +StdEnvVars </FilesMatch> |
Nach einem reload mit apachectl reload
holt sich der Server nun die Zertifikate…
ungünstige schreibfehler zwingen einen zum mitdenken 😉
zeile 15 in example.org.conf:
Include etc/apache24/Includes/ssl.inc
am anfang fehlt ein /
zeile 12 in example.org.conf:
ErrorLog „/var/log/apache24/example.org-error.log
hinten fehlt ein “
bin dabei die tips für ubuntu LTS 18.04 anzuwenden 😉
gruß klaus lehmann
ps: wer mitlesen will: c’t 2018/4 steht was zu mod_md
im linux-magazin dieses jahres müsste auch was erschienen sein!
„der“ kofler hat ein ebook zu ubuntu LTS 18.04 herausgebracht, aber zum thema subdomains schweigen sich mehr oder wenige ALLE aus!
ausser Sie: Ekkehard Gehm. somit sehr loebenswert 😉
Also nach dem mein ServerRoot (Option in der httpd.conf) „/usr/local“ ist, ist das in Zeile 15 Absicht. Denn fehlt der / Am Anfang, sind die Pfade relativ zu eben diesem ServerRoot. Zu Zeile 12: Uuups 🙂
Generell sollte man ja eh immer ein wenig nachdenken, bevor man was Blind übernimmt.
die zeile in ssl.inc
<FilesMatch „\.(cgi|shtml|phtml|php)$“>
kann meines wissen nicht so stehen (bleiben). ich habe keine ahnung, über welchen sinn sie verfügt, aber es gibt diesbezüglich apache-fehler.
ausserdem muss man das modul „expores“ aktivieren!
das kann von distri zu distri und besonders im vergleich zu freeBSD ziemlich verschieden sein 😉
besser gehts (bei ubuntu) damit:
Header set Expires „Mon, 1 Jan 2020 12:00:00 GMT“
Header set Cache-Control „max-age=29030400, public“
Huch! Da ist was verloren gegangen… Das FilesMatch war auch nicht geschlossen! Ich habe das eben verbessert. Ich aktiviere so StdEnvVars für Scripte. ( Zitat:
)
Naja. Ich denke das sollte „mod_expires“ sein. Das muss man dann natürlich scharf schalten. Hat aber nichts mit mod_md zu tun, sondern mit den letzten Zeilen in Ihrem Kommentar…
Ich denke auch nicht, dass es extreme Unterschiede gibt ob ich den Apache unter Ubuntu oder unter nem richtigen OS laufen lasse. Höchsten evtl. ein paar Pfade…
mojn. die freuden vom nichtwissen zum thema „staging“ habe ich gestern nach noch kennengelernt ;-( . tja, zu viel getestet. und plötzlich gelingt nix mehr.
->ServerOption in http.conf (ist in ubuntu ausgeschaltet), vielleicht muss deshalb ein kein relativer pfad sein: bei DStoreDir /etc/apache2/md (für ubuntu)
-> richtiges OS. tztztz. wat iss hier richtig, wat iss falsch? oooh, die philosophie des abendlandes 😉 ich komme eigentlich von der heulsuse her, aber mein servermeister (strato), unterstützt die suse nicht mehr. ich hatte dann nur die wahl zwischen debil und urwald. und LTR 18.04 ist ja auch nicht verkehrt.
grüße, klaus lehmann
so. mein system steht!
1. auf (und das sollte jeder mal tun!) den folgenden ssl-kontroll-seiten kann man testen:
https://securityheaders.com/?q=vufindnet.de&followRedirects=on
https://www.ssllabs.com/ssltest/analyze.html?d=vufindnet.de&latest
(bei ssllabs cache clearen!)
2. wer erst mal mit „staging“ rumprobiert, was sehr klug ist, weil er von letsencrypt nicht „blockiert“ wird, muss von „staging“ zum regulären betrieb später wechseln: das geht so:
https://github.com/icing/mod_md/issues/99#issuecomment-409167507
3. für die sicherheit mit ssl habe ich folgendes getan (die urheber der guten gedanken sind mitangegeben!)
SSLEngine on
#wohl erst ab apache 2.5.xx
#SSLPolicy modern
BrowserMatch „.*MSIE.*“ \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
Header set Expires „Mon, 1 Jan 2020 12:00:00 GMT“
Header set Cache-Control „max-age=29030400, public“
SSLOptions +StdEnvVars
#tip von scott helme https://scotthelme.co.uk/a-new-security-header-referrer-policy/ 2018/078
Header always set Referrer-Policy strict-origin-when-cross-origin
#kein tip von ihm. nurkaround, um Header always set Feature-Policy drin zu haben, mit nix! 😉
Header always set Feature-Policy „“
#tip von https://spacehost.de/10-apache-header-eintraege-webseite-sicher-machen/ 2018/07
#===============================================================================
# HSTS verwenden Pflichtangabe: max-age““ Optional: „includeSubDomains“
Header set Strict-Transport-Security „max-age=31556926; includeSubDomains“
# Verhindert mime based attacks, nur IE und Chrome
Header set X-Content-Type-Options „nosniff“
# Aktiviert XSS Praeventions-/Filter-Tools Optional: mode=block
Header set X-XSS-Protection „1; mode=block“
# Begrenzung der frame/iframe Darstellung
Header append X-Frame-Options „SAMEORIGIN“
# Cookies nur ueber SSL and kein Javascript Zugriff Optional: Expires, Max-Age, Path, Domain
Header always edit Set-Cookie (.*) „$1; HttpOnly; Secure“
# Kein PHP und System-Version ausgeben
Header unset X-Powered-By
# Download / Lade Inhalte nur von Seiten die explizit erlaubt sind. Beispiel das alles von der eigenen Domain erlaubt allerdings keinerlei Externas:
Header set Content-Security-Policy „default-src ’none‘; script-src ’self‘; connect-src ’self‘; img-src ’self‘; style-src ’self‘;“
# Referrer Policy (siehe oben!)
#Header set Referrer-Policy „origin-when-cross-origin“
# Expect-CT fuer kommende Implementation Okt 2017 wo wird diese datei „reportOnly“ landen?
Header set Expect-CT „max-age=0; report-uri=https://vufindnet.de/reportOnly“
grüße, an alle, vom Klausi
ps: ich finds schaisse, daß man seine beiträge, die bei mir voll mit rächtschaipfählern sind, nicht nachträglich korrigieren kann. pech für den leser! 😉
Ohne das weiter kontrolliert zu haben 🙂 Hab gard anders zu tun 😉
Herzlichen Dank für diese Anleitung unter FreeBSD!
Hat auf Anhieb funktioniert und mir weitere Stunden Arbeit erspart!
Viele Grüße
Sidney