Starke Kryptografie für Apache Webserver

Ich habe heute Abend mit meiner Tochter mal einen Apache Web Server auf einem RaspberryPi aufgesetzt und die default Konfiguration so erweitert, dass wir beim testen mit dem Qualys SSLLabs Onlinetool eine A+ Bewertung bekommen haben. Ich hab mir gedacht ich schreib das mal auf.

Da der Server an einer DSL Leitung mit Dynamischer IP Adresse betrieben wird, verwenden wir einen DynDNS dienst der unserem Hostnamen immer die Aktuelle IP Adresse zuweist, beispielsweise NOIP. Auf die Einrichtung soll hier aber nicht weiter eingegangen werden.

Hier die Schritte:

Apache2 (Webserver) installieren

Installieren der Apache Webservers und aktivieren der erforderlichen Module

sudo apt-get install apache2
sudo a2enmod ssl headers

Erzeugen eines private keys und csr (Certificate Signing Request)

Erzeugen eines privaten Schlüssels und des Certificate Signing Requests

openssl req -out yourname.csr -new -newkey rsa:2048 -nodes -keyout yourname.key

Es wird nun der Private Schlüssel generiert und dann ein zu vergebenes Passwort abgefragt (Das Passwortfeld kann auch leer gelassen werden, da ansonsten jedes mal beim Starten des Apache’s das Passwort benötigt werden würde).
(Dieses wird zur Entschlüsslung des Privaten Schlüssels benötigt und zur Beantragung und Erneuerung der Zertifikate bei einer Certificate Authority. Dieses sollte also auf keinen Fall verloren gehen.)

Generating a 2048 bit RSA private key
.................................................................................................+++
....+++
writing new private key to 'yourname.key'
Enter PEM pass phrase:

Es werden nun einige Daten, wie der Country Code u.s.w. abgefragt. Wichtig hier bei ist das „Common Name“ mit dem FQDN des Servers befüllt wird. Aus diesen wird der Certificate Signing Request erzeugt.

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]:Bundesland
Locality Name (eg, city) []:Ein Ort
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Eine Organisation
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:your.fqdn.tld
Email Address []:webmaster@your.fqdn.tld

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Es sind nun zwei Dateien erzeugt worden: yourname.key, dieser enthält den verschlüsselten Privaten Schlüssel und yourname.csr, dies ist der signing Request.

Erzeugen eines private keys und csr (Certificate Signing Request) in einem Rutscht

Wenn ihr den obigen Schritt bereits erledigt habt, könnt Ihr diesen Schritt überspringen!

Man kann den Private-Key, sowie den die CSR-File auch in einem Kommando abfrühstücken und dort auch gleich alle weiteren Angaben unterbringen. (Hierbei wird bei der Erstellung kein Passwort für den private Key abgefragt)
Ein Beispiel dafür würde so aussehen:

openssl genrsa -out yourname.key 2048 && openssl req -new -key yourname.key -sha512 -nodes -subj '/C=DE/ST=Bundesland/L=Stadt/O=Organisation/OU=Webserver/CN=www.example.com/emailAddress=mail@example.com/subjectAltName=DNS.1=example.com' > yourname.csr

Das Resultat ist das selbige, wie oben, nur das hierbei keinerlei Einzelabfragen nötig sind, sondern man den Key inkl. CSR in einem Rutsch erzeugt.
Die entsprechenden Infos müssen hierbei natürlich in dem Befehl angepasst werden bevor man diesen einfach abschickt.

Zusätzlich haben wir in diesem Befehl noch einen zweiten DNS-Namen für die entsprechende CSR hinterlegt, sollte die CA nicht automatisch auch das Cert für www bzw. non-www der Webseite ausliefern.

Bitlänge des Private-Key ändern

Die Bitlänge für den Private-Key lässt sich einfach ändern in dem ihr anstelle von 2048 eine andere Bitlänge in die Befehle einsetzt.

Als Ausgangspunkt ist hier immer gut 1024 * ENTSPRECHENDER WERT (bspw. 4 -> ergo 4094bit) zu nehmen.
Hierdurch verlängert sich zwar der Rechenaufwand sowohl beim Erstellen des Keys (vorallem dann) als auch dann später in der eigentlich Kommunikation, aber die Verschlüsselung ist entsprechend schwerer zu entschlüsseln.
In unserem Fallbeispiel mit einem Raspi 2 genügt allerdings eine Länge von 2048bit.

Auf stärkeren Servern würde sich eine Länge von 4096bit empfehlen, wodurch die Verschlüsselung noch stärker wird, da hierdurch deutlich mehr Primzahlen zu errechnen sind.

.csr-Datei kontrollieren

Die .csr Datei für die Erstellung des Certs kann bevor man Sie bei einer CA einreicht nochmal mittels folgendem Befehl auf der Kommandozeile kontrollieren:

openssl req -text -noout -verify -in yourname.csr

.csr bei einer CA einreichen

Diese .csr Datei wird dann bei einer Certificate Authority eingereicht. Wir haben die kostenlose CA StartSSL verwendet.
Nach der Zuteilung des Zertifikates erhalten wir zwei Dateien. Eine mit dem Root Zertifikat der Certificate Authority „ca.crt“ und eine weitere mit dem Webserver Zertifikat für unsere Domain „yourname.crt“.

