In dieser Anleitung geht es darum, wie ihr euren Nginx Server absichern könnt. Ich habe bereits über den Mozilla SSL Configuration Generator einen Beitrag geschrieben. In diesem Beitrag nehme ich die Mozilla SSL Konfiguration als Grundlage und erweitere diese noch um einige Sicherheitsfeatures.
Um Sicherheit herzustellen wollen wir eine HTTPS Verschlüsselung konfigurieren. Damit dies funktioniert, benötigt ihr ein SSL Zertifikat für eure Domain. Falls ihr dies noch nicht besitzt, dann könnt ihr hier nachlesen, wie es kostenlos und innerhalb weniger Minuten erstellt werden kann.
Diffie Hellman 2048 / 3096 Key erzeugen
Zum Austausch von Schlüsseln nutzt Nginx Standardmäßig nur einen 1024 Bit Key. Dies wollen wir auf 2048 / 3096 Bit erhöhen. Dazu wechseln wir in ein Verzeichnis unser Wahl (in meinem Fall den Ort, wo auch die SSL Zertifikate liegen).
cd /etc/letsencrypt/live/<eureDomain.de>/
In diesem Verzeichnis führen wir folgenden Befehl aus zum Generieren eines 2048 Keys.
openssl dhparam -outform PEM -out dh.pem 2048
Dies kann je nach Rechenleistung eurer Servers mehrer Minuten dauern (bei mir ca. 5 Minuten).
Alternativ könnt ihr auch einen 3096 Bit Schlüssel generieren. Die benötigte Rechenzeit steigt jedoch deutlich an, bis der Key generiert ist.
openssl dhparam -outform PEM -out dh.pem 3096
nginx Konfiguration anpassen
Nun gehen wir in die Nginx Konfigurationsordner mittels
cd /etc/nginx/sites-available/
Dort gibt es bereits eine Datei “default”, die wir nun umbenennen.
mv default default.bak
Nun erstellen wir eine neue Konfigurationsdatei.
touch <eureDomain.de> ln -s /etc/nginx/sites-available/<eureDomain.de> /etc/nginx/sites-enabled/<eureDomain.de>
Diese leere Datei öffnen ihr nun und kopiert nachfolgenden Inhalt in die Datei.
nano <eureDomain.de>
Achtung:
gelbe Zeilen müssen angepasst werden !
server { listen 80; listen [::]:80; server_name <eureDomain>.de www.<eureDomain>.de; #diese Zeile braucht ihr nur, wenn ihr meiner Anleitung zum Erstellen von Zertifikaten gemacht habt. #wenn nicht, dann loescht diese Zeile !!! include /etc/nginx/snippets/letsencrypt.conf; # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response. return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name <eureDomain>.de www.<eureDomain>.de; ssl on; ssl_certificate /etc/letsencrypt/live/<eureDomain>.de/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/<eureDomain>.de/privkey.pem; ssl_session_timeout 1d; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits ssl_dhparam /etc/letsencrypt/live/<eureDomain>.de/dh.pem; ssl_protocols TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; ssl_prefer_server_ciphers on; # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/<eureDomain>.de/chain.pem; resolver 8.8.8.8; root /var/www/html/; index index.html index.htm index.php; #aktiviert X-Frame-Options add_header X-Frame-Options "SAMEORIGIN"; #aktiviert X-XSS-Protection add_header x-xss-protection "1; mode=block" always; #aktiviert X-Content-Type-Options add_header X-Content-Type-Options "nosniff" always; #für PHP5. PHP7 Konfiguration bitte löschen location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php5-fpm.sock; } #für PHP7. PHP5 Konfiguration bitte löschen location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } }
Wenn ihr noch viele ältere Geräte unterstützen wollt, dann könnt ihr folgende Einstellungen wählen:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; ssl_prefer_server_ciphers on;
Bemerkungen:
Gelbe Zeilen
MÜSSEN ANGEPASST WERDEN !!
HTTP2 Support
nginx unterstützt erst ab Version 1.9.5 HTTP2. Bei früheren Versionen muss die konfiguration folgendermaßen abgeändert werden:
listen 443 ssl; listen [::]:443 ssl;
PHP Version
Je nach installierter Version von PHP muss die Konfiguration für die nicht installierte PHP Version gelöscht werden.
Optional: nginx Version ausblenden
Ihr könnt noch die nginx Version ausblenden. Das bedeutet,dass euer Server diese nicht immer mitschickt und so einem Angreifer ermöglicht spezielle Sicherheitslücken für diese Version zu suchen. Hier habe ich erklärt, wie man die Option aktiviert.
nginx Server neu starten
Nun müsst ihr nginx lediglich noch neu starten, damit dieser die Einstellungen übernimmt.
Dies erledigt ihr mittels
service nginx restart
Möglicher Fehler:
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
Wenn ihr diesen Fehler bekommen solltet, dann müsst ihr einen Eintrag abändern. Dazu öffnet ihr folgende Datei:
nano /etc/nginx/nginx.conf
Dort löscht ihr das “#” Zeichen vor folgender Zeile:
# server_names_hash_bucket_size 64; wird zu server_names_hash_bucket_size 64;
Fazit
Durch die obige Konfiguration habt ihr jetzt folgendes aktiviert:
- euer Server alle HTTP Anfragen auf HTTPS umleitet
- nur die aktuellsten Protokolle TLSv1, TLSv1.1 und TLSv1.2 unterstützt
- der Server nur sichere Ciphersuites erlaubt
- Strict-Transport-Security aktiviert
- X-Frame-Options aktiviert
- X-XSS-Protection aktiviert
- X-Content-Type-Options aktiviert
- OSCP aktiviert
- Diffie Hellman Key mit 2048 / 3096Bit
Die Webseite ssllabs.com biete einen Online-Scanner an, der eure Webseite auf Sicherheitslücken überprüft.
Diesen Test habe ich für den eben installierten Webserver durchgeführt mit folgendem (sehr guten) Ergebnis.
Hi
geht das alles auch unter Debian 8? Strato bietet leider kein Debian 9 an. Gerade nutze ich Ubuntu aber dort kann ich Certbot nicht installieren, um die Zertifikate herzustellen.
Danke 🙂
VG Alex
Hallo Christian,
erst einmal Hut ab und Daumen hoch fuer die Dokus. Ich habe nur ‘ne kleine Info. Nachdemich die Schritte wie oben nachvollzogen habe bekam ich nach Neustart von nginx eine 403-Fehlermeldung. Das ist passiert, weil in meiner nginx version das index-file in /var/www/html anders heisst, naemlich ‘index.nginx-debian.html;‘ Das betrifft eine Zeile in der ersetzten default-Datei
‘index index.html index.htm index.php index.nginx-debian.html;‘
nginx-Dienst noch neu starten und dann geht’s.
Beste Gruesse,
Konrad
Hallo!
Danke für den hilfreichen Artikel! Ist es möglich bzw. überhaupt sinnvoll, nur einen DH-Schlüssel für alle Domains auf dem Server zu nutzen oder sollte für jede ein eigener erstellt werden?
Viele Grüße
Robin