teil 4 – reverse-proxy mit ssl

Änderungsstand: 2020-04-20

Als erstes stellt sich hier die Frage, wohin Lets Encrypt installiert werden soll. Auf dem eigentlichen Webserver oder auf vielleicht doch auf den Reverse-Proxy, den wir separat betreiben? Ich kann nicht sagen, welches die „bessere“ Methode ist. Nach Tagelangem einlesen und einigen Feedbackgesprächen mit Menschen, die sich da auskennen sollten, bin ich für mich zu dem Entschluss gekommen, dass es diesbezüglich wahrscheinlich kein allgemeines Rezept gibt, was besser ist. Beide Sachen haben wohl ihre Vor- und Nachteile. Nachdem ich im Teil 1 noch überzeugt war, dass ein Reverse-Proxy auf einen externen Gerät besser aufgehoben wäre, denke ich mittlerweile … naja …. ich weiss es nicht.

Ich werde in diesem Guide meiner Sache treu bleiben und die Verschlüsselung auf dem Reversy-Proxy einrichten.

Im selben Atemzug habe ich mir aber schon das nächste Projekt herausgepickt und werde die Reverse-Proxy-Geschichte noch einmal neu angehen. Dann aber direkt im OMV5 und mittels Traefik-Docker realisiert. Doch nun zurück zum eigentlichen Thema.

Dieser Guide ist sehr umfangreich. Ich empfehle, erst einmal alles zu lesen, damit man eine gewisse Vorahnung hat, auf was man sich einlässt 🙂

Wir erinnern uns. Es wird das Erstellen eines Reverse-Proxy mit signierter SSL-Verschlüsselung, auf einem extra dafür abgestellten RaspberryPi, erläutert.

Soweit die Teile 1-3 erfolgreich absolviert wurden, wenden wir uns jetzt der Verschlüsselung zu. Auch hier wieder meine verwendeten Daten.

Meine verwendeten Ports, IP’s und Domain für diesen Guide:

  • 192.168.252.225 (Mein Raspi Reverse-Proxy Server)
  • reverse-proxy (angelegter Hostname des RaspberrysPi)
  • 192.168.252.118:80 (Mein Server, der später eine Website enthält (NginX Webserver))
  • webserver (angelegter Hostname meines Webservers)
  • 80 zu 80 zu 80 – (http – Portfreigabe Router zum Raspi Reverse-Server)
  • 443 zu 443 zu 443 – (https – Portfreigabe Router zum Raspi Reverse-Server)
  • 80 – NginX Reverse-Proxy (http)
  • 443 – NginX Reverse-Proxy (https)
  • Dynamische DNS: knilix.duckdns.org (für Letsencrypt)
  • 81 – Portverwendung für Letsencrypt

Als erstes eine kleine Sicherheitsanpassung in der nginx.conf:

sudo nano /etc/nginx/nginx.conf

# server_tokens off;

ändern zu

server_tokens off;

STRG-x, y, Enter

service nginx restart

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

Strg-x, y, Enter

Jetzt ändere ich die angelegte conf-Datei, aus Teil 3.

Zuerst lösche ich die vorhande *.conf-Datei aus *.enabled, welche in Teil 3 angelegt wurde. Dann wird eine neue *.Config-Datei erstellt. Wie immer gilt, dass die Grün-makierten Sachen durch Eure eigenen Werte ersetzt werden müssen. In sites-available ist die „alte“ Konfigurationssdatei noch vorhanden. Da stört diese keinen.

