X-Forwarded-For

Diese Seite ist wichtig, wenn Sie einen Loadbalancer in einer Single-Arm-Konfiguration für den Zugriff auf HTTP-Server verwenden. Nur mit einer kleinen Anpassung erhalten Sie auf dem Backend-Server die Client-IP für weitere Auswertungen.

Brauch ich das?

Ich würde sagen: "unbedingt", wenn Sie vor ihren WebServern einen Loadbalancer oder Reverse Proxy haben und bei Auswertungen und Fehlersuche die Client-IP als Filterkriterium nutzen wollen. Für den Betrieb von einem Loadbalancer oder Reverse Proxy vor einem oder mehreren Servern gibt es quasi drei Varianten, die ich hier in Kurzform wiedergeben. Es gibt verschiedene Arten einen HLB einzubinden

  • Layer 7
    Der Client landet beim HLB und der HLB hat das „Zertifikat“ und sieht aus wie ein Webserver. Der HLB holt sich dann die Daten „von hinten“ und kann dabei die http-Requests auch inspizieren und verändern. In dem Zuge kann er auch den x-forwarded-for-header mit der echten Client-IP addieren, muss aber eben auch HTTPS aufbrechen. Dafür kann es auch URLs filtern und Inhalte umschreiben (Application Firewall)
  • Layer 4
    Der HLB nimmt das Paket an und sendet es an ein Backend weiter. Damit ändert er die „Destination IP“ auf den Real-Server. Damit das Paket aber auf dem Rückweg wieder bei HLB durch muss, gibt es zwei Optionen:
    • Der HLB ändert die Source-IP auf seine eigene IP. Der Backend Server sendet so das Paket an den HLB und alles geht. Leider gibt es hier zwei Problem:
      • Der Backend Server sieht nicht mehr die Client IP (was z.B. bei Exchange beim Mailempfang untauglich ist).
      • Der Loadbalancer kann auch an die 65535-Port Grenze laufen. Wenn also viele Clients parallel arbeiten, ist diese Variante von Nachteil.
    • der HLB ändert die Source-IP NICHT. Dann muss der Backend Service aber den HLB als „Default Gateway“ nutzen. Der HLB ist dann also auch „IP-Router“ für jeden Verkehr des Backend Server (Monitoring, AD-Abfragen, Backup, Updates etc.). Das haben wir bei Exchange so eingerichtet und funktioniert super. Allerdings müssen die Backend Server dann in einem eigenen IP-Subnetz stehen, damit der HLB auch „routen“ kann.

Es gibt noch einige andere Details zu beachten. Es gibt also nur einen Fall, bei dem die Client IP nicht sichtbar ist. Aber das ist sehr häufig die aktuelle Konfiguration, da Sie sehr einfach einzurichten ist. Die meisten Firmen installieren ihren Loadbalancer oder Reverse-Proxy vor Exchange oder anderen Servern einfach nur mit einer Netzwerkkarte und die Umsetzung der Pakete erfolgt dann wie hier aufgezeichnet.

Ein Paket von Client A zur IP "B" wird vom Loadbalancer zum Server C1 gesendet. Der Loadbalancer muss dabei nicht nur die Ziel-IP-Adresse des Pakets auf den "echten Server" anpassen, sondern auch die Quelladresse so umschreiben, dass die Rückantwort wieder beim Loadbalancer landet. Nur so kann er auch die Rückantwort anpassen. Ansonsten würde wohl jede Firewall und jeder Client das Paket verwerfen da es von einer anderen IP-Adresse kommt. Allerdings sehen dann die Server C1 und C2 eben nicht mehr die IP-Adresse des Clients A sondern eine IP-Adresse des Loadbalancers.

Beachten Sie dabei aber, dass alle Anfragen an die Backend Server mit der Source-IP des Loadbalancers ankommen. Als Quell-Ports einer IP stehen einem IP-Stack aber max. 65535 Ports zur Verfügung. Auch hier könnten Sie in Probleme kommen.

Wenn der Loadbalancer schon installiert ist, dann können Sie einfach im IISLog schon nachschauen, welche Client-IP im Feld "c-ip" zu finden ist. Alternativ hilft auch mal ein Blick in die PowerShell mit:

Get-NetTCPConnection | group remoteaddress -noelement | sort count -Descending

Sie sehen dann sehr schnell die entfernten Clients mit sehr vielen Connections.

Add Header

Um diese Einschränkung hinsichtlich der Protokollierung zu umgehen, können eigentlich alle professionellen Loadbalancer und Reverse-Proxy-Server in den HTTP-Datenstrom einen Header addieren.

Allerdings ist es dazu bei HTTPS erforderlich, dass der Loadbalancer den SSL-Datenstrom terminiert und ggfls. zu den Server erneut verschlüsselt. Nur so kann er einen Header addieren

Wie der Header addiert wird, unterscheidet sich je nach Produkt. Ich kann hier nur ein paar allgemeine Links bekannter Loadbalancer publizieren. Prüfen Sie die Details bitte mit ihrem Lieferanten oder Support.

Sie sehen schon, dass das Feld "X-Forwarded-For" keine exotische Einstellung ist, sondern ich finde es eher verwunderlich, dass das Feld nicht automatisch addiert wird, wenn es möglich ist.

Protokollierung im IIS

