Nginx: Ältere Client-Zertifikate erlauben

Wenn man am Nginx die SSL-Ciphers updatet und danach gehen manche ältere Client-Zertifikate nicht mehr, liegt das daran das auch für die Client-Zertifikate die Ciphers gelten die unter ssl_ciphers konfiguriert sind – und ist das z.B. sha1RSA nicht mehr drin (hoffentlich 😉 ) werden auch Client-Zertifikate die mit sha1RSA nicht mehr akzeptiert.

Im Log taucht dann folgender Fehler auf:

client SSL certificate verify error: (68:CA signature digest algorithm too weak)

und der Client bekommt

400 Bad Request The SSL certificate error

Um das Problem zu lösen muss man @SECLEVEL=0 an seine ssl_ciphers anhängen – z.B. :

ssl_ciphers 'HIGH:!aNULL:!MD5@SECLEVEL=0';

Danach werden die Client-Zertifikate wieder akzeptiert – die Sicherheit der eigentlichen SSL-Verbindung ist hiervon nicht betroffen 🙂

Quelle: stackoverflow.com

Nginx: proxy_pass mit älteren TLS-Versionen

Ich verwende ja recht gerne den Nginx als ReverseProxy. Aktiviert man allerdings TLS 1.3 in den ssl_protocols – so will der Nginx auch mit dem Backend immer mit TLS 1.3 sprechen. Das kann allerdings z.B. mit älteren IIS-Servern zu Problemen bzw. zu keiner Verbindung führen.

Das Problem kann man mit

proxy_ssl_protocols TLSv1 TLSv1.1;

verhindern. So verwendet der Nginx in diesem Beispiel eben TLS1 oder TLS 1.1 um mit dem Backend zu kommunzieren – mit dem Frontend (also dem Client-Browser) wird dann trotzdem TLS1.3 gepsorchen 🙂

nginx: unknown directive more_set_input_headers

Ich wollte auf einem nginx-Server einen ReverseProxy für Exchange einrichten. Für MAPI-over-HTTP und den Zugriff von Mac-Clients hab ich mich an meine Anleitung gehalten – aber leider scheitert der Start des nginx mit der Fehlermeldung

unknown directive more_set_input_headers

Für den Teil

more_set_input_headers 'Authorization: $http_authorization';
proxy_set_header Accept-Encoding "";
more_set_headers -s 401 'WWW-Authenticate: Basic realm="exch2016.test.local"';

braucht es eine nginx-Erweiterung – das headers-more-nginx-module.

Ob das Modul installiert ist kann mittels

nginx -V

geprüft werden.

Falls es dort nicht zu finden ist kann es einfach entweder mit dem nginx-extras-Paket oder manuell nachinstalliert werden:

sudo apt-get install nginx-extras

bzw.

sudo apt-get libnginx-mod-http-headers-more-filter

Falls jetzt der Start immer noch nicht funktioniert kann es sein das die Module beim Start nicht geladen werden.

Dazu muss in der /etc/nginx/nginx.conf ganz oben (unter pid /run/nginx.pid;)