sudo rm /etc/nginx/sites-enabled/proxyconfig-intern.conf
sudo nano /etc/nginx/sites-available/knilix.duckdns.org.conf
server {
  listen 80;
  listen [::]:80;
  server_name www.knilix.duckdns.org;
    include /etc/nginx/snippets/letsencrypt.conf;

# http Anfragen zu https weiterleiten
        location / {
        return 301 https://$192.168.252.118:3200$request_uri;}
 
        error_log  /var/log/nginx/knilix.duckdns.org.log;
        access_log /var/log/nginx/knilix.duckdns.org.log;
}

STRG-x, y, Enter

ln -s /etc/nginx/sites-available/knilix.duckdns.org.conf /etc/nginx/sites-enabled/knilix.duckdns.org.conf
sudo nginx -t

Werden keine Fehler angezeigt, dann:

sudo service nginx restart

Rufe ich jetzt http://knilix.duckdns.org auf, erscheint die Willkommensnachricht von NginX des Webservers. Das ist auch richtig so, denn das haben wir so angewiesen. Natürlich jetzt unverschlüsselt! Darauf sollte man achten.

Jetzt wird der Code für Letsencrypt erstellt.

Letsencrypt:

sudo apt-get install certbot 
sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
sudo chown -R www-data:www-data /var/www/letsencrypt
sudo systemctl reload nginx
sudo certbot certonly --webroot -w /var/www/letsencrypt -d knilix.duckdns.org -d www.knilix.duckdns.org --rsa-key-size 4096

Mittels Leerzeichen und -d und dann nach einem Leerzeichen können noch weitere Domains hinzugefügt werden.

Mit folgender Ausgabe hat dann auch alles funktioniert und das Zertifikat wurde erstellt.

- Congratulations! Your certificate and chain have been saved at:
  /etc/letsencrypt/live/knilix.duckdns.org/fullchain.pem
  Your key file has been saved at:
  /etc/letsencrypt/live/knilix.duckdns.org/privkey.pem
  Your cert will expire on 2020-07-15. To obtain a new or tweaked
  version of this certificate in the future, simply run certbot
  again. To non-interactively renew *all* of your certificates, run
  "certbot renew"

Mit dem Befehl…

sudo certbot renew

…kann man das Zertifikat erneuern. Das Zertifikat ist immer jeweils 90 Tage gültig. Dieser Befehl kann auch als Cron-Job angelegt werden. Google hilft da weiter 🙂

Ein weiterer Schritt zur eigenen Sicherheit (Diffie-Hellman Parameter für DHE ciphersuites, empfohlen 2048 bits):

sudo mkdir -p /etc/nginx/ssl
sudo openssl dhparam -out /etc/nginx/ssl/dhparams.pem 2048

Zugriffsrechte der Schlüssel anpassen (könnte man auch weglassen, ist aber, in gewisser Weise, Sicherheitsrelevant)

chmod 600 /etc/letsencrypt/live/knilix.duckdns.org/fullchain.pem
chmod 600 /etc/letsencrypt/live/knilix.duckdns.org/privkey.pem
chmod 600 /etc/letsencrypt/live/knilix.duckdns.org/chain.pem
chmod 600 /etc/letsencrypt/live/knilix.duckdns.org/cert.pem
chmod 600 /etc/nginx/ssl/dhparams.pem

Ist bis hierher alles geschafft, haben wir das signierte Zertifikat von Letsencrypt und das zusätzliche ciphersuites-Zertifikat, was einen enormen Sicherheitsrelevanten Fortschritt bringt, erstellt. Nun müssen die Zertifikate noch im NginX Reverse-Proxy eingetragen werden.

Jetzt erweitern wir unsere, vorhin erstellte, knilix.duckdns.org.conf-Datei der Hauptdomain. Vorher lösche die *.conf-Datei.

sudo rm /etc/nginx/sites-available/knilix.duckdns.org.conf
sudo nano /etc/nginx/sites-available/knilix.duckdns.org.conf
server {
  listen 80;
  listen [::]:80;
  server_name knilix.duckdns.org www.knilix.duckdns.org;
    include /etc/nginx/snippets/letsencrypt.conf;
# http Anfragen zu https weiterleiten
        location / {
        return 301 https://$server_name$request_uri;
        }
        error_log  /var/log/nginx/knilix.duckdns.org-error.log;
        access_log /var/log/nginx/knilix.duckdns.org-access.log;
}

##### Start der Konfiguration Port https
#//////////////////////////////////
server {
    listen 443 ssl http2;
    server_name knilix.duckdns.org www.knilix.duckdns.org;
# SSL aktivieren und Einbindung der signierten Zertifikate
    ssl on;
    ssl_certificate /etc/letsencrypt/live/knilix.duckdns.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/knilix.duckdns.org/privkey.pem;

# Nginx - Konfigurieren starker Cipher-Suites (extra-Sicherheit)
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-G$
        ssl_prefer_server_ciphers off;

# Diffie-Hellman Parameter für Ciphersuites, empfohlen 2048 bits
        ssl_dhparam /etc/nginx/ssl/dhparams.pem;

# OCSP Stapling
# OCSP-Datensätze von der URL in ssl_certificate abrufen und cachen
# Benötige ich vorest nicht! Nach dem Testen aktivieren!
   ssl_stapling on;
   ssl_stapling_verify on;
   ssl_trusted_certificate /etc/letsencrypt/live/knilix.duckdns.org/fullchain.pem;

# Behandlung von SSL-Sitzungen
# Benötige ich vorest nicht! Nach dem Testen aktivieren!
   ssl_session_timeout 24h;
   ssl_session_cache shared:SSL:50m;
   ssl_session_tickets off;

# Manche Web-Applikationen leiten einen auf http:// um. Die nachfolgende Anweisung leitet http:// anfragen an Port 443 auf https:// um
        error_page 497 = https://$server_name:$server_port$request_uri;

# Header-Befehle, die später von verschiedenen Anwendungen benötigt werden
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    add_header X-Permitted-Cross-Domain-Policies none;

# Header-Umgehensweise für den Proxy
        location /
               {
                proxy_pass http://webserver:3200;
                proxy_set_header X-Real-IP  $remote_addr;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_set_header Host $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-ROOT-URI /services/oauth;
                proxy_set_header Accept-Encoding "gzip";
                proxy_request_buffering off;
                proxy_http_version 1.1;
                proxy_intercept_errors on;
                proxy_redirect default;
                client_max_body_size 4M;
                }

# Ein weiterer Befehl wäre z.B. location ~ /admin/.*\.php$ {  für die Zugriffsverweigerung auf einen bestimmten Ordner (aber noch nicht getestet)
} #<-- Diese Klammer nicht vergessen zu setzen! Der Https-Block ist fertig.
##### Ende der Konfiguration https
#//////////////////////////////////


STRG-x, y, Enter

Jetzt ein Verlinkung der eben erstellten Datei zu sites-enabled:

ln -s /etc/nginx/sites-available/knilix.duckdns.org.conf /etc/nginx/sites-enabled/knilix.duckdns.org.conf
sudo nginx -t

Werden keine Fehler angezeigt, dann:

sudo service nginx restart

Jetzt gebe ich im Browser folgendes ein:

https://knilix.duckdns.org

oder

http://knilix.duckdns.org

Es wird alles automatisch zu https umgewandelt und zum webserver durchgeleitet. Verschlüsselt und signiert!

Kleiner Nachtrag: Woher weiß ich eigentlich, dass die Willkommensseite des Webservers und nicht die des Proxy aufgerufen wird? Nun, ich habe die html-Seite des webservers einfach etwas geändert, so dass diese ein anderes Aussehen hat. Ich bin anfangs fast verzweifelt, da diese im Original nun mal identisch aussehen 🙂

Somit wäre das Grundgerüst fertig erstellt. Hat man das Grundprinzip halbenwegs verstanden, könnten weitere „Locations“ und virtuelle Hosts angelegt werden. Doch das sprengt hier den Rahmen. Ich denke, das Ziel wurde erreicht.

Nur dass ich es einmal erwähnt habe. Für den ganzen Kram (Teil1 – Teil4) saß ich fast 2 Wochen, bis alles soweit funktionierte. Und selbst jetzt bin ich mir immer noch nicht 100%ig sicher, ob alles den Richtlinien entspricht. Viele Internetseiten bedeuten halt auch viele Fehlinformationen, die man zwar so gut wie möglich herausfiltern möchte, es aber leider nicht immer gelingt, dass zu realisieren. Ich habe erst 2 Wochen vor Erstellung des Guide angefangen, mich mit dem Thema „Reverse-Proxy“ zu befassen.

Quelle(n):

https://decatec.de/home-server/owncloud-9-auf-ubuntu-server-16-04-lts-mit-nginx-mariadb-php-7-und-lets-encrypt/

https://prezer.de/nginx-als-reverseproxy-11.html

https://serversforhackers.com/c/redirect-http-to-https-nginx

Aus vielen weiteren Quellen habe ich mir Randinformationen herausgepickt, die meist aber der sprichwörtliche „Schuß in den Ofen waren“ bzw. wo die erhaltenen Daten so weit modifiziert werden mussten, dass es passte, dass leider eine Erwähnung im Nachgang nicht mehr möglich war.

.

Benötigte Hardware

Teil 1 – Installation des Betiebssystems

Teil 1_1 – Anlegen eines Hostnamen

Teil 2 – RasperryPi und DuckDNS

Teil 3 – RaspberryPi als Reverse-Proxy