Howto: Verschlüsselung auf der WordPress-Oberfläche mit limitierten Ressourcen

SSL-Verschlüsselung für die Admin-Oberfläche scheitert oft an zwei drei Problemen:

  1. SSL-Zertifikate kosten viel Geld
  2. Es steht nur eine IP-Adresse zur Verfügung, jeder SSL-Host braucht aber eine eigene
  3. Die Anleitungen zu dem Thema sind oft recht verwirrend

Doch sowohl für Punkt 1 als auch für Punkt 2 gibt es so langsam eine Lösung. Diese möchte ich hier vorstellen, womit ich Punkt 3 löse. Ich werde dabei einen besonderen Fokus auf WordPress legen und nur kurz auf andere Software eingehen.

Als Basis verwende ich einen Debian 6.0 (Squeeze) Server, das Tutorial funktioniert aber identisch auch mit Ubuntu Servern. Für andere Linux-Distributionen muss man manchmal 2, 3 Dinge anpassen. Plesk dürfte bei meinen Lösungen nur Ärger machen, und ich glaube nicht, dass die Lösungen auf normalem Webhosting funktionieren. [UPDATE]Plesk unterstützt SNI offiziell.[/UPDATE]

Punkt 1: Kostenlose SSL Zertifikate

Das Unternehmen StartCOM bietet seit einiger Weile unter dem Markennamen StartSSL kostenlose SSL-Zertifikate für unkommerzielle Seiten an. Diese werden mittlerweile von den meisten modernen Browsern akzeptiert (sogar vom Internet Explorer seit September 2009), auf Wikipedia findet sich eine Liste dazu. Die Zertifikate sind ein Jahr gültig.

Nachdem man sich auf StartCOM registriert hat (der Vorgang ist etwas aufwändiger) validiert man zunächst seine Domains. Danach geht es zum eigentlichen Signier-Vorgang. Man erstellt auf seinem Linux-Server einen privaten SSL Key:

openssl req -new -nodes -sha256 -keyout meinzertifikat.key -out meinzertifikat.csr -newkey rsa:4096

Statt meinzertifikat sollte man natürlich einen Namen wählen der auf die Domain hinweist. Ich habe mir angewöhnt, den Domainnamen umzudrehen, also z.B. für dieses Blog org.sectio-aurea – aber die Namensgebung ist natürlich jedem selbst überlassen.

Bei den nachfolgenden Fragen gibt man dann seine Daten ein. Es empfiehlt sich, reale Daten anzugeben, die Daten sind nachher für den Website-Besucher öffentlich einsehbar. Beim Common Name muss man seine Domain angeben (incl. Subdomains). Also z.B. piwik.sectio-aurea.org wenn man seine Piwik-Installation in genau dieser Subdomain sichern möchte.

OpenSSL generiert dann zwei Dateien. Die meinzertifikat.key ist der Key, dieser darf niemals öffentlich werden. Die meinzertifikat.csr ist das das Certificate Signing Request, was wir für StartSSL brauchen. Den gesamten Inhalt der Datei kopieren wir also beim Signier-Prozess in das dazu gehörige Feld. StartSSL bietet zwar auch die Möglichkeit, auf der StartSSL Seite einen Key zu generieren – aber da gewöhnen wir uns gleich mal an, dass der Key niemals in fremde Hände gelangen darf, generieren ihn mit dem Befehl oben selbst und überspringen damit diesen Punkt.

Zwischendrin fragt StartSSL noch nach dem zu zertifizierenden Hostname. Wenn man eine Subdomain signieren will, nutzt man diese – also z.B. piwik.sectio-aurea.org. Wenn man sectio-aurea.org selbst signieren wollte trägt man da www ein – eine Subdomain ist Pflicht, www eignet sich da, da das viele Menschen eingeben.

Am Ende des Signierprozesses erhalten wir das Zertifikat, welches wir unter meinzertifikat.crt abspeichern. Außerdem brauchen wir noch das StartSSL Zwischenzertifikat:

wget -O meinzertifikat.chain.ca https://www.startssl.com/certs/sub.class1.server.ca.pem

Alle vier Dateien kopieren wir nun in den privaten Zertifikat-Speicher und passen die Dateirechte an:

sudo mv meinzertifikat.* /etc/ssl/private/
sudo chown root:root /etc/ssl/private/meinzertifikat.*
sudo chmod 400 /etc/ssl/private/meinzertifikat.*

