[tlw. gelöst] HAproxy Konfiguration

Started by viragomann, November 26, 2024, 05:17:34 PM

Previous topic - Next topic
November 26, 2024, 05:17:34 PM Last Edit: November 28, 2024, 02:51:08 PM by viragomann
Hallo,

ich habe schon seit Jahren HAproxy auf pfSense in Verwendung.
Die Konfiguration auf pfSense scheint recht nah an der tatsächlichen HAproxy Konfiguration angelehnt zu sein. Die originalen HAproxy Anleitungen sind so leicht nachzuvollziehen.

Nun evaluiere ich OPNsense für unseren Zweck und habe auch hier HAproxy eingerichtet. Aber die GUI verfolgt ein völlig anderes Konzept, das nicht nur von jener auf pfSense, auch von der tatsächlichen HAproxy Konfiguration weit abweicht. Ich kann nicht nachzuvollziehen, warum hier die Konfiguration dermaßen zerklüfftet ist: Real Servers, Public Services, Backend Pools, Conditions, Rules, Haelth Monitor.
In pfSense wie auch in HAproxy selbst ist all das in zwei Bereichen zu konfigurieren, Frontends und Backends. Das erscheint mir weitaus übersichtlicher und hängt auch sinngemäß zusammen.
Vielleicht kann mir jemand aber den Sinn dahinter erklären.

Aber okay, da mag sich jemand was anderes überlegt haben, und ich versuche halt damit umzugehen. Doch nun zu meinen eigentlichen Fragen / Problemen:

An einem Punkt erscheint mir die Konfiguration doch regelrecht grotesk:
Conditions
Ich versuche, alles über eine öffentliche IP zu lösen und habe 5 Backend Server. Zu Sinn oder Unsinn dieser Lösung kann man sich hier auch gerne äußern, bislang hatte ich ein Frontend je Backup.

Auf einem dieser habe ich etwa 30 ziemlich verschiedene Hostnamen. So brauche ich eine Menge Host-Conditions, um diesen Server zu bedienen. 14 für einen einzigen virtuellen Server darauf. Der hat so viele Aliase.
So habe ich 14 Conditions mit demselben Namen angelegt, und dachte, so wie es die HAproxy Konfiguration vorsieht, brauche ich diesen nur einmal in der Regel zu erwähnen. Aber nicht auf OPNsense. In der Regel-Konfig scheinen auch alle 14 auf und möchten auch alle angehakt werden, damit sie darauf reagiert.
Im Konfig-File habe ich gesehen, dass jede Condition eine eigene ID erhält und diese verwendet wird. Ich frag mich, warum, wenn es das Original doch einfacher vorgibt.

Ist das wirklich so nötig oder habe ich was übersehen?
Das erscheint mir doch ziemlich abwegig von der eigentlichen HAproxy Konfiguration und ist zudem unnötig kompliziert und unhandlich.

Zusätzlich habe ich noch ein Frage zur 'Maintenance' Funktion:
In einem Backend Pool habe ich einen Server mit Status 'active' und einen weiteren mit Status 'backup'.
Mein Test: Ich aktiviere 'maintenance' auf dem aktiven. Die Anfragen werden auf den Backup weitergeleitet, wie erwartet. Nachdem ich den aktiven wieder auf 'ready' setze, bleibt das allerdings so. Auch ein 'drain' des Backups bringt HAproxy nicht wieder dazu, die Anfragen auf den aktiven Server zu leiten, auch nicht jene einer neuen Session / anderen Browser.
Erst, wenn ich den Backup auf 'maintenance' stelle UND die Webseite im Browser aufrufe, verwendet HAproxy wieder den aktiven Server.

Das kann doch auch nicht Sinn der Sache sein. Auch das funktioniert auf pfSense pipifein.
Hat da jemand bessere Erfahrung? Lassen sich die Server noch irgendwie anders umschalten?

Und dann noch die Frage, lassen sich Aliases aus OPNsense in den Conditions verwenden?
Ich vermute mal, nein, nachdem man eigene User und -Gruppen einrichten kann. Auch das geht in pfSense super toll und ist sehr praktisch.

