Skip to content

Der eigene Webserver mit SSL/TLS

Datenströme im Netz zu verschlüsseln ist wichtig, aber auch zunehmend Allgemeingut. Telnet würde sicherlich niemand mehr zum Zugriff auf einen entfernten Rechner nutzen; stattdessen nimmt man SSH. Auch bei anderen Protokollen ist die Übertragung von Passworten im Klartext schon lange out: es fing an mit APOP für den Zugriff über POP3 und CRAM-MD5 für SMTP-Auth, und schon etliche Jahre nutze ich nur noch POP3S/IMAPS/SMTPS, also eine komplette Verschlüsselung des gesamten Datenstroms. So hat auch das auf SSH basierende SCP/SFTP schon lange FTP ersetzt, und nachdem sich mittlerweile auch NNTPS und der verschlüsselte Zugriff auf IRC-Server verbreitet haben, bleiben nur noch wenige Protokolle “offen”.

Selbstverständlich sollte auch - zumindest - die Übertragung von Passworten via HTTP gesichert werden, was die Einrichtung von HTTPS erfordert. Je mehr sich webbasierte Dienste und Apps verbreiten, desto wichtiger ist das. Es ist allerdings - leider - nicht ganz so einfach.

SSL-/TLS-Zertifikate und deren Prüfung

Das liegt darin, dass Verschlüsselung allein zumindest im Grundsatz nicht genügt - wichtig ist auch Authentifizierung, also die Überprüfung, ob man auch mit der richtigen Gegenstelle spricht oder sich ein Dritter, der “Man in the middle”, dazwischengehängt hat. Zu einer mittels SSL/TLS (in Zukunft: SSL als Sammelbegriff für beides) gesicherten Verbindung gehört daher - eigentlich - auch immer die Überprüfung des Zertifikats der Gegenstelle. Dazu muss man entweder den Fingerprint des Zertifikats kennen und prüfen - PGP/GPG lässt grüßen -, oder man begnügt sich damit, dass eine Zertifizierungsstelle die Echtheit des Zertifikats bestätigt hat (und hofft auf deren Sorgfalt; eine Hoffnung, die die Praxis bereits vielfach enttäuscht hat).

Will man selbst verschlüsselte Zugänge anbieten, genügt es für die meisten Dienste, ein selbst-signiertes Zertifikat zu erstellen und den Nutzern den Fingerprint mitzuteilen. In der Regel ist der Nutzerkreis selbstgehosteter Dienste nämlich überschaubar: der private Mailserver wird zum Versand und zum Mailabruf in der Regel nur selbst oder allenfalls von Familienmitgliedern und Freunden genutzt, die dem selbst-signierten Zertifikat dann vertrauen können. Nicht unüblich ist es auch, auf eine Zertifikatsprüfung zu verzichten und jedes präsentierte Zertifikat zu akzeptieren, also nur die Verschlüsselung zu nutzen und der Gegenstelle zu vertrauen. Das ist insofern nachvollziehbar, als es deutlich einfacher ist, (unverschlüsselten) Datenverkehr mitzulesen als sich als “Man in the middle” mit einem falschen Zertifikat in den verschlüsselten Datenstrom einzuklinken.

HTTPS im Speziellen

Bei Webdiensten liegt der Fall hingegen etwas anders: zumeist erfolgt der Zugriff für die Allgemeinheit - der nicht zwingend einer Absicherung durch Verschlüsselung bedürfte - über dieselbe “Domain” (ich verwende den Begriff hier umgangssprachlich; richtiger wäre “Hostname”) wie die Administration. Ein Blog, bspw., das unter http://meinblog.example/ zugänglich ist, wird meist über http://meinblog.example/admin/ verwaltet, nicht aber über http://admin.meinblog.example/. Ich muss also damit rechnen, dass auch die Allgemeinheit auf meine Webseiten über HTTPS zugreift, oder ich will das sogar erzwingen, damit ich nicht versehentlich Passwörter über eine ungeschützte Verbindung übertrage.

