Reverse-Proxy - Was habt ihr im Einsatz?

blurrrr

Well-known member
Mahlzeit!

Da das Thema Reverse-Proxy früher oder später vermutlich bei allen auf der Liste steht, die Dienste im Internet bereitstellen wollen (Nextcloud, HomeAssistant, Wordpress, Dienste auf eurem NAS, etc.) und den Zugriff dabei nicht via VPN realisieren wollen... Was nutzt ihr für Reverse-Proxy-Lösungen und wie sind eure Erfahrungen damit? 🙃

Möglichkeiten gibt es ja einige, die bekanntesten Vertreter dürften klar sein, sind aber mitunter auch gern mal irgendwo als Addon/Plugin verfügbar (z.B. HAproxy-Paket bei pfSense/OPNsense, etc.) und somit eingebettet in andere Lösungen. Nutzt ihr euren Reverse-Proxy "standalone" (z.B. als Docker-Variante wie den Nginx-Proxy-Manager, oder traefik, etc.), oder habt ihr es zusätzlich auf etwas anderem wie einer pfSense/OPNsense, etc. laufen?

Ich fang einfach mal an:

Hier lief einige Zeit zevenet, welches dann übergegangen ist zu skudonet, hat pound als Unterbau. Anderorts teilweise auch HAproxy via OPNsense im Einsatz gehabt. Mit dem Nginx-Proxy-Manager (NPM) bin ich irgendwie nie wirklich warm geworden. Zu Testzwecken auch mal rein nginx, da aber weniger als regulärer Web-Reverse-Proxy, sondern eher als Teststellung für ein Projekt (Mail-Proxy).

Traefik und ähnliche, welche eher in die "cloud-native"-Ecke gehören, sind derzeit noch kein Thema, wird sicherlich aber auch mal kommen und dann wird man froh sein, wenn es sowas schon gitb. Allerdings sehe ich da aktuell keinen Bedarf bei mir (was nicht heisst, dass sich sowas nicht auch sehr schnell ändern kann 😇).

Wie sieht's bei euch so damit aus? :)
 
Versuch es vielleicht mal mit dem Nginx Proxy Manager der scheint recht gut zu sein.
Ich bevorzuge allerdings die VPN Lösung und habe OpenVPN und Wireguard im Einsatz.
 
Versuch es vielleicht mal mit dem Nginx Proxy Manager der scheint recht gut zu sein.
->
Mit dem Nginx-Proxy-Manager (NPM) bin ich irgendwie nie wirklich warm geworden.
Sofern ich Dich richtig verstanden habe - falls nicht, war es so gemeint, dass Du mal den NPM ausprobieren willst? Für mich ist der NPM jedenfalls nichts - 3 Knöpfe für das nötigste und der Rest folgt dann sowieso wieder der entsprechenden Config-Syntax, dafür braucht man dann meiner Meinung nach auch keine WebGUI. Ist aber mit den Basic-Settings schon ganz nett für Leute, welche sich nicht groß mit der Thematik beschäftigen wollen.

Via VPN ist schon klar und für die meisten Dinge auch zu bevorzugen, aber wie ich schon schrieb:
die Dienste im Internet bereitstellen wollen (Nextcloud, HomeAssistant, Wordpress, Dienste auf eurem NAS, etc.) und den Zugriff dabei nicht via VPN realisieren wollen
Geht also schon konkret darum, diverse Dienste "öffentlich" im Internet bereitzustellen :)
 
