Mittwoch, 6. Mai 2015

Multi-Domain-Zertifikate (SAN) erstellen

Problem:

Auf einem Server (Apache) liegen mehrere Domains, die von Tomcat ausgeliefert werden. Die Verschlüsselung kann nicht mit einem normalen Zertifikat für jeweils eine Domain durch Tomcat erfolgen, weil dieser keine unterschiedlichen Zertifikate verwalten kann. Und Apache weiß überhaupt nichts von den unterschiedlichen Domains, die Trennung erfolgt bei mir erst eine Ebene weiter unten, beim Tomcat.
Man benötigt also ein SAN (Subject Alternative Name)-Zertifikat, das mehrere Domainnamen in einem Zertifikat unterbringt. Dieses kann dann dem Apache übergeben werden, dem dann egal sein kann, welche Domain gerade aufgerufen wurde, er hat immer das richtige Zertifikat parat.
Kostenlose SAN-Zertifikate habe ich leider keine gefunden, aber es gibt recht günstige Anbieter auf dem Markt. Bei meinem Versuch, dort ein Zertifikat zu beantragen und auf dem Server korrekt zum Laufen zu bringen, ergaben sich einige Stolperstellen, deshalb hier die Beschreibung des Lösungswegs.

Lösung:

Zertifikatsantrag erstellen

Bevor man bei einem Anbieter ein Zertifikat kaufen kann, muss man auf dem eigenen Server erst einen passenden Antrag zusammenstellen. Dabei erstellt man das Schlüsselpaar (öffentlicher und privater Schlüssel) sowie eine Antragsdatei, die einige Angaben über den eigenen Server enthält. Wie man diese Dateien erstellt, dafür gibt es im Netz viele Anleitungen. Allerdings unterscheidet sich das Erstellen von SAN-Zertifikatsanträgen an ein paar entscheidenden Stellen vom üblichen Vorgehen, schließlich braucht man nicht nur einen, sondern noch eine oder mehrere weitere (Alternative Name...) Domainadressen.
Zunächst erstellt man ein Schlüsselpaar (privat und öffentlich) mit dem Befehl
openssl genrsa -out example.com.key 2048 
wobei der Dateiname example.com beliebig ist.
Aus diesem Schlüssel (dem öffentlichen Teil natürlich, der private wird nicht "aus der Hand" gegeben!) kann man jetzt einen Zertifikatsantrag erstellen. Allerdings muss man dazu zunächst die Konfiguration des betreffenden Programms anpassen. Hierzu erstellt man ein File csr.conf mit folgendem Inhalt:
prompt = yes
distinguished_name = req_distinguished_name
req_extensions = req_ext

[req_distinguished_name]
commonName = Common Name
commonName_default = www.adresse1.de
countryName = Country Name
countryName_default = DE
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State
stateOrProvinceName_default = BW
localityName = City
localityName_default = Reutlingen
organizationName = Organization
organizationName_default = Meine Organisation
organizationalUnitName = Unit
organizationalUnitName_default = Meine Einrichtung

[req_ext]
subjectAltName = @alt_names


[alt_names]
DNS.1 = www.adresse2.de
DNS.2 = www.adresse3.de

Bei meinem Zertifikateanbieter mussten die Angaben zur Organisation usw. im Zertifikatsantrag stehen, blieben die Felder leer, konnte man den Antrag nicht abschließen, die Felder aber auch nicht nachträglich ausfüllen.
Jetzt kann man das Zertifikat erstellen mit dem Befehl:
openssl req -new -key example.com.key -config csr.conf -out example.com.csr
openssl fragt in der Folge ein paar weitere Parameter ab, bis schließlich das csr-File erstellt ist.
Jetzt kann man mit der csr-Datei den das Zertifikat beim Anbieter beantragen. Am Ende des Prozesses sollte man eine crt-Datei (oder pem-Datei) erhalten (oder nur den Inhalt, den man in eine neue Datei hineinkopiert).

SSL auf dem Server einrichten und aktivieren

Jetzt muss man die Dateien an den richtigen Ort verschieben. Bei Linux mit Apache sind das folgende Pfade:
Die crt/pem-Datei nach /etc/ssl/certs/
Die key-Datei nach /etc/ssl/private/