Dann habe ich aber ein Problem: mein selbst-signiertes Zertifikat ist den Besuchern der Webseite natürlich unbekannt, und Browser generieren für diesen Anwendungsfall zunehmend auffälligere Warn- und Fehlermeldungen, die einen Zugriff auf die Seite entweder ganz unterbinden oder doch arg erschweren und den Durchschnittsnutzer abschrecken (was ja auch Sinn der Sache ist).

Virtual Hosting

Zu diesem Problem der Fehlermeldungen bei selbst-signierten Zertifikaten kommt noch ein ein weiteres hinzu: es ist üblich, über einen Webserver (auf ein- und derselben IP-Adresse) eine Vielzahl von “Domains” (also getrennten Webseiten) anzubieten. Bei größeren Anbietern können das hunderte oder zigtausende Nutzer sein, die sich da auf einem Host tummeln, aber auch der private Nutzer hat vielleicht neben seiner Homepage unter meine-domain.example auch noch ein Blog unter blog.meine-domain.example oder will schlicht seine Webseiten sowohl unter meine-domain.example als auch unter www.meine-domain.example erreichbar machen. Das sind aber alles unterschiedliche Hostnamen, und da jedes SSL-Zertifikat angeben muss, für welchen Hostnamen es gültig ist, haben wir das nächste Problem: liefert der Webserver für www.meine-domain.example das Zertifikat für meine-domain.example aus, verfallen die Warnmeldungen im Browser nicht selten in eine noch schrillere Tonlage.

Es ist leider auch nicht so einfach, für jede “Domain” ein eigenes Zertifikat zu präsentieren. Der Zugriff auf solche virtual hosts erfolgt nämlich in der Weise, dass der Browser einen Header mitschickt, aus dem sich ergibt, auf welche “Domain” er zugreifen will. Für diesen Zugriff muss aber die verschlüsselte Verbindung schon stehen; andersherum weiss der Server beim Verbindungsaufbau noch nicht, welche “Domain” angefragt wird, und kann daher auch nicht das jeweils “richtige” Zertifikat ausliefern.

Was also tun?

Lösungswege

Über die Jahre habe ich verschiedene - allesamt mehr oder weniger unbefriedigende - Möglichkeiten getestet, um diesem Problem zu Leibe zu rücken.

Die eigene CA

Angefangen habe ich vor gut einem Jahrzehnt mit einer eigenen Zertifizierungsstelle, die meine SSL-Zertifikate signiert. Dann reicht es nämlich, das Stammzertifikat dieser Zertifizierungsstelle dem Browser (und ggf. dem Mailprogramm) als gültig unterzuschieben, und alle anderen Zertifikate werden automatisch akzeptiert. Das erleichtert zumindest einmal mir selbst (und Freunden und Bekannten, die mir ausreichend trauen) den Umgang mit verschiedenen Servern und ggf. verschiedenen Hostnamen, behebt aber nicht das Problem, dass das Zertifikat immer nur für einen Hostnamen (eine “Domain”) gültig ist, und hilft auch den Webseitenbesuchern nicht.

Ich habe mich daher in der Regel darauf beschränkt, HTTPS nur ergänzend anzubieten oder nur für solche Webseiten, die ausschließlich intern genutzt werden und sich nicht an die Allgemeinheit richten. Professionell geht aber fraglos anders.

SAN

Danach habe ich mich mit Subject Alternate Names, kurz SAN, vertraut gemacht. Es ist nämlich möglich, einem Zertifikat mitzugeben, dass es für mehr als einen Hostnamen gültig ist. Zum einen gibt es - nicht empfehlenswerte - sog. “Wildcard-Zertifikate”, die für alle Subdomains einer bestimmten Domain gültig sind, bspw. *.domain.example. Zum anderen gibt es SAN - zusätzliche Hostnamen, für die das jeweilige Zertifikat auch gilt. Die kann man bei der Erstellung des Zertifikats mit angeben.

