Rating A+ Klein

wall < "SSL via StartSSL"

Broadcast message from spillerm@unixe.de (pts/1) (Di Aug 04 12:20:48 2015):
4
Diesen Beitrag schrieb ich vor 3 Jahren. Behalte das beim Lesen bitte im Hinterkopf.

Die meisten Blog-Betreiber scheinen davon auszugehen, dass der Einsatz von SSL auf ihren Webseiten wenig sinnvoll ist: immerhin werden doch keine sensiblen Daten übertragen, oder? Und die Inhalte sind doch ohnehin für jeden im Netz abrufbar?

Der Einsatz von Verschlüsselung ist sinnvoll, grundsätzlich und in jeder Umgebung.

Nun — das stimmt so nicht. Denn überlege mal, wie du neue Artikel erstellst: richtig, du loggst dich in das Backend des Systems ein. Und ganz gleich, was du verwendest — WordPress, TYPO3, Drupal etc. — du gibst hier sehr wohl sensible Daten an, nämlich einen Usernamen, ein Passwort… Damit ist das erste Argument, das gegen den Einsatz von SSL sprechen soll, widerlegt. Und das zweite? Die Verbindung über HTTPS zu ermöglichen ist ein Mehrwert für jeden Besucher deiner Webseite, denn er kann nun darauf vertrauen, dass die empfangenen Daten echt sind, unterwegs nicht manipuliert wurden — dass die Daten genau die sind, die dein Server abschickte. Vor allem in öffentlichen WLANs und ähnlichem ein nicht zu unterschätzender Vorteil! Und: verschlüsselte Seiten werden inzwischen sogar beim Suchmaschinen-Ranking bevorzugt.

StartSSL - Your connection is not privateDie Ressourcen für die Verwendung von HTTPS (in Form von RAM und CPU) sind heutzutage vernachlässigbar. Zum Testen ist ein Self-Signed-Zertifikat schon ausreichend: du kannst es selbst erstellen, es fallen keine Kosten an, und es tut seinen Zweck. Der Nachteil hierbei ist jedoch: der Browser wird eine Warnung anzeigen, dass das Zertifikat von einer nicht vertrauenswürdigen Stelle ausgestellt wurde und somit unsicher ist. Der Besucher der Website hat dann zwei Möglichkeiten: die Webseite nicht zu besuchen (was nicht in deinem Interesse ist) oder das unsichere Zertifikat dennoch akzeptieren (was nicht in des Users Interesse ist).

Im produktiven Einsatz haben Self-Signed-Zertifikate nichts verloren.

Ich habe früher meine Zertifikate über CAcert beantragt, doch die haben es bis heute nicht geschafft, fest in den Browsern integriert zu werden. Hier muss der Besucher das CAcert-Root-Zertifikat in sein System importieren, was in den meisten Fällen zuviel des Guten ist. Für Angebote von Nerds für Nerds ganz okay sozusagen — ich möchte mich aber einer breiteren Öffentlichkeit zuwenden. Mit Let’s encrypt! wird eine interessante Alternative an den Start gehen, welche jedoch noch nicht verfügbar ist.

StartSSL - Your connection to this site is private.Königsdisziplin ist sicherlich ein offizielles Zertifikat von Thawte, GeoTrust oder einem ähnlichen Anbieter zu kaufen — jedoch liegen die Kosten hier für die Laufzeit eines Jahres durchaus dreistellig, was sich wiederum für kleinere Präsenzen absolut nicht rechnet. Ich habe mich für einen Mittelweg über StartSSL entschieden: ich erhalte hier ein für spiller.me sowie www.spiller.me für ein Jahr gültiges kostenfreies Zertifikat (Class 1). Die Verbindung wird im Browser grün angezeigt, da Zertifikate von dieser Stelle per default als vertrauenswürdig angesehen werden. [0. Auch netzpolitik.org nutzt ein StartSSL-Zertifikat, mindestens Class 2.] Ich möchte dir hier zeigen, wie du das Zertifikat erstellst und anschliessend einbindest. Alle Daten werden in einem Verzeichnis gesammelt — wo genau ist Geschmackssache. Ich nutze nginx und habe die Zertifikate dort hin gepackt, für apache2 analog. Die Pfade musst du in der Konfiguration deines Webservers entsprechend anpassen.

