Debian 9 Stretch: Apache als Reverse Proxy mit Let’s Encrypt einsetzen

Die nachfolgenden Zeilen beschreiben anhand eines Projekts die Einrichtung von Apache als Reverse Proxy mit Zertifikat(en) von Let’s Encrypt unter Debian 9 Stretch.

Warum ein Reverse Proxy?

Die Haupt-Motivation dahinter ist einfach: Es soll nur der Port 443/tcp (https) in der Firewall freigegeben werden und darüber sollen, in Abhängigkeit der aufgerufenen (Sub-)Domain die entsprechenden Webseiten dargestellt werden.

Ein weiterer Vorteil in diesem Szenario besteht darin, das Port 80/tcp (http) mit der folgenden Konfiguration nur für das Ausstellen der Let’s Encrypt-Zertifikate verwendet wird, aber die eigentliche Webseite per Weiterleitung auf https ausschließlich verschlüsselt erreichbar ist. So läuft man nicht Gefahr, doch mal aus Versehen auf die unverschlüsselte Seite zuzugreifen und z.B. Zugangsdaten unverschlüsselt durch den Äther zu schicken.

Als weiteres kann auf diese Art eine unverschlüsselte Webseite im Nachhinein und ohne dortigen Eingriff verschlüsselt werden. Dies ist hilfreich bei so manchem Embedded Device, das entweder gar kein SSL/TLS kann oder nur ein hardcodiertes self-signed Zertifikat hat, wie z.B. bei manchen IP-Kameras.

Weiter kann mit entsprechender Konfiguration zudem die Sicherheit jenseits von SSL/TLS durch Filtern von Aufrufen erhöht werden. Dies ist allerdings kein Teil dieses Beitrags.

Firewall/Port-Forwarding

Die Ports 80/tcp (http) und 443/tcp (https) müssen auf die IP-Adresse des Reverse Proxies zeigen.

Grundinstallation

Für den vorliegenden Reverse Proxy wurde ein kleines Linux als virtuelle Maschine auf Basis von Debian installiert. Dazu wurde das Netinstall-ISO verwendet, beim Setup wurde der Desktop und Druckserver abgewählt und der SSH-Server aktiviert.

Sofern ssh nicht nach Außen hin verwendet wird, kann man sich überlegen, ob man dies intern für root mit Kennwort zulässt. Alle folgenden Befehle werden als root ausgeführt.

In der Datei

/etc/ssh/sshd_config

die Zeile 32 wie folgt anpassen:

PermitRootLogin Yes

Anschließend die Konfiguration neu laden:

service sshd reload

Apache installieren und mod_proxy aktivieren

Zunächst muss der Apache installiert und das Proxy-Modul aktiviert werden:

apt install apache2

a2enmod rewrite
a2enmod proxy
a2enmod proxy_http

service apache2 reload

Dies stellt nur die Minimal-Voraussetzung für dar.

Standard-Webseite deaktivieren

Da der Reverse Proxy selbst keinerlei Webseiten ausliefern soll, schaltet man die Standard-Webseite ab:

a2dissite 000-default.conf
service apache2 reload

VirtualHosts anlegen

Damit die eingehenden Anfragen für die jeweilige Domain beantwortet werden können, muss eine entsprechende Konfiguration her:

Pro Domain eine Datei unter

/etc/apache2/sites-available

anlegen, die folgenden Inhalt bekommt:

<VirtualHost *:80>
ServerAdmin E-Mail-Adresse
ServerName sub.domain.tld
ProxyPreserveHost On 
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / http://Ziel-Adresse:Port/
ProxyPassReverse / http://Ziel-Adresse:Port/
</VirtualHost>

Anschließend aktivieren:

a2ensite Dateiname.conf

service apache2 reload

Bemerkung: Um die SSL-Konfiguration braucht man sich nicht zu kümmern, dies erledigt später Certbot, der für das Let’s Encrypt-Zertifikat zuständig ist.

Certbot erstellt automatisch die notwendigen Rewrite-Anweisungen (http -> https), die SSL-Konfigurationsdateien für die VirtualHosts und aktiviert diese. Die SSL-Konfigurationsdateien enthalten “…-le-ssl.conf” im Namen.

Certbot installieren

Wichtig ist, die Version aus den Backports zu verwenden, da die Version aus den Standard-Paketquellen veraltet ist und damit keine Let’s Encrypt-Zertifikate mehr ausgestellt werden können.

nano /etc/apt/sources

Folgende Zeile hinzufügen und speichern:

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

Certbot installieren und in Apache nutzen:

apt-get install python-certbot-apache -t stretch-backports

certbot –-apache

Certbot fragt ab, ob für alle oder für (einen) bestimmten VirtualHost bzw. Domain das Zertifikat ausgestellt werden soll. Letztlich handelt es sich um ein Zertifikat mit “Alternative Names”.

“Catch-all”-VirtualHost einrichten (Optional)

Wird der Reverse Proxy z.B. direkt mit seiner IP-Adresse aufgerufen, wird keine ihm bekannte Domain übergeben, in Folge landet man auf dem ersten konfigurierten VirtualHost.

Bei Debian ist das dann entweder, sofern doch noch aktiviert, “000-default.conf”, also die Standard-Webseite oder die nächst kleinere Nummer bzw. nach alphabetischer Reihenfolge.

Diese Kenntnis kann man nutzen, um dies abzufangen und auf eine bestimmte nennen wir’s mal Standard- oder catch-all-Seite umzuleiten.

Als Beispiel wird der Dateiname “001-catch-all.conf” verwendet:

<VirtualHost *:80>
ServerAdmin E-Mail-Adresse
ServerName sub.domain.tld
ProxyPreserveHost On 

RewriteEngine on
RewriteRule ^ https://Ziel-Adresse [END,NE,R=permanent]
</VirtualHost>

bzw. “001-catch-all-ssl.conf”:

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin E-Mail-Adresse
ServerName sub.domain.tld
ProxyPreserveHost On

SSLCertificateFile /etc/letsencrypt/live/sub.domain.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sub.domain.tld/privkey.pem

RewriteEngine on

RewriteRule ^ https://Ziel-Adresse [END,NE,R=permanent]

</VirtualHost>
</IfModule>

Beide aktivieren und die Änderung laden:

a2ensite 001-catch-all.conf
a2ensite 001-catch-all-ssl.conf
service apache2 reload

Weiterleitung an eine Webseite mit selbst-signiertem Zertifikat (Optional)

Nach Außen nutz man zwar mit Let’s Encrypt ein öffentliches und sauber zu validierendes Zertifikat, aber intern wäre im ungünstigsten Fall die Kommunikation unverschlüsselt. Das mag kein Problem darstellen, wenn z.B. auf dem gleichen Server das Ziel liegt oder eben gewollt der Reverse Proxy SSL abwickeln soll damit der dahinterliegende Webserver entlastet ist.

Im vorliegenden Szenario ist es allerdings so, das die Zielserver in unterschiedlichen Netzen liegen und die Kommunikation intern ebenfalls verschlüsselt ablaufen soll. Damit dieses Ziel unkompliziert erreicht werden kann, werden schlicht selbst-signierte Zertifikate eingesetzt. Die Konfiguration ist im Reverse Proxy einfach:

Die betreffenden Zertifikate ohne privaten Schlüssel nach

/etc/ssl/certs

kopieren und folgende Konfigurationen anlegen bzw. ändern. Da http zu https umgeleitet wird, reicht an dieser Stelle die Rewrite-Regel aus:

<VirtualHost *:80>
ServerAdmin E-Mail-Adresse
ServerName sub.domain.tld
ProxyPreserveHost On 
DocumentRoot /var/www/html
ProxyPass /.well-known !

RewriteEngine on
RewriteCond %{SERVER_NAME} =sub.domain.tld
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Für das Weiterleiten von https mit Let’s Encrypt-Zertifikat zu https mit selbstsigniertem Zertifikat beim Ziel sieht die Konfiguration so aus:

<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin E-Mail-Adresse
ServerName sub.domain.tld
ProxyPreserveHost On 
DocumentRoot /var/www/html
ProxyPass /.well-known !
ProxyPass / https://Ziel-Adresse:Port/
ProxyPassReverse / https://Ziel-Adresse:Port/

# SSL aktivieren
SSLProxyEngine on

# Domain-Namen-Ueberpruefung deaktivieren
SSLProxyCheckPeerCN Off
SSLProxyCheckPeerName Off

# Pfad und Dateiname zum selbst-signierten Zertifikat des Ziels 
SSLProxyCACertificateFile /etc/ssl/certs/ssl-cert-snakeoil-backend.pem

RewriteEngine on
RewriteCond %{SERVER_NAME} =sub.domain.tld
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]

SSLCertificateFile /etc/letsencrypt/live/sub.domain.tld/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/sub.domain.tld/privkey.pem

Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

Anschließend die Änderung laden:

service apache2 reload

Automatische Zertifikatsverlängerung