Voila. Wir haben ein signiertes SSL Zertifikat an der richtigen Stelle um es weiterzuverwenden. Das machen wir nun mit jeder Domain und Subdomain, die wir absichern möchten. Ja, das kann verdammt viel Zeit kosten. Viel Spaß.

Punkt 2: Nur eine IP Adresse? Server Name Injection(SNI)!

Üblicherweise benötigt jedes SSL-Zertifikat eine eigene IP-Adresse, da die IP-Adresse als Entscheidungsmerkmal genutzt wurde, welches SSL-Zertifikat ausgeliefert wird vom Webserver. Der Hostname steht üblicherweise zum Zeitpunkt der Auslieferung des Zertifikates nicht zur Verfügung, er wird erst im zweiten Schritt übertragen.

SNI dreht den Abfragevorgang um und sendet erst den Hostname, um danach die Verschlüsselung zu starten. Dadurch ist eine Auslieferung des SSL-Zertifikates abhängig vom Hostname möglich. SNI wird von allen aktuellen Browsern unterstützt, der wohl größte Problemfall ist der Internet Explorer unter Windows XP: leider wird kein Internet Explorer unter Windows XP unterstützt. Ab Windows Vista wird jeder Internet Explorer unterstützt. Der zweite größere Problemfall ist Android 2.x, was leider auch noch recht weit verbreitet ist. Auf Wikipedia stehen Details zur SNI-Unterstützug.

Die Einrichtung beim Apache Webserver erfolgt dann wie bei normalen unverschlüsselten virtuellen Hosts. Dabei muss man aber sehr sauber arbeiten, ansonsten gibt es unerwartete Resultate und merkwürdige Fehlermeldungen.

Zunächst muss man definieren für welche Bereiche man virtuelle namenbasierte Hosts nutzen möchte. Dies geht in /etc/apache2/ports.conf:

NameVirtualHost *:80
NameVirtualHost 217.115.130.175:443
Listen 80
Listen 443

Diese Einträge sorgen dafür, dass man die IP-Adresse 217.115.130.175 für virtuelle namenbasierte Hosts mit SNI nutzt. Außerdem wird der unverschlüsselte Port 80 auf allen IP-Adressen für Virtuelle Hosts bereitgestellt. Um nun zunächst einen virtuellen Host für Port 80 bereitzustellen, erstellt man in /etc/apache2/sites-avaiable/ eine Datei z.B. mit dem Namen unverschluesselt. In diese trägt man dann seinen virtuellen Host ein:

<VirtualHost *:80> ServerAdmin mail@ernestoruge.de ServerName sectio-aurea.org ServerAlias www.sectio-aurea.org DocumentRoot /var/www/wordpress/httpdocs ErrorLog /var/log/apache2/wordpress_org.sectio-aurea.error.log CustomLog /var/log/apache2/wordpress_org.sectio-aurea.access.log combined […] <Directory /var/www/wordpress/httpdocs> […] Options -Indexes Order Deny,Allow Allow from All AllowOverride All RewriteEngine On </Directory> </VirtualHost>

Die Teile der Konfiguration welche etwas mit SuExec zu tun haben habe ich auskommentiert. Wichtig ist vor allem die erste Zeile: *:80 haben wir zuvor für die Verwendung für virtuelle namenbasierte Hosts definiert. Mit a2ensite unverschluesselt können wir nun die Seite aktivieren, mit service apache2 reload ist sie auch abrufbar. Dasselbe machen wir nun auch für die SSL-Hosts, auch hier erstellen wir in /etc/apache2/sites-avaiable eine Datei, nennen wir sie verschluesselt1:

<VirtualHost 217.115.130.175:443> ServerAdmin mail@ernestoruge.de ServerName sectio-aurea.org:443 DocumentRoot /var/www/wordpress/httpdocs ErrorLog /var/log/apache2/wordpress_org.sectio-aurea.error.log CustomLog /var/log/apache2/wordpress_org.sectio-aurea.access.log combined […] SSLEngine on SSLCertificateFile /etc/ssl/private/org.sectio-aurea.crt SSLCertificateKeyFile /etc/ssl/private/org.sectio-aurea.key SSLCertificateChainFile /etc/ssl/private/org.sectio-aurea.chain.ca <Directory /var/www/wordpress/httpdocs> […] Options -Indexes Order Deny,Allow Allow from all AllowOverride All </Directory> </VirtualHost>