Ich hab Caddy im Einsatz. Die Config verwalte ich per Git. Insgesamt habe ich 4 Instanzen laufen. 2 für den Zugriff von intern und zwei für den Zugriff von extern. Alle vier Instanzen werden per einem Git Push Hook aktualisiert. Falls sich jemand fragt wieso 4... Das hat den Hintergrund, dass ich erst nur zwei laufen hatte. Die liefen auf verschiedenen Hosts. Mit keepalived wird zwischen Master und Slave geschaltet. So kann ich ein Node neustarten/ausmachen was auch immer. Der andere springt dann immer ein. Durch die virtuelle IPs (IPv4 und IPv6) kann ich auch die Port Weiterleitungen auf diese IPs setzen und es wird immer auf den Master geleitet. Ich hab Domains, die nur intern aufgelöst werden und einige die öffentlich sind. Dann ist mir aufgefallen, dass wenn jemand seinen DNS Server anders konfiguriert und eine interne Domain auf meine IP auflöst, dann kann er trotzdem meine internen Dienste aufrufen, weil mein Reverse Proxy drauf reagiert. Ja ich könnte die Configs bei den Hosts anpassen, dass diese nur intern erreichbar sein dürfen, aber da hatte ich keine Lust zu und dachte mir, dass es eigentlich besser wäre, wenn man die gar nicht aufrufen könnte. Deshalb habe ich zwei weitere Instanzen hinzugefügt. Die Server auf die 443 weitergeleitet wird, laden erst gar nicht die Configs für die internen Dienste. So kann es auch nicht durch einen Fehler passieren, dass jemand etwas aufrufen kann, was er nicht sollte. Bei Adguard wird auf die virtuelle IP vom internen Proxy alles geleitet. So seh ich auch direkt was nur von extern angefragt wird und ob irgendwas nicht stimmt....

Ich hoffe ich konnte es bisschen verständlich erklären. :)
 
Mmh, kannst die zwei letzten Sätze nochmal anders formulieren bitte?
Komme dem Gedankengang nicht hinterher.

Aktuell habe ich 2 NPM, werde aber auch nur so halb warm. Die zwei Hauptkriterien die ich aktuell befriedige durch gewachsene Strukturen sind Wildcard Zertifkate (um nicht sämtliche Dienste in transparency logs zu leaken. Und um mit weniger Zertifikaten auszukommen, die ich dann intern flexibler weiter deployen kann egal welche Subdomains laufen sollen) und DNS delegation für die acme challenges (damit Hoster auch ohne DNS API kein Problem sind).
Zumindest in der Kombi fällt NPM da auch die Schnauze.
Jetzt hatte ich überlegt mir als nächstes ein nackten nginx selbst als Proxy zu nehmen...
Nach einem kurzen Überflug zu Caddy scheint dieser beide Kriterien zu meistern und noch andere... Dann werde ich mir den als nächstes anschauen, mindestens wieder als 2 getrennte Instanzen. Ob ich mir das mit der Redundanz (CARP IP) antue weiß ich noch nicht.

Aber schon mal danke für den Denkanstoß.

Aus Interesse, kannst vielleicht noch 1-2 Sätze zur eingesetzten Hardware absetzen?
 
Durch keepalived bekommen die Instanzen virtuelle IPs. Diesen definiere ich selber in der config. In Adguard habe ich dann einfach *.meine-domain.de auf die virtuelle IP geleitet. Wenn der main Server weg ist, dann wird der zweite zum master und übernimmt die virtuelle IP. Und weil extern und intern jetzt komplett getrennt sind, kann ich in der access.log viel besser kontrollieren was wirklich von extern aufgerufen wird. Dafür bereite ich es mit goaccess per Cron auf und hab eine gute Übersicht über alles was aufgerufen wird und von wo aus die Anfragen kommen.
Hardware sind zwei Proxmox Kisten. Ein m720q und ein Fujitsu S740. Caddy läuft bei mir nativ in einer VM. Könnte es auch mit Docker machen, aber da bräuchte ich extra Skripte für keepalived, weil ich prüfen müsste ob der Container läuft. So kümmert sich keepalived selber drum.

Wenn etwas unklar ist, dann gerne fragen. Ich weiß nicht ob es so besser verständlich war :)
 
Moin,

hab mal kurz versucht was ich rausgelesen habe in ein Diagramm zu legen.
Wie gut ist das Verständnis?