Da bekanntermaßen die Zertifikate von Let’s Encrypt nur eine Gültigkeit von drei Monaten besitzen, ist es sinnvoll eine automatische Verlängerung zu konfigurieren. Certbot richtet dazu einen Timer in systemd ein, man braucht sich folglich um nichts weiter zu kümmern.

Weiteres (Sicherheit)

Keine schlechte Idee ist es, den Apache des Reverse Proxies in Sachen Sicherheit weiter zu konfigurieren. Als Denkanstösse kann man auf folgenden Seiten nachlesen:

TechMint – 13 Apache Web Server Security and Hardening Tips (Punkte 1, 2, 4, 6, 7, 8, 11)

netnea – Einen Reverse Proxy Server aufsetzen

Quellen:

Ben’s Thoughts –  Apache as reverse proxy for letsencrypt free https certificates

certbot – Apache on Debian 9 (stretch)

Debian Backports – Instructions

RoseHosting – How to set up Apache Virtual Hosts on Debian 9

DigitalOcean – How To Use Apache HTTP Server As Reverse-Proxy Using mod_proxy Extension

xinotes – Apache reverse proxy with SSL configuration file example

ProfitBricks – Configure Apache as a Reverse Proxy Using mod_proxy on Ubuntu

serverfault – Apache Default/Catch-All Virtual Host?

Let’s Encrypt – Cerbot cron job?

kofler.info – Systemd-Timer als Cron-Alternative

8 Kommentare

  1. Flo

    Hi,

    ich würde den Port 80 Vhost anders konfigurieren. Eine 301 Weiterleitung ist für Suchmaschinen günstiger.

    ServerName sub.domain.tld
    ServerAlias sub.domain.tld
    RedirectMatch 301 ^(?!/.well-known/acme-challenge/).* https://sub.domain.tld$0
    DocumentRoot /var/www/sub.domain.tld

    Options Indexes FollowSymLinks
    AllowOverride None
    Order allow,deny
    Deny from env=illegal
    Allow from all

    Gruss

    Flo

  2. Rainer Müller-Knoche

    Hallo Danke für das Tutorial, funktioniert nur im letzten Beispiel sind die Zeilen
    “RewriteEngine on
    RewriteCond %{SERVER_NAME} =sub.domain.tld
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]”
    falsch. da gehören die let’s Encrypt Zeilen
    “SSLCertificateFile /etc/letsencrypt/live/sub.domain.tld/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/sub.domain.tld/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf”
    hin.
    Vermutlich beim Copy und Paste schiefgegangen

  3. andy

    Hallo Rainer, ich weiß leider gerade nicht, wo genau du meinst.

  4. Rainer Müller-Knoche

    Hi es geht um das letzte beispiel “Für das Weiterleiten von https mit Let’s Encrypt-Zertifikat zu https mit selbstsigniertem Zertifikat beim Ziel sieht die Konfiguration so aus:”

    da machen die letzten Zeilen bei Dir noch mal einen Redirect, da müssen aber die vom Lrt’sEncrypt Script eingefügten Zeilen hin, sonst loopt der Redirect.

  5. andy

    Ich steh’ grad auf dem Schlauch (einer Erkältung sei dank), aber ich schätze du hast recht. Vmtl. gehören die Rewrite-Anweisungen da auch nicht hin. Letzteres hab’ ich mal durchgestrichen und ersteres eingefügt. So ähnlich sieht die Konfig. auf einem “Live-ReverseProxy” aus.

  6. Rainer Müller-Knoche

    Also bei mir klappt das so wie es jetzt ist. Kann Dir auch mal meine conf zusenden, aber per mail nicht öffentlich hier im Forum. Gute Besserung.
    Hab noch ein anderes, etwas tricky gelöstes Problem mit dem reverse proxy, führt aber zu weit es hier zu diskutieren, wäre per mail möglich, falls Du Interesse hats

    Gruß

    Rainer

  7. andy

    Klar hab’ ich interesse. Mail-Addy siehe imprint.

  8. Stephan von Gehlen

    Danke Andy!!
    Dein toller Artikel hat mein setup gerettet!

    auf dem Weg durch deinen Artikel ist mir dann eine Kleinigkeit aufgefallen die ser Certbot nicht macht, zumindest auf Ubuntu 18.04.
    der trägt nicht “SSLProxyEngine on” in die -le-ssl.conf Dateien ein die er aber sonst gut generiert!
    nachdem ich das nachgetragen habe lief alles.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

© 2024 Andy's Blog

Theme von Anders NorénHoch ↑