Zertifikat von der CA überprüfen

Mit folgendem Befehl könnt ihr das ausgestellt Zertifikat für eure Webseite auch nochmal überprüfen:

openssl x509 -in yourname.crt -text -noout

Hierbei ist vorallem wichtig das der unter Subject CN die richtige Domain bzw. FQDN steht und ebenfalls der Signature Algorithm mindestens SHA2 ist.

SHA1 wird nämlich in den meistens Browsern in zwischen für unzureichend erklärt, was zur Folge hat, das eure Besucher eine Warnmeldung erhalten.

Private-Key wieder entschlüsseln

Dieser Schritt ist nur nötig, sofern ihr dem Private-Key ein Passwort gegeben habt.

Bevor die Zertifikate in die Konfigurationsdateien des Webservers eingebunden werden, muss der Privatekey entschlüsselt werden.
Da ansonsten jedes mal beim starten, es nötig wäre das Passwort des Private-Keys einzugeben.

openssl rsa -in yourname.key.enc -out yourname.key

Es wird das Passwort verlangt, das bei der Erzeugung des privaten Schlüssels vergeben wurde.

Zertifikat, Private-Key und CRT-File in den Apache2 einbinden

Die drei Dateien legen wir nun im Konfigverzeichnis des Apache Webservers ab.

sudo mkdir /etc/apache2/certs
sudo mkdir /etc/apache2/private 
sudo cp yourname.crt /etc/apache2/certs
sudo cp yourname.key /etc/apache2/private
sudo cp ca.crt /etc/apache2/certs

Jetzt zur Konfiguration des Webservers.
Wir erstellen in /etc/apache2/sites-available/ eine Datei mit folgendem Inhalt.
(bspw. mittels nano /etc/apache2/sites-available/example.com oder vim /etc/apache2/sites-available/example.com)

<IfModule mod_ssl.c>
 <VirtualHost *:443>
 Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

ServerName yourdomain
ServerAlias yourdomain
 
ServerAdmin mailaddress

DocumentRoot /var/www/html

ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
 
SSLEngine on
SSLCertificateChainFile /etc/apache2/certs/ca.crt
SSLCertificateFile /etc/apache2/certs/yourname.crt
SSLCertificateKeyFile /etc/apache2/private/yourname.key
SSLCompression off
SSLInsecureRenegotiation off
SSLProtocol +TLSv1.2 
SSLHonorCipherOrder on
SSLCipherSuite AES256+EECDH:AES256+EDH

<FilesMatch "\.(cgi|shtml|phtml|php)$">
 SSLOptions +StdEnvVars
 </FilesMatch>

<Directory /usr/lib/cgi-bin>
 SSLOptions +StdEnvVars
 </Directory>

BrowserMatch "MSIE [2-6]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
# MSIE 7 and newer should be able to use keepalive
BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

</VirtualHost>
</IfModule>

Apache2 vhost aktivieren

Hiernach ist es noch nötig die entsprechende vhost-Datei zu aktivieren, dies geschieht mit folgendem Befehl:

a2ensite /etc/apache2/sites-available/example.com

Und danach den Apache einmal „neustarten“:

service apache2 reload

Apache2 Details

Die relevanten Zeilen hier noch mal im Einzelnen:

Aktivieren der Http Strict Transport Policy (HSTS) mit langer Lebensdauer

Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"

XFO (X-Frame-Options) Header auf SAMEORIGIN oder DENY Setzen

Header always set X-Frame-Options SAMEORIGIN
oder
Header always set X-Frame-Options DENY

X-Content-Type-Options Header set auf „nosniff“

Header always set X-Content-Type-Options nosniff

Cross Site Scripting Protection aktivieren

Header always set X-XSS-Protection: "1; mode=block"

Content Security Policy Header auf  „default-src ’self'“ setzen

Header set Content-Security-Policy "default-src 'self'"
Header set X-Webkit-CSP "default-src 'self'"

Aktiviern der SSL Engine

SSLEngine on

Einbinden der erstellten SSL Zertifikate

SSLCertificateChainFile /etc/apache2/certs/ca.crt
SSLCertificateFile /etc/apache2/certs/yourname.crt
SSLCertificateKeyFile /etc/apache2/private/yourname.key

Deaktivieren der SSL Kompression und unsicherer SSL Aushandlungsverfahren

SSLCompression off
SSLInsecureRenegotiation off

Deaktivieren aller veralteten SSL und TLS Versionen, wir wollen nur TLSv1.2 unterstützen.

SSLProtocol +TLSv1.2

Deaktivieren aller Cipher Suites außer Elliptic Curve Diffie Hellman Keyexchange mit AES256 Verschlüsselung. Damit wird Perfect Forward Secrecy (PFS) unterstützt und erzwungen.

SSLHonorCipherOrder on
SSLCipherSuite AES256+EECDH

SSLCheck

Das war`s auch schon. Ein Testlauf mit den SSLCheck Tools von SSLLabs.com sieht dann wie folgt aus:

ssllabrpie

Juhuuuu