Auch 217.115.130.175:443 haben wir zuvor für die Verwendung als virtuelle namenbasierte Hosts freigegeben. Wichtig ist natürlich auch der korrekte Pfad zu den Dateien des SSL-Zertifikates sowie der Port hinter dem ServerName. Mit a2ensite verschluesselt1 und service apache2 reload wird die Seite abrufbar.

Wir können nun einen zweiten virtuellen namenbasierten Host hinzufügen. Nennen wir ihn verschluesselt2 und erstellen ihn analog zum oben beschriebenen verschluesselt1. Aktivieren wir diesen, haben wir zwei funktionierende SSL Hosts unter derselben IP. Ziel erreicht!

Manch einer wird sich gefragt haben, warum ich durchgängig die IP bei den SSL-Hosts angebe. Ganz einfach: dadurch kann ich weitere verfügbare IPs für normale und damit für mehr Browser zugängliche Seiten nutzen – SNI wird dann nur bei dieser einen IP verwendet. Ein weiterer virtueller nicht namensbasierter Host wäre dann so denkbar:

<VirtualHost 83.169.35.183:443>
ServerAdmin mail@ernestoruge.de
ServerName mail.foej.net
DocumentRoot /srv/www/net.foej.mail/httpsdocs
ErrorLog /var/log/apache2/net.foej.mail.error.log
CustomLog /srv/www/apache2/net.foej.mail.access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/private/net.foej.mail.crt
SSLCertificateKeyFile /etc/ssl/private/net.foej.mail.key
SSLCertificateChainFile /etc/ssl/private/net.foej.mail.chain.ca
[...]
<Directory /var/www/net.foej.mail/httpsdocs>
[...]
Options -Indexes
Order Deny,Allow
Allow from all
AllowOverride All
</Directory>
</VirtualHost>

Hat man nur eine IP, kann man auch überall mit *:443 statt 217.115.130.175:443 arbeiten. Wichtig ist nur, dass es in sich konsistent ist. Dies ist auch bei allen anderen Sachen wichtig – z.B. sollte man nicht * und *:80 durchmischen, sollte aufpassen, dass man nicht mehrfach für dieselben Hosts geltende NameVirtualHost definiert etc. Sauberes strukturiertes in sich logisches Arbeiten ist hier die halbe Miete.

WordPress: Admin-Oberfläche nur mit SSL

Um die Admin-Oberfläche immer mit SSL zu verschlüsseln müssen wir noch die .htaccess von WordPress ergänzen. Außerdem habe ich mir angewöhnt, überall das www zu entfernen. Folgende Zeilen werden dafür ganz am Anfang der .htaccess von WordPress ergänzt:

# BEGIN custom
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /(.*)\ HTTP/ [NC]
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^/?(wp-admin/|wp-login\.php) https://%{HTTP_HOST}%{REQUEST_URI}\?%{QUERY_STRING} [R=301,QSA,L]
# END custom

Die beiden Zeilen RewriteEngine On und RewriteBase / müssen in den darunter liegenden Zeilen der .htaccess entfernt werden. Die erste Kombination von RewriteCond und RewriteRule ist für die Weiterleitung von www.sectio-aurea.org auf sectio-aurea.org (oder jedem beliebigen anderen Host, das geht sogar mit Subdomains, also www.blog.ruhrmobil-e.de wird automatisch zu blog.ruhrmobil-e.de) verantwortlich, die letzten drei Zeilen aus zwei RewriteCond und einer RewriteRule sind für die Weiterleitung auf die verschlüsselte Verbindung bei der wp-login.php und bei dem gesamten wp-admin Bereich verantwortlich. [UPDATE 14.08., 23:30: Bugfix in letzter RewriteRule]

Abschließende Worte

Mit dem obrigen Tutorial habe ich versucht, die Idee hinter kostenloser Verschlüsselung mehrerer Domains zu beschreiben. Es ist kein Copy & Paste Tutorial, da ich es als wichtig empfinde, dass man versteht, was man da tut, wenn man einen Server betreibt. Außerdem sind zu viele Punkte abhängig von Domains und Ähnlichem, so dass ein Copy & Paste Tutorial kaum möglich wäre.

Wenn ein oder mehrere Punkte unverständlich sind schreibt dies bitte im Kommentarbereich, dann ergänze ich gerne.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.