Wenn das alles negativ bleibt, frage ich mich, ob HAproxy überhaupt die richtige Wahl für einen Reverse-Proxy auf OPNsense ist.
Habe mitbekommen, dass hier sehr viel von Caddy geschrieben wird. Aber kann der auch all das und ist der vernünftiger einzurichten und zu bedienen?
Meine Anforderungen sind sehr überschaubar: Eben wie o.g. ein Backup-Backend, das verwendet wird, wenn der primäre Host down ist, HTTP auf HTTPS Redirect und ein paar Regeln basieren auf Hostnamen, Pfade und später vielleicht noch Files und IPs.

Grüße

Die Konfiguration von HAproxy ist etwas komplex, aber sehr flexibel. Hast Du Dir die Anleitung von TheHellsite angesehen? Das deckt die meisten Anwendungen gut ab.

Caddy ist im Vergleich weniger komplex, aber "geschwätziger" und es kann ein bisschen weniger, ich habe dazu hier etwas geschrieben.

Auch zu Caddy gibt es ein Tutorial.

Bei Deiner Anzahl an Hostnamen würde ich eher zu HAproxy mit einer Alias Map raten, dann kannst Du die Zertifikate mittels ACME-Wildcards erledigen.

Dazu braucht man nur eine Condition, wirst schon sehen. Je nachdem, wie viele Backends Du hast, brauchst Du natürlich Backends und "Real Server", aber es kann ja gut sein, dass ein Backend mehrere Hostnamen abdeckt.

Mit Maintenance habe ich noch nicht gespielt, ich nutze auch keine Redundanz nach hinten. Durch das "Health Checking" könnte man aber m.W. sowieso ein automatisches Failover hinbekommen, so dass man das nicht aktiv managen muss.
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Caddy hat einen anderen Fokus im Plugin. Eher Heimanwender und kleine Firmen. Features wie Lets Encrypt, DNS Provider, Dynamic DNS etc... sind da direkt mit eingebaut. Die GUI ist auf so gut es geht Einfachheit und wenig User Error durch zuviel Abstraktion ausgelegt, im gesamten Design.

Ich würde die Tools (in Form der Plugins) so nicht vergleichen da sie einen grundlegend anderen Scope haben.
Featureparität gibt es da nicht, beide haben Features die das andere Tool in der Form nicht bieten.
Hardware:
DEC740

Die Frage war, weshalb die Konfiguration des HAproxy-Plugins so vollkommen anders aufgebaut ist als in pfSense  ;)
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)


Der Weg zur Hölle ist gepflastert mit guten Absichten  ::)

Ich hatte die Diskussion mit Franco schon beim WireGuard. Ich würde Konzepte und Bezeichnungen für jeden in OPNsense integrierten Dienst immer zu 100% vom Upstream übernehmen.

Der Commit liest ich zwar anwenderfreundlich, ist es aber nicht.

Anwenderfreundlich ist, wenn man "HAproxy how to do foo" in Google kippen und die Ergebnisse von Stackoverflow 1:1 ins UI kopieren kann mit so wenig Übersetzungsleistung wie möglich.

Meine Meinung, muss nicht jeder teilen.  :)
Deciso DEC750
People who think they know everything are a great annoyance to those of us who do. (Isaac Asimov)

@Patrick
Genau, das ist der Punkt.

Es gibt im Web jede Menge Hilfe zu HAproxy, Doch wenn ich das im OPNsense Plugin konfigurieren will, brauch ich einen Pons dazu.
pfSense hatte ich erwähnt, weil da in der GUI weitgehend die HAproxy Konfig-Datei abgebildet ist. Da wird ein frontend als "Frontend", backend "Backend" und acl als "ACL" bezeichnet, wie im Konfig-File auch. Auch die Reihenfolge ist identisch, wenngleich ich Backends voranstellen würde, weil ich diese zuerst konfigurieren muss.
In OPNsense GUI finde ich nicht mal eine dieser Bezeichnungen demselben Zweck entsprechend verwendet.

