Ich nutze schön seit längerer Zeit einen Reverse Proxy unter Apache um meine Server im Homelab erreichbar zu machen. Die Einrichtung ist nicht schwer, aber es gibt ein paar Dinge zu beachten und ich möchte euch dem Thema heute mal näher bringen.
Der Reverse Proxy bietet einen zentralisierten Zugang zu eurem Homelab und bietet ein extra Layer an Sicherheit. Es wird nur der Port in euer lokales LAN weitergereicht, der auch nötig ist. Zusätzliche Kommunikation wird unterbunden und euer Heimnetz ist nach außerhalb maskiert.
Grundlegender Aufbau
Ich zeige euch hier mal den Aufbau meines Netzes, damit ihr versteht was passiert und was ich erreichen wollte.
Ich habe in meinem Homelab mehrere Server, welche ich von Außerhalb erreichbar machen wollte. Anfänglich habe ich mit Dynamic DNS gearbeitet, mich dann aber für diese Lösung entschieden. Ich habe einen Root-Server bei netcup gemietet, mit welchem ich z.B. diesen Blog betreibe. Gleichzeitig ist er auch ein Wireguard Endpoint und stellt mich somit auch einen VPN-Dienst zur Verfügung. Zu Hause in meinem Heimnetz habe ich einen entsprechenden Wireguard Client, der eine Verbindung zum Server aufbaut, somit kann der Client mit dem Server kommunizieren. Da IPv4 Routing auf dem Client aktiv ist, können auch alle Endpoints im Heimnetz, meinen Server erreichen und umgekehrt. Das ist die erste Voraussetzung, damit mein Vorhaben funktioniert.
Neben meiner Hauptdomain domain.de, habe ich noch Subdomains erzeugt. Dabei erzeuge ich pro Dienst eine eigene, so z.B. app1.domain.de. Die Subdomains verweisen dabei auf die gleiche IP wie die Hauptdomain.
Der Reverse Proxy ist nun dafür zuständig http-Anfragen an die Subdomains, an den entsprechenden Server im Homelab weiterzureichen. Somit ist von Außerhalb nur der Root-Server sichtbar und das Homelab ist nicht sichtbar. Der Proxy gibt auch nur Anfragen an die hinterlegten Ports weiter, wie z.B. 80 und 443. Zugriff auf den Port 22 für SSH ist dadurch nicht möglich, da das Homelab nicht offen steht, sondern nur einzelne Ports und Clients erreichbar sind. Der Proxy ist dadurch auch eine weiteres Sicherheitslayer.
Der Reverse Proxy hat ebenfalls die Möglichkeit die externe Verbindung via https zu verschlüsseln. Die Verbindung dahinter kann weiter unverschlüsselt betrieben werden. So habt ihr nur einen Server, bei dem ihr euch um Zertifikate kümmern müsst. Natürlich kann auch beides mit https abgesichert werden.