Jetzt muss man nur noch dem Apache beibringen, zukünftig mit SSL zu verschlüsseln. Dazu sind folgende Änderungen/Ergänzungen in /etc/apache2/sites-available/000-default.conf notwendig:
Sofern alle Anfragen, auch an http.//... auf https://... umgeleitet werden sollen, kommen in den Abschnitt <VirtualHost *:80> folgende Zeilen hinein:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
In den Abschnitt <VirtualHost *:443> (wenn nicht vorhanden, dann von oben kopieren und abändern, DocumentRoot sollte vorhanden sein) kommen folgende Zeilen:
SSLEngine On
SSLCertificateFile /etc/ssl/certs/example.com.pem
SSLCertificateKeyFile /etc/ssl/private/example.com.key
Bei meinem Zertifikatsanbieter war noch ein ChainFile notwendig, weil kein Root-Zertifikat des Anbieters in Firefox & Co installiert war. Sofern notwendig, wird dies mit der Zeile
SSLCertificateChainFile /etc/ssl/certs/XYZChain.pem
eingebunden. (Vorher muss das File natürlich vom Anbieter heruntergeladen und hierher kopiert werden...)
Jetzt kann man noch seine SSL-Konfiguration anpassen, indem man unsichere Protokolle ausschließt, hier nutzt man am besten den Mozilla-SSL-Configuration-Generator und fügt dann die Zeilen
SSLProtocol ...
SSLCipherSuite ...
SSLHonorCipherOrder on 
ein.
Nach einem Apache reload sollte jetzt die SSL-Verschlüsselung der beantragten URLs funktionieren, zu überprüfen mit http://sslzilla.de/zertifikatstest.php.




Mittwoch, 28. Januar 2015

https-Webserver unter Ubuntu 14.04 mit VirtualHosts

Problem:

Wie stellt man für einzelne VirtualHosts (in meinem Fall: Eine Moodle-Installation) die SSL-Verschlüsselung ein, ohne dass andere VirtualHosts unter der gleichen IP (in meinem Fall: Eine Joomla-Installation) betroffen sind?

Vorgehen:

  • Wie bei heise-online hervorragend beschrieben ein SSL-Zertifikat erstellen (kostenlos, recht einfach und problemlos bei StartSSL). Der Dateiname kann dabei die URL sein, muss aber nicht. Die 3 Dateien (Zertifikat, Schlüssel und Intermediate-Zertifikat)
  • Das SSL-Modul von Apache laden und die Konfiguration neu einlesen
sudo a2enmod ssl
sudo service apache2 force-reload 
  •  Wenn nicht schon vorhanden, neue VirtualHosts anlegen:
    • Die Datei /etc/apache2/sites-available/000-default.conf zweimal kopieren nach /etc/apache2/sites-available/www.domain1.de.conf und ...../www.domain2.de.conf
    • (Mindestens) folgende Angaben eintragen (in meinem Fall ist Domain1 die moodle-Installation und Domain2 die joomla-Installation)
    • Achtung: [ und ] bitte durch < und > ersetzen! Lässt sich im blöden Blogger-Editor nicht richtig formatieren!!!
[VirtualHost *:80´]
ServerName www.servername1.de
DocumentRoot /var/www/moodle/
[Directory /var/www/moodle]
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
[/Directory]
ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined
[/VirtualHost]

[VirtualHost *:443]
ServerName www.servername1.de
DocumentRoot /var/www/moodle/
[Directory /var/www/moodle]
    Options Indexes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    allow from all
[/Directory]
ErrorLog /var/log/apache2/error.log
LogLevel warn
CustomLog /var/log/apache2/access.log combined
SSLEngine on
SSLCertificateFile /etc/ssl/certs/moodle.crt
SSLCertificateKeyFile /etc/ssl/private/moodle.key
SSLCertificateChainFile /etc/ssl/certs/sub.class1.server.ca.pem
[/VirtualHost]
    • Das Entsprechende auch mit der zweiten Seite machen, allerdings nur mit dem ersten VirtualHost auf Port 80, wenn die zweite Seite nicht auch verschlüsselt werden soll.
    • Die neuen Seiten in Apache aktivieren:
sudo a2ensite www.domain1.de.conf
sudo a2ensite www.domain2.de.conf
sudo service apache2 force-reload 
  • Ab sofort sollte sich die Webseite auch über https://www.domain1.de aufrufen lassen. Will man das zum Standardverhalten machen (Weiterleitung von http auf https), findet sich hier eine ausreichende Anleitung dafür.
  • Anmerkung für Moodle: In Moodle kann man einstellen (Webseiten-Administration-http-Sicherheit), ob man SSL nur für den Login verwenden will oder für die gesamte Seite, wobei dann der Moodle-eigene Cache nicht funktioniert. Die Performance-Auswirkungen habe ich noch nicht getestet.