Das funktioniert ganz gut, löst aber zum einen nicht das Problem der fehlenden allgemeinen Akzeptanz des Zertifikats und schafft zudem zwei neue Schwierigkeiten. Zum einen kann jeder Besucher durch Ansicht des Zertifikats feststellen, welche Webseiten auf dem Server sonst noch so gehostet werden (was nicht immer optimal ist), zum anderen braucht es für jede neue “Domain”, auf die auch per HTTPS zugegriffen werden soll, auch ein komplett neues Zertifikat.

SNI

Dem strukturellen Problem, dass der Server erst die verschlüsselte Verbindung aufbauen muss und danach erfährt, für welche “Domain” er das eigentlich tun soll, ist man mit Server Name Indication, kurz SNI, zu Leibe gerückt. Das ist eine Erweiterung des TLS-Protokolls, die es dem Client erlaubt, beim Verbindungsaufbau bereits mitzuteilen, aus welcher “Domain” er später Webseiten abrufen will, so dass der Server ihm dann das richtige Zertifikat präsentieren kann. So kann auch der Webserver für jede “Domain” ein eigenes Zertifikat anbieten.

Mittlerweile darf man davon ausgehen, dass SNI so verbreitet ist, dass man es im praktischen Betrieb voraussetzen kann: Firefox unterstützt es seit Version 2.0, der Internet Explorer seit Version 7 und Windows Vista (nicht unter Windows XP), und auch wget sollte das seit 2012 beherrschen.

Kommerzielle Zertifikate

Dies wiederum ermöglicht es, auf kommerzielle SSL-Zertifikate zurückzugreifen. Deren Anbieter lassen sich nämlich ihre Dienste bei “Wildcard-Zertifikaten” oder solchen mit einer Vielzahl von Hostnamen (oder auch bei erweiterter Validierung der “Domains”, für die das Zertifikat gelten soll) geradezu fürstlich bezahlen; Zertifikate für nur ein oder zwei Namen (also bspw. domain.example und www.domain.example) sind hingegen erschwinglich oder gar kostenlos. SNI macht es jetzt möglich, jeder “Domain” ihr eigenes günstiges Zertifikat zuzuweisen, bspw. von StartCom, einem Anbieter, der Zertifikate für maximal zwei “Domains” kostenlos abgibt (dann allerdings für den Widerruf eines kompromittierten Zertifikats Geld verlangt - nun ja).

So kann man dann allmählich vernünftig mit SSL arbeiten.

Die Zukunft: letsencrypt

Neuerdings befindet sich zudem mit Let’s Encrypt ein Anbieter am Start, der sich kostenloses, freies und massentaugliches SSL/TLS auf die Fahnen geschrieben hat:

Let’s Encrypt is a new Certificate Authority:
It’s free, automated, and open.

Dazu werde ich später mehr berichten.

SSL-Zertifikate und Apache

Nach der Theorie nun etwas Praxis: wie richte ich beim Apache-Webserver einen virtual hosts mit SSL ein?

Im Prinzip ist das recht einfach; Debian liefert bspw. eine entsprechende Konfiguration schon mit. Ich setze im Folgenden voraus, dass sowohl passende SSL-Zertifikate (mit dem zugehörigen private key in entschlüsselter Form, d.h. ohne Passwortschutz) vorhanden als auch virtual hosts grundsätzlich eingerichtet sind. Die Zertifikate speichere ich im Verzeichnis /etc/apache2/ssl.

Eine Basis-Konfiguration könnte dann - mit einem Zertifikat von StartCom - bspw. so aussehen:

<VirtualHost *:443>
    ServerName meine-domain.example
    ServerAlias www.meine-domain.example

    DocumentRoot /var/www/meine-domain.example

    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/meine-domain.example.crt
    SSLCertificateKeyFile /etc/apache2/ssl/meine-domain.example.key
    SSLCertificateChainFile /etc/apache2/ssl/sub.class1.server.ca.pem
</VirtualHost>

Will man alle Zugriff von HTTP auf HTTPS umleiten, kann man bspw. folgendes ergänzen:

<VirtualHost *:80>
    ServerName meine-domain.example
    ServerAlias www.meine-domain.example

    Redirect / https://meine-domain.example/
