Using "X-Forwarded-For" in Apache or PHP
An issue that often comes up for users of any full proxy-based product is that the original client IP address is often lost to the application or web server. This is because in a full proxy system there are two connections; one between the client and the proxy, and a second one between the proxy and the web server. Essentially, the web server sees the connection as coming from the proxy, not the client.
Needless to say, this can cause problems if you want to know the IP address of the real client for logging, for troubleshooting, for tracking down bad guys, or performing IP address specific tasks such as geocoding. Maybe you're just like me and you're nosy, or you're like Don and you want the webalizer graphs to be a bit more interesting (just one host does not a cool traffic graph make, after all!).
That's where the "X-Forwarded-For" HTTP header comes into play. Essentially the proxy can, if configured to do so, insert the original client IP address into a custom HTTP header so it can be retrieved by the server for processing.
If you've got a BIG-IP you can simply enable the ability to insert the "X-Forwarded-For" header in the http profile. Check out the screen shot below to see just how easy it is. Yeah, it's that easy.
If for some reason you can't enable this feature in the HTTP profile, you can write an iRule to do the same thing.
when HTTP_REQUEST { HTTP::header insert "X-Forwarded-For" [IP::client_addr]}
Yeah, that's pretty easy, too. So now that you're passing the value along, what do you do with it?
Modifying Apache's Log Format
Well, Joe has a post describing how to obtain this value in IIS. But that doesn't really help if you're not running IIS and like me have chosen to run a little web server you may have heard of called Apache.
Configuring Apache to use the X-Forwarded-For instead of (or in conjunction with) the normal HTTP client header is pretty simple. ApacheWeek has a great article on how to incorporate custom fields into a log file, but here's the down and dirty. Open your configuration file (usually in /etc/httpd/conf/) and find the section describing the log formats. Then add the following to the log format you want to modify, or create a new one that includes this to extract the X-Forwarded-For value:
%{X-Forwarded-For}i
That's it. If you don't care about the proxy IP address, you can simply replace the traditional %h in the common log format with the new value, or you can add it as an additional header. Restart Apache and you're ready to go.
Getting the X-Forwarded-For from PHP
If you're like me, you might have written an application or site in PHP and for some reason you want the real client IP address, not the proxy IP address. Even though my BIG-IP has the X-Forwarded-For functionality enabled in the http profile, I still need to access that value from my code so I can store it in the database.
$headers = apache_request_headers(); $real_client_ip = $headers["X-Forwarded-For"];
That's it, now I have the real IP address of the client, and not just the proxy's address.
Happy Coding & Configuring!
Imbibing: Coffee
- Lori_MacVittie1Nimbostratus@JefferE
- Lori_MacVittieEmployeeF5 Friday: Latency, Logging, and Sprawl
- Lori_MacVittieEmployeeWILS: Client IP or Not Client IP, SNAT is the Question
- Lori_MacVittieEmployee@jwang
- Lori_MacVittieEmployee@Pete
- Colin_Walker_12Historic F5 AccountYou should only be seeing one IP in the logs. If you're seeing two it's likely because you have a header being inserted with the original address that apache is pulling out and logging, but you're still logging the actual source from the proxy as well. Have you checked your conf settings?
- Lori_MacVittieEmployeeHi Edwin,
- Lori_MacVittieEmployeeThe IP address in the HTTP header will only be as reliable as the source. If the BIG-IP (or proxy) is talking directly to the client, the IP address captured is reliable. If you aren't sure about the source of the request - i.e. the client might be accessing the service through a different proxy first, then you can't be certain that the address forwarded is the correct one.