Aber gut, das ist nicht mein größtes Problem. Nachdem ich mit HAproxy schon etwas Erfahrung gesammelt habe, weiß ich zumindest, wonach ich suchen muss.

Doch die Sache mit den zig Conditions für denselben Zweck, die ich dann auch nochmals in der Regel angeben muss, würde ich schon als Problem bezeichnen. Das führt schnell zu Unübersichtlichkeit, selbst bei meiner kleinen Konfiguration mit nur einer handvoll Backends.

@Alle
Danke für die Links. Muss ich mir morgen noch ansehen.

Grüße

November 26, 2024, 10:47:41 PM #7 Last Edit: November 26, 2024, 10:51:37 PM by meyergru
Zwei Dinge:

1. Ja, die OpnSense GUI unterscheidet sich stark von "HAproxy native". Die Karawane zieht weiter, man muss das Plugin nicht nutzen.

2. Man braucht eben keine tausend Conditions. TheHellsite umgeht das elegant mit einer einzigen Regel, wo in einer Map die Namen auf Backends abgebildet werden. Das ist, was ich meinte, wieso ich bei komplexen Konfigurationen HAproxy bevorzuge. In Caddy müssen die verschiedenen Bestandteile jeweils pro Name angelegt werden, das wird mir immer zu unübersichtlich.

Ist wohl mehr die Frage, ob / wie man etwas fertig bekommen möchte (ich bin da ziemlich lösungsorientiert) oder sich an der konkreten Umsetzung in einer bestimmten Umgebung abarbeitet oder mit einem bestimmten Hintergrundwissen daherkommt. Letztlich war das wohl auch der Grund, weshalb Fraenki HAproxy so "verpackt" hat, dass es seiner gewohnten Load-Balancer-Nomenklatur entspricht.

Wenn man sich mal von seinem vermeintlichen Vorwissen löst (oder vorgibt, keins zu haben, wie ich), muss man ja nur dem einen oder anderen Tutorial folgen, um sein Ziel zu erreichen - wenn man's denn will.

P.S.: Wie bei vielen Open-Source Tools habe ich bei HAproxy auch feststellen müssen, dass ein 2-3 Jahre altes Tutorial, das ich bei Google finde. überhaupt nicht mehr anwendbar ist, weil die Hälfte der Optionen inzwischen deprecated sind.
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Quote from: meyergru on November 26, 2024, 07:30:12 PM
Die Konfiguration von HAproxy ist etwas komplex, aber sehr flexibel. Hast Du Dir die Anleitung von TheHellsite angesehen? Das deckt die meisten Anwendungen gut ab.
Danke dafür.

Die Map Files könnten also wahrscheinlich mein Problem mit den vielen Conditions für denselben Zweck lösen.
Allerdings, so wie ich es verstanden habe, lassen sich damit Hostnamen nur direkt auf ein Backend mappen, nicht aber auf einen Backend Pool, wodurch kein Failover möglich wäre.
Muss mir aber noch die genannten Links dazu ansehen. Für meinen speziellen Zweck brauch ich aber eh kein Failover.
Damit wäre mir also schon mal geholfen.

Quote from: meyergru on November 26, 2024, 10:47:41 PM
P.S.: Wie bei vielen Open-Source Tools habe ich bei HAproxy auch feststellen müssen, dass ein 2-3 Jahre altes Tutorial, das ich bei Google finde. überhaupt nicht mehr anwendbar ist, weil die Hälfte der Optionen inzwischen deprecated sind.
Das trifft auch auf TheHellsites Tutorial zu.

Und leider behandelt es keine HTTPS Frontends, nur TCP. Ich werde aufgrund der Filtermöglichkeiten eher HTTPS verwenden.

