I'm testing a new web server setup which is having a couple of issues. Essentially, we have a web server, where the code uses the remote IP for some interesting things, and also some apache directories secured down to some certain IP's (our office etc).
However, we've just chucked this behind ha_proxy so we can look at adding some more app servers, but now the remote IP is always coming through as the proxy ip, not the real remote user. This means we can't get to some locations, and our app is behaving a little oddly where user IP is important.
Our config is as follows:
global
maxconn 4096
pidfile /var/run/haproxy.pid
daemon
defaults
mode http
retries 3
option redispatch
maxconn 2000
contimeout 5000
clitimeout 50000
srvtimeout 50000
listen farm xxx.xxx.xxx.xxx:80
mode http
cookie GALAXY insert
balance roundrobin
option httpclose
option forwardfor
stats enable
stats auth username:userpass
server app1 xxx.xxx.xxx.xxx:80 maxconn 1 check
Quoted from the HAProxy doc at haproxy.1wt.eu.
It is stated that the application must treat the X-Forwarded-For HTTP Header to know the client IP adress. Seems like the only way to go in your case.
Updated for HAProxy 1.4
There is a way to recompile HAproxy to include Tproxy which will allow forwarding of the source address.
There's a blog post here about it: http://blog.loadbalancer.org/configure-haproxy-with-tproxy-kernel-for-full-transparent-proxy/
A few notes:
The latest linux kernel (2.6.28-11-server) includes support for TProxy, so recompiling the kernel is not necessary.
Make sure to configure the servers in your web farm with a default gateway address which points to the HAProxy server.
Use rpaf apache module http://stderr.net/apache/rpaf/ I know this is and old post but it took me days to find this. This will present to any application the x-forwarded-for ip.
Note that it would appear that you can override what the application see's my changing the Apache headers:
However, this doesn't work for Apache access via "Allow from" etc.
HAProxy, by design, can't forward the original IP address to the real server, pretty much like any other proxy.
One solution may be, if your only problem is with a web server, to look into the X-forwarded-for HTTP header, which should contain the client's address. Now, that's pretty much application/language specific, but take a look at this example in php:
$headers = apache_request_headers();
$real_client_ip = $headers["X-Forwarded-For"];
If you also want to log the original address, you can modify the LogFormat in httpd.conf to look something like this:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{X-Forwarded-For}i\"" common
Well, it seems that the X-Forwarded-for doesn't work well for your setup. So, is there any special reason for you to stick with haproxy? It seems that IPVS is more aproppriate for your needs (I actually use ldirector which in turn uses ipvs).
Take a look at:
http://kb.linuxvirtualserver.org/wiki/IPVS
and
http://www.vergenet.net/linux/ldirectord/
Using IPVS in 'IP Tunneling' or 'Direct Routing' mode preserves the client's address.
Try mod_extract_forwarded from http://www.openinfo.co.uk/apache/
Easy way with haproxy in mode tcp and nginx :
add send-proxy as server option:
haproxy.conf:
.
.
listen ssl 0.0.0.0:443
mode tcp
balance leastconn
option httpchk GET /ping
option log-health-checks
server w1 192.168.1.1:443 send-proxy check check-ssl verify none
server w2 192.168.1.1:443 send-proxy check check-ssl verify none
.
.
Nginx need support proxy-protocol
nginx.conf:
.
.
listen 192.168.1.1:443 ssl proxy_protocol;
.
.
set_real_ip_from 192.168.1.0/24;
real_ip_header proxy_protocol;
.
.