Korrektur auch gerne per PN, dann kann ich es nachher mit der korrekten Version ersetzen, falls es noch 2-3 mal hin/hergeht.
 

Anhänge

  • keepalived_caddy_setup.jpg
    keepalived_caddy_setup.jpg
    47,9 KB · Aufrufe: 7
Ja schon, nur läuft der je der Master auf Proxmox 1 und der Slave auf Proxmox 2.
Alle Anfragen von intern (egal ob interner Dienst oder extern) wird über den Caddy für intern geleitet. Nur was über die Fritzbox reinkommt, landet auch auf den Caddy für extern.

Weil die VMs auf unterschiedlichen Nodes laufen kann ich ohne Probleme die Nodes abschalten. Das selbe Prinzip mit keepalived habe ich für Adguard+Unbound laufen. So funktionieren auch die Umschreibungen immer bzw. das Internet.
 
Ich probier ansonsten mal morgen oder Montag das zu skizzieren wie ich es genau habe. Inklusive der VMs mit Diensten. Jedenfalls falls es gewünscht ist
 
  • Traffic aus dem Internet:
    • Auf meinem Router lauscht auf den WAN-Ports 80/443 ein haproxy mit SNI und TLS-Passthrough
    • Port 80 ist nur ein Redirect auf 443.
    • leitet je nach Domain an andere Ziel weiter
  • Lokaler Traffic:
    • Ich nutze Unbound, um Überschreibungen für meine Public Domain zu machen (damit der Traffic nicht erst wieder über das WAN Interface reinkommen muss)
    • Und Bind9 zum Managen meiner Subdomains der Domain (hier schummel ich etwas, um LE Wildcard Zertifikate für die ausgestellt zu bekommen)

Beide Wege zeigen dann im Endeffekt auf Swarm und k8s Cluster, die jeweils Traefik mit LE Wildcard Zertifikat haben. Dort geschieht dann TLS-Offloading und geht weiter an die entsprechenden Container.

Alles in allem recht pflegearme Lösung.
 
@*alx* Wegen mir, sehr gerne. Um sich in das Thema hinein zu denken und nachzuvollziehen und eine Lösung zu erarbeiten (für mich) finde ich das sehr hilfreich.

Falls du mehr Gefallen daran findest kannst dir ja auch überlegen, ob du deine config Beispielhaft im Bereich der Anleitungen hier auf der Seite für die Nachwelt festhalten willst.
Edit: Das hilt natürlich für jeden, der eine interessante Konstellation oder Thematik außerhalb von Threads aufbereitet darstellen will.

Bin in jedem Fall für die Denkanstöße dankbar. Das hilft ungemein ein Thema von mehreren Seiten zu durchleuchten im Vergleich zu es selbst in/outside the box und aus verschiedenen Richtungen zu betrachten.
 
Ich probier mal es genauer zu beschreiben.
Schonmal vor ab. Ich verwende überall nur IPv4 in der Beschreibung, aber im Einsatz geht es immer um IPv4 und IPv6. Nur zur Übersicht lasse ich das IPv6 weg.

Mein Problem war am Anfang als ich das so aufgesetzt habe mit nur zwei Instanzen folgendes:
Folgende DNS Records habe ich gesetzt gehabt.

RecordIP
*.domain.de79.174.160.19
*.intern.domain.de0.0.0.0