November 27, 2024, 03:13:39 PM #9 Last Edit: November 27, 2024, 03:17:31 PM by meyergru
Quote from: viragomann on November 27, 2024, 02:17:52 PM
Die Map Files könnten also wahrscheinlich mein Problem mit den vielen Conditions für denselben Zweck lösen.
Allerdings, so wie ich es verstanden habe, lassen sich damit Hostnamen nur direkt auf ein Backend mappen, nicht aber auf einen Backend Pool, wodurch kein Failover möglich wäre.

Nein, das Mapping läuft auf einen Backend Pool, der dann mit N "Real Servers" bestückt wird.

Quote from: viragomann on November 27, 2024, 02:17:52 PM
Und leider behandelt es keine HTTPS Frontends, nur TCP. Ich werde aufgrund der Filtermöglichkeiten eher HTTPS verwenden.

Doch, genau das tut es. Die Konfiguration ist tricky, aber sehr effektiv. Er definiert drei Frontends, das erste ist tatsächlich TCP, dient aber nur dazu, auf ein Backend zu verweisen, das SNI macht und dann auf die beiden anderen HTTP(S) Frontends verzweigt. Dabei macht er auch gleich noch HSTS-Redirection, verwaltet Zertifikate, macht SSL-Offloading u.v.a.m.

Ich wage zu behaupten, dass man ohne diese Anleitung mit HAproxy "native" kaum selbst eine so elegante Lösung hinbekäme. Ich habe das sowohl bei mir zu Hause wie auf zwei Proxmox-Servern bei Hetzner im Einsatz.
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Quote from: meyergru on November 27, 2024, 03:13:39 PM
Nein, das Mapping läuft auf einen Backend Pool, der dann mit N "Real Servers" bestückt wird.

Okay, das mach ja Sinn.

QuoteEr definiert drei Frontends, das erste ist tatsächlich TCP, dient aber nur dazu, auf ein Backend zu verweisen, das SNI macht und dann auf die beiden anderen HTTP(S) Frontends verzweigt. Dabei macht er auch gleich noch HSTS-Redirection, verwaltet Zertifikate, macht SSL-Offloading u.v.a.m.
Dann hab ich den Sinn dahinter wohl nicht verstanden.

Er schreibt beim TCP Frontend, dass dieses dazu da ist, um den Traffic zwischen SSL Offloading oder nicht aufzuteilen. Ich möchte aber für alles SSL Offloading haben, also habe ich es für meinen Zweck als nicht nötig gehalten.

Die Umleitung von HTTP auf HTTPS hatte ich auch schon gebaut. Dazu hatte ich ein Frontend erstellt, dass nur auf Port 80 lauscht und mit er entsprechenden Regel versehen. Das von ACME erstellte "redirect_acme_challenges" wollte dann auch noch da rein.

Und für alles andere habe ich ein HTTP Frontend auf Port 443.
In dem vorgeschalteten zusätzlich TCP Frontend kann ich aktuell keinen Vorteil für mich erkennen. Ich möchte mit dem Reverse Proxy ausschließlich Webserver Backends bedienen.

Kann schon sein, dass man das auch anders lösen kann.

Aber: TheHellSite's Ansatz hat den Vorteil, dass es die HTTP->HTTPS Redirection am Rande mit erledigt, außer, wo es nicht gebraucht wird oder sogar schädlich wäre, z.B. für die ACME-Verifikation unter /.well-known..., denn die funktioniert eben nur per HTTP.

Also bringt ein Frontend, dass immer auf HTTPS umleitet, gewisse Probleme mit sich.

Ich will jetzt hier nicht die ganzen Vor- oder potentiellen Nachteile des Tutorials durchkauen. Daher mein Rat: Vergiss, was Du zu wissen glaubst und probier die Anleitung einfach aus. Du wirst überrascht sein.

Die Alternative ist, dass Du alles selbst erfindest. Ich würde das nicht tun, weil die Anleitung 100% für genau Dein Vorhaben funktioniert, Deinen Bedenken zum Trotz. Das setzt natürlich voraus, dass man nichts vergisst.

