Lastverteilung ist in vielen Umgebungen nicht mehr wegzudenken. Es sorgt dafür, dass Anfragen gleichmäßig über mehrere Server verteilt werden, was die Verfügbarkeit und Leistung von Anwendungen erheblich verbessert. Allerdings gibt es dabei ein häufiges Problem: Die ursprüngliche Quell-IP-Adresse des Clients geht verloren, was Logging- und Sicherheitstools das Leben schwer macht.
In diesem Beitrag werde ich dir zwei Methoden vorstellen, mit denen dieses Problem der Vergangenheit angehören wird. In Zukunft werden deine Anwendungen die Quell-IP-Adresse direkt auslesen können, und zwar ohne Spielereien wie einen X-Forwarded-For-Header. Eines sei an dieser Stelle aber gesagt. Zur Umsetzung des Artikels brauchst du einen echten Loadbalancer.
Bekannte Reverse-Proxy-Software wie Nginx oder Apache scheiden damit direkt aus. Gute Erfahrungen habe ich im Homelab mit dem Open-Source-Tool HAProxy gemacht. Im kommerziellen Bereich trifft man häufig auf Appliances von Loadbalancer.org oder F5. Entscheidend ist aber nicht, welchen Hersteller du nutzt, sondern dass du die Funktionsweise verstanden hast.
Die im Folgenden vorgestellten Methoden arbeiten auf Layer 4 des OSI-Modells. Sie verteilen also den Netzwerkverkehr basierend auf der Ziel-IP-Adresse und Portnummer. Eine tiefgehende Analyse der Pakete findet daher nicht statt, was eine hohe Geschwindigkeit und geringere Latenz garantiert. Bekannte Anwendungsfälle wären DNS-, Kubernetes oder Video-Streaming-Cluster.
Quell-IP-Transparenz ermöglichen:
In der Praxis gibt es drei Varianten, wie man Source IP Transparency umsetzen kann. Häufig liest man von der Verwendung des X-Forwarded-For-Headers. Diese Methode hat jedoch einige Nachteile. Zum einen müssen die Pakete zunächst auf dem Application Layer (Layer 7) des OSI-Modells bearbeitet werden, was zu Performanceeinbußen führen kann.
Außerdem funktioniert diese Methode nur bei HTTP-Verkehr. Auch muss die im Cluster genutzte Software in der Lage sein, die Header korrekt zu verarbeiten. Geschickter ist daher ein echtes Loadbalancing auf der Transportschicht (Layer 4) des OSI-Modells. Hier haben sich zwei Ansätze durchgesetzt: Network Address Translation (NAT) und Direct Server Return (DSR):
Network Address Translation (NAT):
NAT ist eine weit verbreitete Methode, die nicht nur bei professionellen Loadbalancern, sondern auch bei Heimroutern wie der Fritz!Box zum Einsatz kommt. Einige von euch werden sicherlich schonmal ein Destination-NAT auf die heimische NAS oder Nextcloud-Instanz eingerichtet haben. Ich erkläre das Ganze aber anhand eines hochverfügbaren Loadbalancer-Pärchens.
Bei einem ankommenden Paket wird die Ziel-IP (Virtual IP) der Loadbalancer gegen die IP eines Backend-Servers ausgetauscht. Dieser empfängt nun das Paket, lässt die Anfrage durch die gehostete Anwendung verarbeiten und schickt im Anschluss die Antwort ab. Und genau an dieser Stelle wird es spannend. Der Backend-Server hat nämlich die VIP der Loadbalancer als Gateway eingetragen.
Dadurch kann jetzt ein Source-NAT durchgeführt werden. Die Quell-IP-Adresse des Backend-Servers wird also durch die VIP des Loadbalancer-Pärchens ersetzt. Der anfragende Client bemerkt von all dem nichts, denn die angefragte IP-Adresse antwortet ihm schließlich. Diese Load-Balancing-Methode ist schnell eingerichtet, hat jedoch einen kleinen Nachteil: eine erhöhte Latenz.
- Bei IPv4-Adressen sind Source- und Destination-NAT weit verbreitet. Auch bei IPv6 sind diese Verfahren möglich. Ich würde jedoch die Verwendung von Anycast in Betracht ziehen. Dabei werden die Pakete samt Quell-IP-Adresse zum am besten geeigneten Knoten weitergeleitet. Ausgewählt wird dieser anhand der Entfernung, Latenz, Bandbreite oder Netzwerktopologie.
Direct Server Return (DSR):
Hierbei handelt es sich um eine fortschrittliche Methode, die eine direkte Antwort vom Backend-Server an den Client ermöglicht, ohne dass der Rückverkehr über den Loadbalancer geleitet wird. Diese Vorgehensweise ist eher für versierte Netzwerk-Admins geeignet, da sie etwas schwerer einzurichten ist. In der Praxis wird diese Methode häufig bei Video-Streaming-Diensten genutzt.
Hier müssen nämlich die Loadbalancer entlastet werden. Sind die Anfragen der Clients noch überschaubar in der Größe, sind es die Antworten nämlich nicht mehr. Daher möchte man diese auch nicht durch die Loadbalancer schleusen. Der Kommunikationsablauf lässt sich wie folgt darstellen:
Eingehender Traffic zum Load Balancer:
- Ein Client sendet eine Anfrage an die VIP (Virtual IP) der Loadbalancer.
Änderung der Ziel-MAC-Adresse:
- Der Primary-Loadbalancer empfängt das Paket und ändert die Ziel-MAC-Adresse auf die eines Backend-Servers, während die Ziel-IP-Adresse unverändert bleibt.
Weiterleitung zum Backend-Server:
- Das Paket wird an den Backend-Server weitergeleitet. Dieser empfängt das Paket und sieht die VIP als Ziel-IP-Adresse. Da diese auf dem Loopback-Interface vorhanden ist, wird er auch ordnungsgemäß antworten.
Direkte Antwort des Servers an den Client:
- Der Backend-Server sendet die Antwort direkt an den Client zurück, wobei die VIP als Quell-IP-Adresse verwendet wird. Der Antwortverkehr umgeht den Loadbalancer also vollständig. Eine weitere Anfrage des Clients würde natürlich wieder auf dem Loadbalancer-Pärchen aufschlagen.
Insgesamt betrachtet ist DSR eine elegante Lösung, die durch eine effiziente Handhabung des Traffics überzeugt. In Loadbalancing-Szenarien, insbesondere für Anwendungen mit hohem Datenaufkommen oder spezifischen Anforderungen an die Latenz und Skalierbarkeit ist Direct Server Retun eine Top-Wahl. Und ein kleiner Hinweis am Rande, häufig wird auch von Direct Routing gesprochen.
Mein persönlicher Favorit:
Die Beibehaltung der Quell-IP-Adresse ist entscheidend für Logging, Sicherheit und Benutzeranalyse. Während der X-Forwarded-For-Header für HTTP-Verkehr eine einfach zu implementierende Möglichkeit darstellt, ist er meist nicht die performanteste Lösung. NAT und DSR sind hingegen zwei bewährte Methoden, die eine effiziente Umsetzung von Source IP Transparency ermöglichen.
Durch die Wahl der richtigen Methode können Unternehmen sicherstellen, dass ihre Backend-Server die notwendigen Informationen erhalten, um optimal zu funktionieren. Beide Ansätze tragen dazu bei, die Effizienz und Performance der Netzwerkinfrastruktur zu verbessern und gleichzeitig die Transparenz der Quell-IP-Adresse zu gewährleisten.
Ich persönlich bin ein großer Fan von Direct Server Return. Und warum dem so ist, möchte ich dir zum Abschluss des Artikels aufzeigen:
- Entlastung der Loadbalancer: Da der rückfließende Verkehr den Loadbalancer umgeht, werden die Loadbalancer erheblich entlastet. Dies führt zu einer verbesserten Skalierbarkeit und Leistung, da die Ressourcen des Loadbalancers ausschließlich für die Verarbeitung eingehender Anfragen verwendet werden können.
- Keine Störung durch andere Traffic-Arten: Durch die Verwendung von DSR werden andere Arten von Verkehr, wie beispielsweise Server-Updates oder interne Kommunikation mit weiteren beteiligten Services, nicht über die Loadbalancer geleitet. Dies sorgt für eine klare Trennung von Datenverkehrstypen und verhindert potenzielle Engpässe oder Probleme durch die Überlastung der Loadbalancer.
- Verbesserte Kontrolle über den Traffic-Fluss: DSR ermöglicht eine direkte Kommunikation zwischen dem Client und dem Backend-Server für den rückfließenden Verkehr. Dadurch behältst du eine bessere Kontrolle über den Traffic und kannst gezielt bestimmte Verbindungen oder Routing-Regeln implementieren, um die Anforderungen deiner Anwendung besser zu erfüllen.
- Geringere Latenz: Da der rückfließende Verkehr direkt zwischen dem Client und dem Backend-Server erfolgt, wird die Latenzzeit reduziert, da keine zusätzlichen Umleitungen über den Loadbalancer erforderlich sind. Dies ist besonders wichtig für Anwendungen, die eine niedrige Latenz erfordern, wie Video-Streaming, Gaming oder Telefonie.
- Falls beide Methoden nicht infrage kommen, bietet sich noch Source-NAT an. Hierbei wird die Quell-IP durch die VIP der Loadbalancer ersetzt, wodurch die Client-IP verloren geht. Netzwerk-Änderungen auf den Servern sind jedoch nicht erforderlich. Bei HTTP-Traffic kann zudem der X-Forwarded-For-Header gesetzt werden, wenn die Loadbalancer dies unterstützen.