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.pemRewriteEngine 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
Verheiratet, Vater von zwei Kindern, eines an der Hand, eines im Herzen. Schon immer Technik-Freund, seit 2001 in der IT tätig und seit über 10 Jahren begeisterter Blogger. Mit meiner Firma IT-Service Weber kümmern wir uns um alle IT-Belange von gewerblichen Kunden und unterstützen zusätzlich sowohl Partner als auch Kollegen.
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
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
Hallo Rainer, ich weiß leider gerade nicht, wo genau du meinst.
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.
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.
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
Klar hab’ ich interesse. Mail-Addy siehe imprint.
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.