Voraussetzungen für den Reverse Proxy
In diesem Beitrag gehe ich davon aus, das ihr bereits einen lauffähigen Apache Server im Einsatz habt. Ihr habt eine Domain und könnt dafür Subdomains einrichten. Ihr solltet die Möglichkeit haben Zertifikate (z.B. mittels Certbot) zu erzeugen um die Verbindung abzusichern. Euer Server muss ebenfalls eine IP-Verbindung zu den Applikationsserver aufbauen können. Diese Thematiken werde ich hier nicht besprechen, sondern nur die pure Konfiguration des Apache.
Module aktivieren
Damit der Apache als Proxy arbeiten kann, müssen entsprechende Module geladen werden. Über die folgenden Befehle (als root) könnt ihr die Module aktivieren und somit laden. Proxy ist das eigentlich Modul für den Proxy. Proxy_http erlaubt es Proxy für http und https Verbindungen zu sein. Da viele Systeme auf Websockets setzen, muss auch proxy_wstunnel geladen werden und auch rewrite um die URL umzuschreiben. Damit ist der Apache vorbereitet und kann als Proxy arbeiten.
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
a2enmod rewrite
systemctl restart apache2.serviceShellSessionVirtual Host einrichten
Wir arbeiten mit Virtual Hosts, die über ihren DNS-Namen identifiziert werden. Die einzelnen Konfigurationsdateien werden im Verzeichnis /etc/apache2/sites-available abgelegt. Wir beginnen damit eine entsprehcnede Konfigurationsdatei anzulegen und zu befüllen.
vi /etc/apache2/sites-available/app1.confShellSessionFolgende Datei soll als Beispiel dienen. In der Konfig gibt es zwei VirtualHost abschnitte, einer für Port 80 und einer für Port 443. Port 80 bedient die normalen http-Anfragen und Port 443 ist für https. In meinem Fall werden Anfragen auf Port 80 direkt umgeleitet und kommen wieder als Anfragen für Port 443 herein. Zusätzlich nutzt der Backend-Server selbst auch ein Zertifikat und verschlüsselt seine Verbindung. Daher wird er mittels https:// angesprochen und die Websockets mit wss://. Zusätzlich wird der Parameter SSLProxyEngine On gesetzt.
<VirtualHost *:80>
ServerName app1.domain.de
Redirect / https://app1.domain.de
ErrorLog ${APACHE_LOG_DIR}/app1-error.log
CustomLog ${APACHE_LOG_DIR}/app1-access.log common
</VirtualHost>
<VirtualHost *:443>
ServerName app1.domain.de
ProxyPreserveHost On
SSLProxyEngine On
ProxyPass / https://192.168.x.x:8443/
ProxyPassReverse / https://192.168.x.x:8443/
ErrorLog ${APACHE_LOG_DIR}/unifi-error.log
CustomLog ${APACHE_LOG_DIR}/unifi-access.log common
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "wss://192.168.x.x:8443%{REQUEST_URI}" [P]
SSLCertificateFile /etc/letsencrypt/live/app1.domain.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app1.domain.de/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>UniFi-Network| <VirtualHost *:80> | Abschnitt für Anfragen auf Port 80 |
| <VirtualHost *:443> | Anschnitt für Anfragen auf Port 443 |
| ServerName | DNS-Name eures Servers; anhand des DNS-Namens wird der entsprechende Virtual Host ausgewählt |
| Redirect | Umleitung zu einer anderen Domain; hier http zu https redirect |
ErrorLog ${APACHE_LOG_DIR}/app1-error.logCustomLog ${APACHE_LOG_DIR}/app1-access.log common | Verzeichnis für Access- und Error-Log; eine Trennung ist sinnvoll um Eregnisse besser zuordnen zu können |
| ProxyPreserveHost On | Soll der Hostname weitergereicht werden (On) oder die gleiche Einstellung wie im Eintrag ProxyPass (Off) |
| ProxyRequests Off | War früher Default auf On, musste daher abgeschaltet werden. Nicht mehr nötig. |
| SSLProxyEngine On | Wenn der Backend Server mit SSL angesprochen wird, auf On setzen |
ProxyPass / https://192.168.x.x:8443/ProxyPassReverse / https://192.168.x.x:8443/ | An welchen Server wird die Anfrage weitergereicht (ProxyPass) und woher kommen die Antworten zurück (ProxyPassReverse). Spricht das Backend http oder https? |
RewriteEngine onRewriteCond %{HTTP:Upgrade} websocket [NC]RewriteCond %{HTTP:Connection} upgrade [NC]RewriteRule .* "wss://192.168.x.x:8443%{REQUEST_URI}" [P] | Wenn die Anwendung Websockets nutzt (Home Assistant, Grafana, Node-RED), muss dieser Block ebenfalls rein. Wenn das Backend via http angesprochen wird, dann ws://, bei https wird wss:// genutzt. Ich würde es generell setzen, da viele Anwendungen darauf setzen und es nicht schadet. |
SSLCertificateFile /etc/letsencrypt/live/app1.domain.de/fullchain.pemSSLCertificateKeyFile /etc/letsencrypt/live/app1.domain.de/privkey.pemInclude /etc/letsencrypt/options-ssl-apache.conf | Wo fndet euer Server die Zertifikate für den Virtual Host |
Um die Konfiguration zu aktivieren, müssen wir mit a2ensite die Site aktivieren. Damit wird ein link in /etc/apache2/sites-enabled/ zu der conf-Datei erzeugt. Anschließend wird mit reload die Konfiguration neu geladen. Sollte der Apache danach nicht funktionieren, habt ihr einen Syntaxfehler eingebaut oder z.B. können die SSL Zertifikate nicht gelesen werden.
a2ensite app1.conf
systemctl reload apache2.serviceShellSessionMit a2dissite nehmt ihr die Site wieder heraus.
a2dissite app1.conf
systemctl reload apache2.serviceShellSessionIch habe ich mal verschiedene Beispielkonfigurationen angehängt. Ihr seht das die Konfiguration eigentlich immer gleich ist. Ihr müsst halt darauf achten ob euer Backend selber via https oder http angesprochen wird. Sollte es selbst ein Zertifikat haben, müsst ihr SSLProxyEngine setzen, es via https ansprechen und bei den Websockets via wss, ansonsten ist die Konfiguration gleich.
Home Assistant mittels Reverse Proxy erreichen und absichern
Von extern erreicht ihr Home Assistant über https:/homeassistant.domain.de und intern wird Home Assistant auf dem Port 8123 angesprochen. Home Assistant nutzt auch Websockets.
<VirtualHost *:80>
ServerName homeassistant.domain.de
Redirect / https:/homeassistant.domain.de
ErrorLog ${APACHE_LOG_DIR}/homeassistant-error.log
CustomLog ${APACHE_LOG_DIR}/homeassistant-access.log common
</VirtualHost>
<VirtualHost *:443>
#Domain-Name
ServerName homeassistant.domain.de
#Proxy settings
ProxyPreserveHost On
ProxyPass / http://192.168.x.x:8123/
ProxyPassReverse / http://192.168.x.x:8123/
#Logging
ErrorLog ${APACHE_LOG_DIR}/homeassistant-error.log
CustomLog ${APACHE_LOG_DIR}/homeassistant-access.log common
#Websocket
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "ws://192.168.x.x:8123%{REQUEST_URI}" [P]
#Certificates for SSL
SSLCertificateFile /etc/letsencrypt/live/homeassistant.domain.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/homeassistant.domain.de/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>ShellSessionGrafana mittels Reverse Proxy erreichen und absichern
Von extern erreicht ihr Grafana über https:/grafana.domain.de und intern wird Grafana auf dem Port 3000 angesprochen. Grafana nutzt auch Websockets.
<VirtualHost *:80>
ServerName grafana.domain.de
Redirect / https:/grafana.domain.de
ErrorLog ${APACHE_LOG_DIR}/grafana-error.log
CustomLog ${APACHE_LOG_DIR}/grafana-access.log common
</VirtualHost>
<VirtualHost *:443>
ServerName grafana.domain.de
ProxyPreserveHost On
ProxyPass / http://192.168.x.x:3000/
ProxyPassReverse / http://192.168.x.x:3000/
ErrorLog ${APACHE_LOG_DIR}/grafana-error.log
CustomLog ${APACHE_LOG_DIR}/grafana-access.log common
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "ws://192.168.x.x:3000%{REQUEST_URI}" [P]
SSLCertificateFile /etc/letsencrypt/live/grafana.domain.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/grafana.domain.de/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>ShellSessionNode-RED mittels Reverse Proxy erreichen und absichern
Von extern erreicht ihr Node-RED über https:/nodered.domain.de und intern wird Node-RED auf dem Port 1880 angesprochen. Node-RED nutzt auch Websockets.
<VirtualHost *:80>
ServerName nodered.domain.de
Redirect / https:/nodered.domain.de
ErrorLog ${APACHE_LOG_DIR}/nodered-error.log
CustomLog ${APACHE_LOG_DIR}/nodered-access.log common
</VirtualHost>
<VirtualHost *:443>
ServerName nodered.domain.de
ProxyPreserveHost On
ErrorLog ${APACHE_LOG_DIR}/nodered-error.log
CustomLog ${APACHE_LOG_DIR}/nodered-access.log common
ProxyPass / https://192.168.x.x:1880/
ProxyPassReverse / https://192.168.x.x:1880/
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "ws://192.168.x.x:1880%{REQUEST_URI}" [P]
SSLCertificateFile /etc/letsencrypt/live/nodered.domain.de/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/nodered.domain.de/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>ShellSessionWie ihr seht ist das Thema grundsätzlich nicht schwer. Ich wünsche euch viel Erfolg!