include /etc/nginx/modules-enabled/*.conf;

hinzugefügt werden.

Danach den nginx neustarten – dann sollte es gehen 🙂

Nginx: upstream timed out (110: Connection timed out)

Ich hatte bei einem Nginx als ReverseProxy das Problem das dieser oft in Fehler upstream timed out (110: Connection timed out) lief und so die Seite nicht funktionierte – der User bekam dann eine 504 Fehlerseite.

Ich habe das mit dem hinzufügen der beiden Zeilen

proxy_http_version 1.1;
proxy_set_header Connection „“;

gefixt – danach lief alles ohne Probleme.

Quelle: stackoverflow

Nginx: Einbinden von allen Domains erlauben

Ich hatte das Problem eine Seite bzw. Unterseite die unter einem Nginx als ReverseProxy lief so zu konfigurieren, dass diese sich von jeder Seite einbinden lassen lies. Dies verhindern aber eigentlich die sehr sinnvollen X-Frame-Options.

Diese lassen sich aber einfach mit proxy_hide_header X-Frame-Options für eine Seite oder auch nur für Unterseiten deaktivieren – hier ein Beispiel für eine Unterseite:

location /api {
    proxy_pass https://1.2.3.4/api;
    proxy_hide_header X-Frame-Options;
}

Nach einem Reload oder Restart des Nginx klappte mit der Einbindung 🙂

IIS: X-Forwarded-For Header im Log

Wenn man einen Microsoft Internet Information Services (IIS) hinter einem Reverse Proxy oder einem Load Balancer betreibt, sieht man in den Logs des IIS nur immer die IP-Adresse der Reverse Proxys bzw. dem Load Balancers und nicht die eigentliche IP des Clients.

Wenn der Reverse Proxy bzw. Load Balancer richtig konfiguriert wurde – z.B. bei Nginx wäre es

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

dann wird die IP des Clients an den IIS jedoch sauber übergeben.

Um diese jetzt in den Logs zu sehen muss jetzt nur noch der X-Forwarded-For-Header aktiviert werden.

Den IIS Manager starten und den Punkt Protokollierung öffnen

Dort bei Format auf Felder auswählen…

Dort auf Feld hinzufügen

Dort folgende Werte eintragen:

Feldname: x-forwarded-for
Quelltyp: Anforderungsheader
Quelle: X-Forwarded-For

und mit OK bestätigen.

nochmal mit OK bestätigen und auf Übernehmen klicken

Jetzt taucht im Log-Verzeichnis eine Log-Datei mit eine vorangestellten x_ auf – dort wird jetzt reingeloggt – mit dem X-Forwarded-For-Header und so auch mit der originalen Client-IP.

Quelle: www.loadbalancer.org

Let’s Encrypt mit NGINX auf Debian

Ich setze den NGINX ja gerne sowohl als Web Server als auch als Reverse Proxy ein – fast genauso gerne setzte ich mittlerweile die Let´s Encrypt Zertifikate ein.

Ich hab jab hier schon eine Anleitung geschrieben wie man das auf Ubuntu einrichtet – aber mittlerweile mach ich hauptsächlich Server mit Debian – deshalb hier eine kleine Anleitung wie ich das immer unter Debian konfiguriere:

1) Erstellen eines NGINX-Config-Snippet

wir erstellen einen Config-Datei

vim /etc/nginx/snippets/letsencrypt.conf

und dort einfügen (gegebenfalls das Verzeichnis unter root ändern):

location ^~ /.well-known/acme-challenge/ {
default_type „text/plain“;
root /var/www/letsencrypt;
allow all;
}

und mit :wq abspeichern.

2) Anpassen der bestehenden NGINX-Konfig

Ich konfiguriere eigentlich meine Webseiten immer als HTTPS-only – das heißt jede Anfrage auf Port 80 (HTTP) auf 443 (HTTPS) umgeleitet.

Da die Domänen-Verifizierung von Let´s Encrypt über einen HTTP Aufruf gemacht wird, müssen wir allerdings hier eine Ausnahme erstellen.

Dazu passen wir unsere Webseiten Konfig an:

vim /etc/nginx/sites-available/meineseite

und fügen unser Snippet mittels include in dem Serverteil für HTTP hinzu:

server {
        listen 80;
        listen [::]:80;

        server_name www.meineseite.de;

	include /etc/nginx/snippets/letsencrypt.conf;

        # Redirect any HTTP request to HTTPS
        location / {
        return 301 https://$server_name$request_uri;}

        error_log  /var/log/nginx/meineseite-error.log;
        access_log /var/log/nginx/meineseite-access.log;
}

Der Serverteil für HTTPS braucht hier nichts angegeben werden – wir haben ja auch noch keine Zertifikate 😉

3) Installieren des Let´s Encrypt Clients

Installation unter Debian 9 (Stretch):

sudo apt-get install certbot

Installation unter Debian 8 (Jessie):

Bei Debian 8 muss der Client über die Backports installiert werden.

Dazu müssen zuerst die Backports in den Apt-Sources eingetragen werden:

sudo vim /etc/apt/sources.list

und dort die Zeile

deb http://ftp.debian.org/debian jessie-backports main

ans Ende anfügen und mit :wq speichern und den vim verlassen.

Danach die Sources updaten:

sudo apt-get update

und mit

sudo apt-get install certbot -t jessie-backports

4) erstellen des root-Verzeichnises für Let´s Encrypt

sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

Ich vergebe auch noch entsprechende Rechte (meistens läuft der NGINX ja als www-data User bzw. der User ist in der www-data-Gruppe)

sudo chown -R www-data:www-data /var/www/letsencrypt

5) NGINX reload

sudo systemctl reload nginx

6) Let´s Encrypt Client auführen

Jetzt kann der Client ausgeführt werden – hier als Beispiel für die Domänen meineseite.de und www.meineseite.de (mittels -d domain.tld können noch weitere Domains – falls benötigt – hinzugefügt werden)

sudo certbot certonly --webroot -w /var/www/letsencrypt -d meineseite.de -d www.meineseite.de

dann gibt man eine Mail-Adresse ein und bestätigt mit A die Lizenz-Bedingungen.

Falls alles geklappt hat werden jetzt die Zertifikate ausgestellt – zu finden sind die Zertifikate unter /etc/letsencrypt/live/www.meineseite.de

7) HTTPS-Konfig am NGINX

Jetzt müssen wir noch die HTTPS-Konfig mit unseren neuen Zertifikaten hinzufügen bzw. anpassen.

vim /etc/nginx/sites-available/meineseite

und die Zertifikate im der HTTPS Konfiguration angeben

ssl_certificate /etc/letsencrypt/live/www.meineseite.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.meineseite.de/privkey.pem;

mit :wq speichern.

jetzt noch die Konfiguration am NGINX neu laden

systemctl reload nginx

und wir müssten jetzt die Seite mit einem wunderbaren Zertifikat öffnen können 🙂

8) Renew automatisieren

Die Let´s Encrypt Zertifikate haben die Einschränkung, dass sie nur 90 Tage gültig sind. Man kann hier aber über einen cron-job Abhilfe leisten:

sudo crontab -e

und die folgenden Zeilen hinzufügen

30 2 * * 1 certbot renew >> /var/log/le-renew.log
35 2 * * 1 systemctl reload nginx

so wird automatisch das Zertifikat verlängert und die Konfig des NGINX aktualisiert

9) fertig 🙂

Quelle: https://certbot.eff.org/

UniFi Controller: WebSocket connection error

Wenn man einen UniFi Controller hinter einen ReverseProxy (in meinem Fall einen nginx) betreibt bekommt man oft nach dem einloggen einen WebSocket connection error

Das lässt sich einfach mit einer kleinen Konfig-Änderung am nginx-ReverseProxy beheben:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection „upgrade“;

Diese Zeilen bewirken ein sauberes Weiterleiten von WebSocket-Aufrufen. Nachdem diese Zeilen die die Konfiguration eingetragen und der nginx seine Konfiguration neu geladen hat funktioniert der Aufruf ohne den Fehler 🙂

Hier noch meine nginx-Konfig:

server {
        listen 80;
        listen [::]:80;
 
        server_name unifi.domain.net;
 
        include /etc/nginx/snippets/letsencrypt.conf;
 
        # Redirect any HTTP request to HTTPS
        location / {
        return 301 https://unifi.domain.net;}
 
        error_log  /var/log/nginx/unifi-error.log;
        access_log /var/log/nginx/unifi-access.log;
}

server {
listen 443;
listen [::]:443;
server_name unifi.domain.net;

#cipers
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1; 
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; 
ssl_stapling on; 
ssl_stapling_verify on;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

# Enable SSL
ssl on;
ssl_certificate /etc/letsencrypt/live/unifi.domain.net/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/unifi.domain.net/privkey.pem;
ssl_session_timeout 5m;

# Set global proxy settings
proxy_read_timeout      360;

proxy_http_version 1.1;
proxy_pass_request_headers on;

proxy_pass_header       Date;
proxy_pass_header       Server;

proxy_set_header        Host $host;
proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        Accept-Encoding "";

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

location / {proxy_pass https://localhost:8443;}

error_log /var/log/nginx/unifi-error.log;
access_log /var/log/nginx/unifi-access.log;
}

Quelle: nginx.org

Nginx: Upstream-Server mit SNI unterstützen

Wenn man einen Nginx als ReverseProxy für einen Upstream-Server verwendet der SNI verwendet (egal ob Apache, IIS, etc) , muss man dies in der Konfiguration des Nginx beachten – sonst klappt die Verbindung nicht und wirft 502-Errors.

Die Konfiguration ist allerdings ganz einfach:

location / {
    proxy_pass https://upstream-server;
    proxy_ssl_name $host;
    proxy_ssl_server_name on;
  }

So wird dem Upstream-Server „sauber“ mitgeteilt welche Webseite aufgerufen werden soll.

Und schon klappt der Aufruf über einen Nginx ReverseProxy 🙂

Hier eine kleine Beispiel-Komplett-Konfig:

server {
    listen                  443 ssl; 
    server_name             www.domain.com;
    ssl_certificate         /etc/nginx/ssl/domain/server.crt; 
    ssl_certificate_key     /etc/nginx/ssl/domain/server.key; 

    proxy_read_timeout      360;
    proxy_pass_header       Date;
    proxy_pass_header       Server;
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        Accept-Encoding "";


    location / {
    proxy_pass https://1.2.3.4;
    proxy_ssl_name $host;
    proxy_ssl_server_name on;
    }

    error_log /var/log/nginx/domain-error.log;
    access_log /var/log/nginx/domain-access.log;
}

Quelle: serverfault.com

Let’s Encrypt mit NGINX

Ich setze den NGINX ja gerne sowohl als Web Server als auch als Reverse Proxy ein – fast genauso gerne setzte ich mittlerweile die Let´s Encrypt Zertifikate ein.

Hier eine kleine Anleitung wie ich das immer konfiguriere (Webroot unter Ubuntu):

1) Erstellen eines NGINX-Config-Snippet

wir erstellen einen Config-Datei

vim /etc/nginx/snippets/letsencrypt.conf

und dort einfügen (gegebenfalls das Verzeichnis unter root ändern):

location ^~ /.well-known/acme-challenge/ {
default_type „text/plain“;
root /var/www/letsencrypt;
allow all;
}

und mit :wq abspeichern

2) Anpassen der bestehenden NGINX-Konfig

Ich konfiguriere eigentlich meine Webseiten immer als HTTPS-only – das heißt jede Anfrage auf Port 80 (HTTP) auf 443 (HTTPS) umgeleitet.

Da die Domänen-Verifizierung von Let´s Encrypt über einen HTTP Aufruf gemacht wird, müssen wir allerdings hier eine Ausnahme erstellen.

Dazu passen wir unsere Webseiten Konfig an:

vim /etc/nginx/sites-available/meineseite

und fügen unser Snippet mittels include in dem Serverteil für HTTP hinzu:

server {
        listen 80;
        listen [::]:80;

        server_name www.meineseite.de;

	include /etc/nginx/snippets/letsencrypt.conf;

        # Redirect any HTTP request to HTTPS
        location / {
        return 301 https://www.meineseite.de;}

        error_log  /var/log/nginx/meineseite-error.log;
        access_log /var/log/nginx/meineseite-access.log;
}

Im Serverteil für HTTPS braucht hier nichts angepasst werden 🙂

3) Installieren des Let´s Encrypt Clients

Installation unter Ubuntu ist super einfach:

sudo apt-get install letsencrypt

4) erstellen des root-Verzeichnises für Let´s Encrypt

sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

Ich vergebe auch noch entsprechende Rechte (meistens läuft der NGINX ja als www-data User bzw. der User ist in der www-data-Gruppe)

sudo chown -R www-data:www-data /var/www/letsencrypt

5) NGINX reload

sudo systemctl reload nginx

6) Let´s Encrypt Client auführen

letsencrypt certonly –webroot -w /var/www/letsencrypt -d www.meineseite.de -d meinerseite.de –email email@meineseite.de –agree-tos

mittels -d domain.tld können noch weitere Domains – falls benötigt – hinzugefügt werden und unbedingt die Email nicht vergessen anzupassen!

Falls alles geklappt hat werden jetzt die Zertifikate ausgestellt – zu finden sind die Zertifikate unter /etc/letsencrypt/live/www.meineseite.de

7) HTTPS-Konfig anpassen

Jetzt müssen wir noch die neuen Zertifikate in die HTTPS-Konfig hinzufügen

vim /etc/nginx/sites-available/meineseite

und die Zertifikate angeben

ssl_certificate /etc/letsencrypt/live/www.meineseite.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.meineseite.de/privkey.pem;

mit :wq speichern – und wir sind fast fertig 🙂

8) Renew automatisieren

Die Let´s Encrypt Zertifikate haben die Einschränkung, dass sie nur 90 Tage gültig sind. Man kann hier aber über einen cron-job Abhilfe leisten:

sudo crontab -e

und die folgenden Zeilen hinzufügen

30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl reload nginx

so wird automatisch das Zertifikat verlängert und die Konfig des NGINX aktualisiert

9) fertig 🙂

Quellen:
letsencrypt.org
GitHub