Übrigens: Das Tutorial behandelt auch - entgegen Deiner Annahme - keine reinen TCP-Verbindungen bzw. "Nicht-Webserver". Es geht nur um HTTP und HTTPS, man kann aber durch Hinzunahme weiterer Frontends natürlich auch beispielsweise SMTP(S) oder IMAP(S) bedienen. Das ist aber nicht Gegenstand des Tutorials.
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Quote from: meyergru on November 27, 2024, 04:13:50 PM
Aber: TheHellSite's Ansatz hat den Vorteil, dass es die HTTP->HTTPS Redirection am Rande mit erledigt, außer, wo es nicht gebraucht wird oder sogar schädlich wäre, z.B. für die ACME-Verifikation unter /.well-known..., denn die funktioniert eben nur per HTTP.
Ich hatte das schon eingerichtet gehabt, bevor ich dieses Tutorial kannte.

Er benötigt mit seiner Methode auch zwei Frontends, nur dass das HTTP dann auf die interne IP lauscht.

Auf pfSense ging meine Methode übrigens mit einem einzigen für beide Ports 80 u. 443. Die Regel für das Redirect war dann im Frontend angelegt.
OPNsense hatte bei mir aber beim HTTPS Frontend nicht unterschiedliche Ports akzeptiert. Bei TCP scheint das zu gehen, dann ist aber auch ein zweites erforderlich. Kommt für mich aufs selbe raus.

QuoteIch will jetzt hier nicht die ganzen Vor- oder potentiellen Nachteile des Tutorials durchkauen. Daher mein Rat: Vergiss, was Du zu wissen glaubst und probier die Anleitung einfach aus. Du wirst überrascht sein.
Ja, die Anleitung habe ich mir notiert und ich werde sicher noch mehrmals rein schauen, ob ich was brauchen kann.
Danke dafür.

Ich habe jetzt aber eine neue Herausforderung: Anstatt die ganzen Hostnamen im Map File auf ein Backend zu leiten, möchte ich sie direkt in HAproxy auf einen andren Server weiterleiten. Ich komme da aber mit dem Map File nicht weiter.

In der Regel, wo http-redirect zu setzen wäre, kann ich dann aber nur Conditions für diese Funktion angeben. Demnach brauche ich dann doch wieder meine 14 Conditions.  ::)

Eine Idee noch, vielleicht kann man den Redirect-URL im Map File angeben. Muss ich mir noch genauer ansehen, was das so alles kann.

November 27, 2024, 05:32:23 PM #13 Last Edit: November 27, 2024, 05:34:44 PM by meyergru
Man kommt mit einem Map-File alleine nicht weiter (und man kann dort auch keine URLs angeben), kann aber einfach mehrere Backends (eine pro Weiterleitung) definieren. In denen verzichtet man auf Angabe eines "Real Server", fügt aber eine Regel hinzu.

Die Regel enthält dann die Weiterleitung mittels "http-request redirect  code 301  location https://xxxxxx". Das gesperrte ist der Parameter zur "http-request redirect"-Regel.

Wenn die Weiterleitungen einem Muster folgen, kann man natürlich auch mit einem Backend und einer Regel arbeiten, die entsprechend parametriert ist.

Damit sehen Redirects im Map-File genauso aus wie die Verteilung auf "normale" Backends. Man kann sie zur Unterscheidung ja z.B. xxxxxx_redirect statt xxxxx_backend nennen.

Ergo: Keine einzige Condition.
Intel N100, 4 x I226-V, 16 GByte, 256 GByte NVME, ZTE F6005

1100 down / 440 up, Bufferbloat A+

Verstehe nicht, wie ich da dem Proxy klar mache, wann er diese Backends verwenden soll.

Ich habe aktuell 14 Hosts Muster, die alle auf einen URL weitergeleitet werden sollen. Diese enthalten schon Wildcards, wie ich sie in "Host" Conditions verwenden kann, ansonsten wären es über 20.
Wo ich diese da einbauen soll, kann ich deiner Anleitung leider nicht entnehmen, und ob das Komplexität einspart oder diese nur verlagert.