Das *.intern.domain.de musste ich setzen, weil sonst auch dienst.intern.domain.de auf meine IP zeigen würde. Deshalb habe ich das überschrieben.
Mein Reverse Proxy hatte somit alles in der Config um jeweils die internen Dienste als auch die externen Dienste aufzurufen. Irgendwann ist mir das klar geworden, dass wenn jemand seinen DNS Server umkonfiguriert und meinen Eintrag für *.intern.domain.de umschreibt, dann könnte er ohne Probleme meine internen Dienste aufrufen. Der RP würde das ja routen, weil die Anfragen wieder rein kommen. Deshalb habe ich zwei weitere Instanzen eingeführt. Ich unterschede jetzt zwischen internen und externen. Der RP der von extern erreichbar ist, hat keine Konfiguration für interne Dienste. Der RP für von intern hat sämtliche Konfigurationen. So konnte ich den Record auch für *.intern.domain.de löschen. Das muss eh nur von intern erreichbar sein. Aus diesem Grund läuft auch die Konfiguration per Git + Ansible. Wenn ich etwas anpasse und commite, dann wird per Ansible automatisch das auf allen Instanzen eingespielt. So habe ich immer den selben Stand überall.
Weil von intern nur der Interne RP verwendet wird, erleichtert es extrem die Auswertung von der access.log. Da sind wirklich nur Anfragen drin, die über die Fritzbox rein kamen. Da hat man dann auch einen guten Überblick mit goaccess.
Ich hab das mal probiert als Grafik aufzuarbeiten. Ich hoffe es wird deutlicher was ich da gemacht habe :D

caddy.png

Wegen dem Aufwand das 4x mal einzurichten.... Ich hab ein Ansible Playbook, der alles einrichtet. Also Caddy, Crowedsec, Keepalived installieren und konfigurieren. Ich hab das innerhalb von 2 Minuten eingerichtet. Ich kann darüber auch 10 weitere Instanzen betreiben. Die Keepalived Prio kann ich da mitgeben, damit ich steuern kann was der Master ist und was die Slaves. Bei Interesse kann ich auch das gerne mal teilen.
 
Moinsen,
wow, Danke fürs Teilen und Zeigen! :)
Ich habe das Thema die letzten 2 Tage auch gehabt.
Da ich hier alles doch recht simpel habe, habe ich den Geräten (also den echten hosts) einmal lokal selfsigned Zertifikate verpasst. Hier alle später gewollten CNAMEs mitangegeben, auch IP (ist ja selbstsigniert). Diese sind also immer intern erreichbar (auch über http), alles schön auch in Pihole UND unbound (pfsense) hinterlegt.
Als eigentlichen reverse proxy nutze ich rein intern den einfachen bereits erwähnten Nginx PRoxy Manager. Der reicht bisher aus. Einziger Grund: die angedrohte drastische Verkürzung der durch die Browser akzeptierten Zertifikatslebenszeiten. Sollte das also dann eines Tages so kommen, muss was anderes her, als die 10 Jahre gültigen selbstsignierten ssl Zertifikate. Deswegen LetsEncrypt.
Also einmal einen NPM für die wesentlichen Dinge mit eigener *.subdomain.example. Dazu eine *.anderesubdomain.example. Das eben für die Geräte, die zusätzlich lokal auch ihre selbstsignierten haben. Damit ist die gesamte Strecke weiter verschlüsselt. Also geht ein Aufrufen via IP und hostname, mit domainname#1 (in unbound/pihole angelegt), domainname (LE Zertifikat) als CNAME in unbound und pihole hinterlegt. Jaja, kleine Spielere...;)
Für die dockerbasierten Dienste und zb ein paar LXC dann mit der anderen NPM Instanz, die dann eben eine eigene subdomain dafür bedient. Grund hier dafür weniger eine Ausfallsicherheit. Ich wollte eher 2 NPM, damit ich da auch zwischen harware und virtueller Anwendung /Dienst eine Trennung habe. Fällt die docker VM aus dann ist wenigstens noch der NPM für den Rest da. Fällt das ganze Proxmox System aus bin ich eh mit anderen Dingen beschäftigt...
Irgendwann schaue ich mir mal den HA proxy auf der pfsense an, dann vielleicht auch darüber etwas machen. Aktuell mag ich aber gerade die Einfachheit des NPM: Domain reserviert, NS Records gesetzt, per DNS-Challenge wildcard Zertifikate mit diversen subomains holen. Gut. Auf ACLs innerhalb des nginx verzichte ich aktuell, das regelt die firewall und ich bin eh der einzige Nutzer... ;)
 
Zuletzt bearbeitet:
Zurück
Oben