PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


Archive for the ‘X_Forwarded_For’ tag

Client-IP Problem bei Reverse-Proxy-Betrieb

without comments

In einem meiner letzten Artikel schrieb ich ja bereits über Reverse-Proxies. Der Reverse-Proxy nimmt die Verbindung vom Client (Browser) entgegen, dann kann er entweder selbst den Request bedienen (statische Dateien von der lokalen Platte oder aus dem Cache), oder er verbindet sich zu einem der Backend-Webserver, ruft dort die geforderte Datei ab, und sendet sie dem Client zurück.

Ein Problem entsteht nun auf dem Backend-Webserver: Alle Requests kommen vom Reverse-Proxy. Wenn nun in den PHP-Scripten die Client-IP-Adresse verwendet wird, steht darin die IP des Reverse-Proxies.

Betroffen ist in diesem Fall die PHP-Variable  $_SERVER[‚REMOTE_ADDR‘]  als auch das Apache-Log, denn dort taucht auch immer nur die IP des Reverse-Proxy auf.

xforwardedfor3

127.0.0.1 - - [03/Oct/2009:10:45:24 +0200] "GET /phpinfo.php HTTP/1.0" 200 7800 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729) FirePHP/0.3"

127.0.0.1 deshalb, da ich direkt auf der Linux-Maschine sowohl den nginx als auch den Apache laufen habe.

Da gibt es natürlich Lösungen. Zuerst einmal müssen wir die Client-IP irgendwie an den Backend-Webserver übergeben. Dafür gibt es den Header „X_FORWARDED_FOR“, da wird der nginx die Client-IP reinschreiben.

Im nginx muss dann folgendes gesetzt werden:

location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect off;
........

Ein phpinfo() liefert dann die korrekte Client-IP in X_FORWARDED_FOR (34 ist der Server, 33 der Client):

xforwardedfor4

Nun installieren wir noch ein Apache-Modul. Dieses Modul sorgt dafür, dass in die Variable $_SERVER[‚REMOTE_ADDR‘]  der Wert aus X-FORWARDED-FOR geschreiben wird, damit wir keine PHP-Scripte anpassen müssen. Außerdem sorgt dieses Modul dafür, dass im Apache-Log dieser Wert auftaucht.

Das Module, das es für diese Aufgabe gibt, lautet „mod_rpaf“. Einfach danach googlen, downloaden und in der Apache-Konfiguration laden. Oder unter Linux:

sudo apt-get install libapache2-mod-rpaf

Noch kurz konfigurieren /etc/apache2/mods-available/rpaf.conf:

<IfModule mod_rpaf.c>
RPAFenable On
RPAFsethostname On
RPAFproxy_ips 127.0.0.1
</IfModule>

Das Ergebnis sieht dann so aus:

xforwardedfor2

192.168.1.33 - - [03/Oct/2009:10:47:23 +0200] "GET /phpinfo.php HTTP/1.0" 200 7808 "-" "Mozilla/5.0 (Windows; U; Windows NT 6.0; de; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729) FirePHP/0.3"

Möchte man das Modul nicht installieren, muß man überall in seinen PHP-Scripten die Variable $_SERVER[‚X_FORWARDED_FOR‘] statt $_SERVER[‚REMOTE_ADDR‘] nutzen, und das Apache-Log anpassen:

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

Damit hätten wir das Problem auch gelöst, überall steht nun die Client-IP zur Verfügung, die Anwendungen und Logs laufen wieder korrekt.

Written by Michael Kliewe

Oktober 7th, 2009 at 8:35 am