</VirtualHost>

Disclaimer

SSL/TLS, der Umgang mit Zertifikaten und die Konfiguration des Apache sind ein weites Feld, für das ich zudem kein Spezialist bin.

Dieser Beitrag will einen kurzen, knappen und daher notwendigerweise unvollständigen Überblick zu diesem Thema geben und zur eigenen Beschäftigung damit anregen. Ich habe daher manches vereinfacht, anderes weggelassen, wieder anderes - absichtlich oder unabsichtlich - ungenau dargestellt.

Dies ist kein Tutorial, und die am Schluss genannten Beispiele sind nicht zur 1:1-Übernahme via copy & paste geeignet.

Wenn sich Fehler eingeschlichen haben, bin ich über Kommentare dankbar - und auch Ergänzungen nehme ich natürlich gerne entgegen.

Trackbacks

Jens Kubieziel am : Jens Kubieziel via Twitter

Vorschau anzeigen
@Szlauszaf Kannst du meinen Kommentar noch um die Tags bereinigen. In der Vorschau sah er gut aus. Jetzt ist da HTML https://t.co/QmWu6lNgPy

Dirk Deimeke am : Dirk Deimeke via Twitter

Vorschau anzeigen
RT @Szlauszaf: Netz-Rettung-Recht: Der eigene Webserver mit SSL/TLS https://t.co/SHAaZRsVJP #apache #ssl

Netz - Rettung - Recht am : SSL/TLS mit Let's Encrypt

Vorschau anzeigen
Bereits vergangene Woche berichtete ich von meinen Irrungen und Wirrungen des letzten Jahrzehnts mit SSL/TLS im Web. Erst Ende 2015 hatte ich mich aufgerafft, über StartCom für einige Domains Zertifikate erstellen zu lassen, und parallel die Berichterstat

Netz - Rettung - Recht am : SSL/TLS für Fortgeschrittene

Vorschau anzeigen
Hat man dem eigenen Webserver erfolgreich SSL beigebracht und für ein valides Zertifikat gesorgt, bspw. mithilfe von Let’s Encrypt, finden sich in der Konfigurationsdatei (bei Debian: /etc/apache2/mods-available/ssl.conf) noch etliche Schrauben und

Kommentare

Ansicht der Kommentare: Linear | Verschachtelt

Jens Link am :

Jens Link

Wer sein Setup dann testen will sollte einen Blick auf http://testssl.sh werfen. Und wer noch tiefer in die Materie einsteigen will dem seit "Bulletproof SSL und TLS" von Ivan Ristić ans Herz gelegt.

Jens Kubieziel am :

Jens Kubieziel

Bezüglich der Einstellungen im Apachen oder einem anderen Server empfiehlt sich ein Blick auf die Seite BetterCrypto.org. Die bieten konkrete Hinweise, welcher Cipherstring mit eingetragen werden sollte.

Daneben sollte am Ende der Einstellungen die Webseite mit SSLLabs getestet werden. Die Seite gibt einen guten Überblick über mögliche Probleme und zeigt mit einer Art Benotung, wie gut die Einstellungen sind. Deine Seite erhält derzeit ein C, weil er noch SSL3 und RC4 unterstützt.

Schließlich ist es durchaus sinnvoll, HSTS einzusetzen. Also ein Protokoll, was dem Browser sagt, dass die Seite HTTPS unterstützt und der Browser wird in Zukunft immer versuchen, die Seite über HSTS zu erreichen. Auch gibt es eine Testseite. SecurityHeader.io zeigt, welche HTTP-Header gesetzt sind. Bei deiner Seite ist noch etwas zu tun. :-) (Nicht alle der Header sollte man sofort anschalten, sondern vorher wissen, was man tut.)

Thomas Hochstein am :

Thomas Hochstein

Danke für die umfangreichen Hinweise!