mkdir /etc/nginx/ssl

Account bei StartSSL erstellen und Domain validieren

Nachdem du dir einen Account bei StartSSL erstellt hast, wird für dich ein SSL-Clientzertifikat erzeugt, das du im Browser installieren solltest. Fortan dient es der Authentifizierung auf den Webseiten von StartSSL. Ist dein Account vollständig eingerichtet und freigeschaltet, musst du unter Validations Wizard → Domain Name Validation deine Domain (ohne www oder sonstiges!) hinzufügen. Ein Verfication Code wird an eine Mailadresse gesendet, die du dir aus einer Liste aussuchen kannst — stelle sicher, dass es diese Adresse auch wirklich gibt, denn den Code musst du anschliessend eingeben, um die Inhaberschaft der Domain zu bestätigen.

KEY und CSR für StartSSL erstellen

Jetzt erstellst du dir einen Key namens DEINEDOMAIN.key mit 4096 Bit Länge und ohne Passwort, da es in der Praxis ungünstig ist, bei jedem Restart des Webservers ein Passwort angeben zu müssen:

cd /etc/nginx/ssl
openssl genrsa -out DEINEDOMAIN.key 4096

Sobald das getan ist, kannst du dir einen Certificate Signing Request (CSR) erstellen; er enthält den öffentlichen Schlüssel und Angaben zum Inhaber des Schlüssels. Der Inhalt dieser .csr-Datei ist jener, der an StartSSL übermittelt werden muss!

openssl req -new -sha256 -key DEINEDOMAIN.key -out DEINEDOMAIN.csr

Welche Werte du hier einträgst ist im Prinzip gleichgültig; bei Class 1-Zertifikaten werden alle Angaben mit Ausnahme des öffentlichen Schlüssels von StartSSL verworfen, da sie ohnehin nicht verifiziert werden können.

Die StartSSL-Webseite bietet dir auch an, sowohl KEY als auch CSR auf deren Seite generieren zu lassen; davon rate ich dir ab! Der KEY ist geheim, und geheim soll er bleiben — generiere ihn selbst, gib ihn nicht aus der Hand, dann kann eigentlich nicht viel schief gehen.

Zertifikat bei StartSSL erstellen

  • Zur Erstellung deines Zertifikats navigierst du auf der Webseite von StartSSL zu Certificates Wizard; als Certificate Target wählst du im Drop-Down den Eintrag Web Server SSL/TLS Certificate.
  • Im nächsten Schritt bietet dir das System an, KEY und CSR zu erstellen — diesen Schritt überspringst du mit einem Klick auf Skip und kopierst den Inhalt deiner DEINEDOMAIN.csr in das Textfeld, das nun erscheint.
  • Anschliessend wirst du aufgefordert, aus der Liste der von dir validierten Domains eine auszuwählen, für die das Zertifikat gelten soll; triff diese Auswahl und bestätige sie.
  • Füge nun die Subdomain www hinzu — dein Zertifikat wird nun gelten für DEINEDOMAIN.tld und für www.DEINEDOMAIN.tld.

Nun wird dein Zertifikat im PEM-Format erstellt; kopiere den gesamten Inhalt des Textfeldes in die Zwischenablage und von dort in eine Datei namens /etc/nginx/ssl/DEINEDOMAIN.crt. Anschliessend werden noch die Rechte auf diese Dateien eingeschränkt:

chmod 0600 DEINEDOMAIN*

StartSSL Intermediate Certificate

Dein Webserver muss das Intermediate Certificate (IM) von StartSSL ausliefern, mit dem dein Zertifikat unterschrieben wurde — nur dann können alle Browser dein frisch erstelltes Zertifikat bis zu einer bekannten vertrauenswürdigen Instanz zurückverfolgen. (Übergehst du diesen Schritt, erhalten deine Besucher weiterhin die oben erwähnte Warnung.) Ziehe dir das Zertifikat vom StartSSL-Server:

wget https://www.startssl.com/certs/sub.class1.server.ca.pem

Die Website geht online…

Alle Vorarbeiten sind abgeschlossen; das Zertifikat kann nun in die Konfiguration deines Webservers eingebunden werden. Es ist sinnvoll, das nicht blind zu tun, sondern sich ein wenig zu informieren, was die verschiedenen Parameter bedeuten. Die nachfolgenden Konfigurationsschnipsel für nginx und apache2 sind erstmal sehr grundlegend, schliessen aber die unsicheren Protokolle SSLv2 und SSLv3 sowie die veralteten Cipher Suites komplett aus und lenken Anfragen auf HTTP ohne Umschweife auf HTTPS um.

Einbinden in nginx

Für nginx muss das Intermediate Certificate an das eigentliche Server-Zertifikat drangeklebt werden — einen Parameter wie SSLCertificateChainFile unter apache2 gibt es hier nicht.

cd /etc/nginx/ssl
cat sub.class1.server.ca.pem >> DEINEDOMAIN.crt
## /etc/nginx/sites-available/DEINEDOMAIN
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
 
server {
        listen 80;
        server_name www.DEINEDOMAIN.tld;
	rewrite ^(.*) https://www.DEINEDOMAIN.tld$1 permanent;
}
 
server {
  listen 443 ssl;
  server_name www.DEINEDOMAIN.tld;
  ssl on;
  ssl_certificate /etc/nginx/ssl/DEINEDOMAIN.crt;
  ssl_certificate_key /etc/nginx/ssl/DEINEDOMAIN.key;
  ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
  ssl_ciphers "HIGH:!aNULL:!MD5:!3DES:!CAMELLIA:!AES128";
  ssl_prefer_server_ciphers on;
  ...

Einbinden in apache2

## /etc/apache2/sites-available/DEINEDOMAIN.conf
<VirtualHost x.x.x.x:443>
  ServerName DEINEDOMAIN.tld
  ServerAdmin webmaster@DEINEDOMAIN.tld
  CustomLog /var/log/apache2/DEINEDOMAIN.log combined
 
  SSLEngine On
  SSLCertificateFile /etc/apache2/ssl/DEINEDOMAIN.key
  SSLCertificateKeyFile /etc/apache2/ssl/DEINEDOMAIN.crt
  SSLCertificateChainFile /etc/apache2/ssl/sub.class1.server.ca.pem
 
  <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  </IfModule>
 
  ...
## /etc/apache2/mods-available/ssl.conf
<IfModule mod_ssl.c>
  SSLRandomSeed startup builtin
  SSLRandomSeed startup file:/dev/urandom 512
  SSLRandomSeed connect builtin
  SSLRandomSeed connect file:/dev/urandom 512
  AddType application/x-x509-ca-cert .crt
  AddType application/x-pkcs7-crl .crl
  SSLPassPhraseDialog exec:/usr/share/apache2/ask-for-passphrase
  SSLSessionCache         shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
  SSLSessionCacheTimeout  300
  SSLHonorCipherOrder on
  SSLCipherSuite "HIGH:!aNULL:!MD5:!3DES:!CAMELLIA:!AES128";
  SSLProtocol all -SSLv2 -SSLv3
</IfModule>

Testen via SSL Labs

StartSSL - SSL Labs Rating A+Sobald du dein Zertifikat eingebunden hast und der Webserver nach einem Restart fehlerfrei läuft (Logfiles beachten!), solltest du das Setup gegentesten — beispielsweise über den Service der SSL Labs. Das Rating ist vergleichbar mit dem der Energieeffizienzklasse — F ist ganz schlecht, A ist ziemlich gut und A+ noch besser.

Einen Protocol Support von 100% könntest du beispielsweise erreichen, indem du als einziges Protokoll TLSv1.2 zulässt; das ist technisch machbar, schliesst aber viele (für meine Begriffe zu viele) ältere Clients aus, die deine Webseite dann überhaupt nicht aufrufen können — die Wahl der Ciphers ist ein Trade-Off zwischen Sicherheit und Nutzbarkeit des Systems. Und dass ich lediglich 90% Key Exchange habe begründet sich darauf, dass ich beim Erstellen meines Zertifikats gepennt und eine Schlüssellänge von 2048 Bit (statt 4096) angegeben habe. Grrr. Aber das bestehende Zertifikat einfach so widerrufen und ein neues anfordern ist nicht: das kostet bei StartSSL um die $25. Aber nunja — ich kann damit leben.

Schrittweise kannst du anhand des Outputs nun Verbesserungen einführen — beispielsweise, indem du an folgenden Punkten ansetzt:

  • Verwendung eigener Diffie-Hellmann-Parameter: sie werden per openssl dhparam -out dhparams.pem 4096 erstellt und anschliessend per ssl_dhparam in die Konfiguration des nginx eingebunden; bei Verwendung von apache2 hilft lediglich ein Upgrade auf eine Version > 2.4.7, dann wird automatisch ein hinreichend starker Key verwendet
  • OCSP (Online Certificate Status Protocol, RFC 6960)
  • HSTS (HTTP Strict Transport Security, RFC 6797)

UnterschriftUnd wie das geht, zeige ich dir im nächsten Posting :-)