Die Erweiterung des HTTP-Requests um das "X-Forwarded-For"-Feld ist aber nur ein Teil der erforderlichen Änderungen. Der nachgelagerte Webserver muss dieses Feld natürlich auch in die Logs schreiben. Beim IIS ist das recht einfach über die GUI zu konfigurieren, indem Sie auf der Webseite auf "Logging" gehen und dann auf "Select Fields". Hier können Sie dann "Custom Fields" addieren:

So lasse ich dann die Information aus dem Request Header in das IISLog schreiben. Die Einstellung können Sie natürlich auch per PowerShell vornehmen. Das ist insbesondere für automatische Installationen und große Serverfarmen interessant. Manuelle Änderungen per GUI sind doch recht fehleranfällig:

Add-WebConfigurationProperty `
   -pspath 'MACHINE/WEBROOT/APPHOST' `
   -filter "system.applicationHost/sites/siteDefaults/logFile/customFields" `
   -name "." `
   -value @{logFieldName='X-Forwarded-For';sourceName='X-Forwarded-For';sourceType='RequestHeader'}

Für andere WebServer sind ebenfalls Konfigurationsdateien zu ändern:

Andere Protokolle?

Die Erweiterung eines HTTP-Headers um das Feld "X-Forwarded-For" funktioniert schon aus technischer Sicht nur für das Protokoll HTTP. Beim Einsatz von HTTPS muss der Reverse Proxy oder Loadbalancer schon die SSL-Verbindung terminieren und neu zum Backend Service leiten. Andere Protokolle können davon nicht profitieren.

Allerdings gibt es durchaus genug Gründe, warum z.B. bei SMTP der Exchange Server die Client-IP-Adresse sehen sollte. Bei Exchange 2007 und höher können Administratoren mehrere Receive Connectoren auf dem gleichen Port konfigurieren, solange der Server z.B. anhand der Client-IP-Adresse den richtigen Connector bei einer Verbindung auswählen kann. Diese Entscheidung fällt natürlich schon beim TCP-Connect. Wenn diese Anforderung erforderlich ist, dann bleibt ihnen nur der Umbau des Loadbalancer auf eine "Dual-Arm"-Konfiguration, bei der das Default Gateway der Server auf den Loadbalancer gesetzt wird. So wird dann doch erreicht, dass die Rückantworten auch wieder durch den Loadbalancer gehen, der dann die Adressen wieder korrekt umschreiben kann.

Wenn statt eines Loadbalancer ein Application-Proxy eingesetzt wird, kann dieser natürlich auch die Client-IP addieren. Bei SMTP ist das relativ einfach, da jedes Relay ja einen Header addieren kann. Das machen insbesondere Spamfilter sehr häufig zur Fehlersuche.

Allerdings hilft dies nicht bei der Auswahl eines Receive Connectors beim Exchange Server. Sie können natürlich das "Problem" auch einfach eine Station nach vorne verlagern und die Protokollierung und Verbindungsfilterung dem Loadbalancer übertragen. Dann ist er aber meist nicht mehr ein einfacher Layer-4-Balancer, sondern muss schon etwas mehr vom Protokoll verstehen.

Oder doch Dual-Arm?

Sobald sie natürlich Protokolle verteilen, die der Loadbalancer nicht als Application Proxy aufbrechen und erweitern kann oder Sie aus anderen Gründen gerne die echte Client-IP auf dem Backend-Server sehen wollen, dann steht ihnen immer noch de Weg offen, den Loadbalancer in den Datenstrom als Router einzubinden. Die Backend Server nutzen dann den Loadbalancer als Default Gateway

So kann der LB die Pakete in beide Richtungen unter Beibehaltung der Client-IP umschreiben. Ehe Sie nun aber "Heureka" rufen und ihr komplettes Netzwerk umbauen, sollten Sie einige Randbedingungen berücksichtigen

  • Last und Bandbreite
    Heute ist IPv4-Routing eigentlich keine besondere Aufgabe und sollten den Loadbalancer im Regelbetrieb nicht überfordern. Wenn Sie aber über die gleiche Verbindung auch ein Backup oder Restore ziehen, dann könnte eine 1GBit-Verbindung zu knapp sein.
  • Subnetze
    Wenn Sie die Server "hinter" einem Loadbalancer verstecken, dann bekommen Sie ein eigenes IP-Subnetz. Die Clients interessiert das weniger aber andere Dienste wie Backup, Monitoring und natürlich das Active Directory müssen den Leitweg kennen
  • Dienste hinter dem HLB
    Denken Sie daran, dass alle Dienste mit Zugriff auf die Server "vor" dem Loadbalancer stehen müssen. Das bedeutet aber auch, dass diverse Commandlets auf Exchange Server nicht mehr den virtuellen Namen nutzen können. Ein Zugriff von hinten auf IP-Adresse "B" kann der LB zwar umschreiben aber wenn die Source-IP unverändert ist, geht die Antwort an ein System im gleichen Subnetz nicht mehr durch den LB. Das bedeutet, dass Faxserver u.a. Systeme auf dem Exchange Server nur mit besonderen Anpassungen laufen.

Das ist nur die Kurzfassung aber eine Dual-Arm-Konfiguration ist aus meiner Sicht dennoch meine bevorzugte Variante, da neben der Client-IP z.B. auch das Port-Limit (Siehe 65535 Port-Limit) umgangen wird. Beim Single-Arm verbergen sich ja quasi alle Clients hinter der LB-Adresse.

Weitere Links