Im Jahre 2020 sollte Verschlüsselung Standard für die Übertragung von Daten mit Webservern sein. Spätestens seitdem Browser mit dezenten “Not Secure”-Hinweisen auf die Gefahren unverschlüsselter Datenübertragung hinweisen, bietet es sich an konsequent auf SSL (korrekter eigentlich TLS) zu setzen.

Daher macht es Sinn auch die lokale Umgebung SSL-fähig zu machen um gleich während der Entwicklung festzustellen, ob es Lücken in der Verschlüsselung gibt oder ob die Anwendung überhaupt mit SSL sauber funktioniert.

Kernstück der Verschlüsselung sind Zertifikate, die den Webserver identifizieren und den Datenstrom nach außen unleserlich machen. Aber woher bekommt man ein solches Zertifikat für den lokalen Einsatz?

(Hinweis: Um meine lokale Konfiguration und mein Vorhaben besser zu verstehen, ist es sinnvoll vorher Teil 1 und Teil 2 dieser kleinen Artikelserie zu lesen.)

Ein lokales SSL-Zertifikat erzeugen

Die Antwort ist einfach: das Zertifikat kann selbst erzeugt werden. Dafür brauchen wir zunächst einmal das Paket openssl.

david@mars ~ $ sudo apt-get install openssl

Zudem sollten wir sicherstellen, dass das Apache Modul ssl aktiviert ist:

david@mars ~ $ sudo a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
  service apache2 restart

Im nächsten Schritt erzeugen wir das Zertifikat. Es besteht aus dem privaten Schlüssel apache.key und dem eigentlichen Zertifikat apache.pem:

david@mars ~ $ sudo mkdir /etc/apache2/ssl
david@mars ~ $ sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.pem

Während der Erstellung sind einige Angaben zu machen, die dann auch im Zertifikat auftauchen:

Generating a 2048 bit RSA private key
..........................................................................................................+++
................................................+++
writing new private key to '/etc/apache2/ssl/apache.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:Leipzig
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Gruniversal
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:gruniversal.mars
Email Address []:

SSL-Konfiguration im Apache Webserver

Nun muss das Zertifikat noch in den Webserver eingebunden und die Domain entsprechend SSL-fähig gemacht werden. Die zentrale Einbindung kann über die /etc/apache2/sites-available/default-ssl.conf erfolgen:

david@mars ~ $ sudo vim /etc/apache2/sites-available/default-ssl.conf
<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin webmaster@localhost

        [...]

        # SSL Engine Switch:
        # Enable/Disable SSL for this virtual host.
        SSLEngine on

        SSLCertificateFile /etc/apache2/ssl/apache.pem
        SSLCertificateKeyFile /etc/apache2/ssl/apache.key

        [...]

    </VirtualHost>
</IfModule>

Damit die Konfiguration überhaupt eingelesen wird, muss die Site default-ssl.conf natürlich auch aktiviert sein. Zudem ist es nach jeder Änderung der Konfiguration erforderlich diese im Apache neu einzulesen:

david@mars ~ $ sudo a2ensite default-ssl.conf
Enabling site default-ssl.
To activate the new configuration, you need to run:
  service apache2 reload
david@mars ~ $ sudo service apache2 reload

Danach sollte der Webserver zumindest für einen Aufruf von https://localhost/ schon mal das Zertifikat kennen. Der Browser wird aller Wahrscheinlichkeit nach aber einen Fehler anzeigen, da er das Zertifikat nicht validieren kann.

Mit folgendem Aufruf auf Kommandozeile kann man prüfen, dass das Zertifikat eingebunden ist und die Verbindung grundsätzlich funktioniert:

david@mars ~ $ openssl s_client -connect localhost:443
depth=0 C = DE, ST = Saxony, L = Leipzig, O = Gruniversal, CN = gruniversal.mars
verify return:1
---
Certificate chain
 0 s:/C=DE/ST=Saxony/L=Leipzig/O=Gruniversal/CN=gruniversal.mars
   i:/C=DE/ST=Saxony/L=Leipzig/O=Gruniversal/CN=gruniversal.mars
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDnTCCAoWgAwIBAgIJAMY40K0IUAxCMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNV
BAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMRAwDgYDVQQHDAdMZWlwemlnMRQw
[...]

Sollte das nicht klappen, muss das nicht an der obigen Konfiguration liegen, es kann auch einfach sein, dass der Apache nicht auf Port 443 lauscht:

david@mars ~ $ openssl s_client -connect localhost:443
connect: Connection refused
connect:errno=111

In diesem Fall ist eine Anpassung der /etc/apache2/ports.conf erforderlich. Dort sollten beispielsweise folgende Zeilen enthalten sein:

david@mars ~ $ sudo vim /etc/apache2/ports.conf 
Listen 127.0.0.1:80
Listen 127.0.0.1:443

Nach einer Anpassung der Ports muss der Webserver neu gestartet werden:

david@mars ~ $ sudo service apache2 restart

Das ist ohnehin immer eine gute Idee, wenn man sicherstellen möchte, dass man wirklich mit der aktuellsten Konfiguration arbeitet. Dauert nur unwesentlich länger als der Reload und man spart sich ggf. eine unnötige Fehlersuche.

Mit den beschriebenen Anpassungen ist der lokale Webserver nun grundsätzlich SSL-fähig. Aber wie bekommt man die nervigen Warnungen im Browser weg? Damit beschäftigt sich der nächste Teil meiner kleinen Artikelserie.