Das ist aus meiner Sicht der "fortgeschrittene" Teil, von dem ich bisher aus Lektüre wusste, dass es ihn gibt - und auch von allen hier genannten Diensten habe ich schon einmal gehört -, mit dem ich mich bisher aber nicht beschäftigt hatte, weil es bis vor kurzem überhaupt schon an den Hausaufgaben (SSL/TLS für zumindest die meisten "Domains" und Umstellung auf nicht mehr nur selbst-signierte Zertifikate) mangelte. Ich bin mit der Umstellung auch noch nicht vollständig durch, obschon Let’s Encrypt - dazu schreibe ich spätestens kommende Woche noch etwas - da doch vieles erleichtert.

Insofern hilft mir diese Zusammenstellung sehr; die kann ich dann, wenn ich soweit bin, einfach abarbeiten, ohne mir die Quellen wieder zusammensuchen zu müssen …

Thomas Hochstein am :

Thomas Hochstein

Immerhin - die Maschine mit dem frisch installierten Debian Jessie kommt aus dem Stand bei SSLLabs auf "A-". Ist also offenbar zunächst mal eine Frage der Aktualität der Standardkonfiguration, und dann noch etwas Recherche bzgl. der von SecurityHeader.io bemängelten Header …

Dirk Deimeke am :

Dirk Deimeke

Danke für den Artikel, Thomas.

Zwei Ergänzungen möchte ich machen. Zum Einen ist es wichtig, Protokolle, die als nicht mehr sicher gelten aus der Serverkonfigruation zu verbannen. Dabei kann der Mozilla SSL Configuration Generator helfen.

Der zweite Punkt betrifft die Weiterleitung, die ich noch etwas ergänzen würde:

CODE:
<VirtualHost *:80>         ServerName www.deimeke.net         RewriteEngine on         RewriteCond %{HTTP_HOST}   !^$         RewriteRule ^/(.*)         https://www.deimeke.net/$1 [L,R] </VirtualHost>

Damit ist kompletter Umzug von http auf https möglich, ohne, dass Links ihre Gültigkeit verlieren.

Thomas Hochstein am :

Thomas Hochstein

Macht es denn im Ergebnis (!) einen Unterschied, ob http://xyz.example auf https//xyz.example per Redirect weiterleitet (was auch alle URLs "innerhalb" dieser "Domain" betrifft, also bspw. http:://xyz.example/blog/startseite.html), oder ob man Deinen Weg geht (der, wenn meine mangelhaften Kenntnisse des Apachen mich nicht täuschen, doch auch einen Redirect auslöst)?

Dirk Deimeke am :

Dirk Deimeke

Vielleicht hat sich das bei neueren Apacheversionen geändert, aber zumindest früher war es so, dass für www.example.com ein redirect von

/ auf https://www.example.com/

Nur den Aufruf von http://www.example.com/ umgeleitet hat, nicht aber von http://www.example.com/start.html.

Aus diesem Grund gibt es die rewrite rule, die per RegEx den Teil hinter dem / ersetzt (da heisst es übrigens nicht "em", sondern Klammer auf, Punkt, Stern, Klammer zu).

Thomas Hochstein am :

Thomas Hochstein

Ich habe da früher - statt des Wechsels von Redirect zu Rewrite - immer RedirectMatch verwendet, bis mir jemand erklärt hat (oder mir aufgefallen ist), dass es das gar nicht braucht und die Angelegenheit nur unnötig kompliziert. Einigermaßen aktuelle Apachen ("einigermaßen aktuell" im Sinne von Debian old-stable, also 2.2.x) können das so.

Tut mir leid wegen des vergurkten Codebeispiels, das ich jetzt repariert habe. Das ist der Fluch der Flexibilität - die Parser für Markdown und BBCode kommen sich da offensichtlich in die Quere. (Ich habe nicht probiert, ob es auch mit reinem Markdown gegangen wäre.)

Kommentar schreiben

HTML-Tags werden in ihre Entities umgewandelt.
Markdown-Formatierung erlaubt
Standard-Text Smilies wie :-) und ;-) werden zu Bildern konvertiert.
BBCode-Formatierung erlaubt
Gravatar, Identicon/Ycon Autoren-Bilder werden unterstützt.
Formular-Optionen
tweetbackcheck