Betreibt man Web-Applikationen hinter einem Load Balancer so bekommt man in den
normalen IP-Headern nur die IP-Adresse der Load Balancer. Mit den X-Fowarded
http-Headern hat sich ein Quasi-Standard entwickelt, der von den meisten Load
Balancern implementiert wird. Apache CXF erlaubt das automatische Auslesen dieser Header. Vorher möchte ich aber kurz auf die Bedeutung eingehen:
X-Forwarded-For
: Dieser Header enthält die IP Adresse des Clients für den der Load Balancer den Aufruf weitergeleitet hat. Kommen auf dem Weg vom Client zum Backend mehrere Load Balancer zum Einsatz werden auch die IP Adressen der Zwischenstationen, durch Komma getrennt, in diesem Header mitgegeben.X-Forwarded-Proto
: Dieser Header enthält das Protokoll (http
oderhttps
) mit dem der Client den Service aufgerufen hat. Es wird beispielsweise um bei URLs das korrekte Protokoll zurückzugeben. Das Protokoll zwischen Client, Load Balancer und Backend kann sich durchaus unterscheiden wenn beispielsweise der Load Balancer auch den TLS Endpoint darstellt und die Backend Services nur noch überhttp
aufruft.- Es gibt auch noch weitere
X-Forwarded
Header auf die ich hier aber nicht eingehe da sie weniger weit verbreitet sind und auch nicht von CXF behandelt werden.
CXF ab Version 3.0.2
bzw. 3.1.0
erlaubt uns nun mit einem relativ unbekannten Feature die genannten Header automatisch auslesen zu lassen. Mit dem Ticket CXF-5937 wurde zu diesem Zweck ein neuer Servlet Parameter implementiert: use-x-forwarded-headers
. Wird dieser aktiviert, verarbeitet CXF die http-Header aus und legt sie in einem Filter, der HttpServletRequestWrapper implementiert, ab. Liest man nun die IP Adresse aus der Message
aus, kommt der Filter zum Einsatz und gibt, falls vorhanden, die Original-IP Adresse zurück.
Ihr müsst also eure Servlet Definition in eurer web.xml
anpassen:
{% include_code 2015-08-25-cxf-forwarded-for/web.xml %}
In den Zeilen 8 - 12 seht ihr den neuen Init Parameter use-x-forwarded-headers
, der mit true
belegt wird. Mehr ist nicht zu tun!
Wenn ihr nun in eurem Web Service Aufruf, wie bisher auch, die Client Adresse aus der Message
holt, bekommt ihr den Wert aus dem Header:
{% include_code Implementierung eines Beispiel Services 2015-08-25-cxf-forwarded-for/Service.java %}
Wir testen das ganze noch mit SoapUI indem wir die WSDL importieren und einen Beispiel-Aufruf erstellen. Bisher haben wir noch nichts mit den HTTP Headern gemacht, sodass 127.0.0.1
ausgegeben wird.
Und jetzt setzen wir den HTTP Header in SoapUI und schauen uns das Ergebnis an: Der Service verwendet nun den Wert aus dem X-Forwarded-For Header! Am Beispiel sieht man auch, wieso dieses Feature nicht standardmäßig aktiviert ist: für einen nicht ganz wohlgesinnten Client ist es ein Leichtes falsche Werte in diesem Header zu übergeben. Ein Load Balancer sollte das behandeln. Ist kein Load Balancer vorgeschaltet, macht es auch keinen Sinn diese Header zu verarbeiten.
Wenn ihr selbst damit etwas rumspielen wollt, könnt ihr Euch das im Beispiel verwendete Projekt hier herunterladen: cxf-forwarded-example.zip