4
  1. Hiho! Kann es sein, dass TSLv1.2 mit Ubuntu 14.04.3 gar nicht drin ist? Wenn ich das entsprechend einstelle beschwert sich SSL Labs deswegen und ich bekomme eine miese C-Wertung. Nginx 1.8.0-1+trusty1 kommt aus Launchpad[1] und OpenSSL sollte das in der Version 1.0.1f-1ubuntu2.15 doch auch hinbekommen!?

    [1] http://ppa.launchpad.net/nginx/stable/ubuntu/

    • Habe inzwischen mit der Hilfe vom Ubuntu-Paket-Maintainer rausgefunden woran es lage. Ich hatte, wie hier auch, die ssl_protocols im server-Kontext definiert. Allerdings hatte ich auch noch ältere Configs, bei denen lediglich TLSv1 aktiviert war. Das hatte offensichtlich alle anderen Site-Configs dann auf den kleinsten gemeinsamen Nenner runtergezogen. Jetzt steht das brav in der nginx.conf und ich habe auch meine A+-Wertung. :)

      • Prima! Ich war hier so in Kindergeburtstags-Vorbereitungen verstrickt, dass ich erst jetzt zum Antworten komme. Auf dieses »auf den kleinsten gemeinsamen Nenner runterziehen« bin ich nämlich auch schon reingefallen ;-) Ich habe es für mich mit einer für alle VHosts gültigen ssl.conf gelöst. Viel Spass :-)

        • Kein Ding. Ich hoffe die Party hatte beim der/dem Kleinen Anklang gefunden!

          Aber das mit den ssl_protocols ist besonders bitte, da in der Doku[1] dazu nichts steht und sogar noch explizit der Kontext http und server angegeben ist. Werde mal schauen, wo man da einen Bug-Report tätigen kann.

          [1] http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols

          • Ah, und hier haben wir den Grund: https://trac.nginx.org/nginx/ticket/766
            Verschiedene Protokollkombinationen kann man nur auf untersch. Ports betreiben.

            Danke dir übrigens für den Tipp mit der ssl.conf. Das werde ich jetzt auch so machen. Dann kann ich nämlich weiterhin alles automatisch über Pakete installieren und muss nicht händisch an der nginx.conf rumfummeln.

  2. Bits United

    Dieses Thema steht bei mir demnächst auch an, wenn dieses verfi**te PHP wieder läuft. Bist du auf Linux oder FreeBSD unterwegs?

  3. für eine gute cipher auswahl empfehle ich gerne https://cipherli.st/ – mitlerweile eine gute anlaufstelle auch für nicht generische web software.

Keine weitere Reaktionen mehr möglich.