Hi Toni,

On Wed, Apr 07, 2010 at 04:51:36PM +0300, Toni Mattila wrote:
> Hi,
> 
> Has anyone solved the issue where you have haproxy compiled with TPROXY 
> support and use "source 0.0.0.0 usesrc clientip" configuration when 
> client is behind the tproxied server.
> 
> Scenario:
> Haproxy server with:
> 10.0.0.1/24 IP address this is the "public" side
> 10.1.0.1/24 IP address this is the tproxy side
> 
> Web server with:
> 10.1.0.2/24 IP address (using 10.1.0.1 as default gateway)
> 
> Configuration:
> listen  www 10.0.0.1:80
>         mode    http
>         option http-server-close
>         option abortonclose
>         mode    http
>         balance leastconn
>         source 0.0.0.0 usesrc clientip
>         server server1 10.1.0.2:80 weight 1 check maxconn 270
>         option redispatch
> 
> Let's say www.example.com is mapped to 10.0.0.1 and you try to access 
> www.example.com from webserver using lynx/links/wget you just get:
> HTTP/1.0 503 Service Unavailable
> Cache-Control: no-cache
> Connection: close
> Content-Type: text/html

This is expected, it cannot work because your webserver would have to
reply to itself directly without going back through haproxy, so the
connection does not match at all. It's amusing, because 10 years ago,
people had this issue with NAT-based load balancers. So editors have
added a "proxy" feature so that the LB could translate the source
address to put theirs when reaching the server. Now you have a proxy
which works in this proxy mode by default, and you're trying to make
it work like those old NAT-based LBs and are encountering the same
routing issues.

Since you're using HTTP, it's a real waste of simplicity and performance
to try to work in transparent mode. You'd better work in a normal proxy
mode and configure your web server to report the client's IP address in
the logs instead of relying on haproxy and your kernel to spoof the client.

If for any reason you absolutely want to do that anyway, here are two
possibilities :

1) use two different backends, one for local connections, and another one
   for external ones. The local one must not do transparent proxying :

listen  www 10.0.0.1:80
        mode    http
        option http-server-close
        option abortonclose
        use_backend from-lan if { src 10.1.0.0/24 }
        balance leastconn
        source 0.0.0.0 usesrc clientip
        server server1 10.1.0.2:80 weight 1 check maxconn 270
        option redispatch

backend from-lan
        mode    http
        option http-server-close
        option abortonclose
        balance leastconn
        server server1 10.1.0.2:80 weight 1 maxconn 270 track www/server1
        option redispatch

2) The second option is very dirty. Since 1.4.4 you can make haproxy bind to
a source address presented in an HTTP header. You just have to enable the
x-forwarded-for header except from the LAN. It will then bind to the client's
IP when it comes from outside the LAN and not do any specific binding when
it comes from the LAN :

listen  www 10.0.0.1:80
        mode    http
        option http-server-close
        option abortonclose
        reqidel ^X-Forwarded-For  # just in case your servers would set one
        option forwardfor except 10.1.0.0/24
        balance leastconn
        source 0.0.0.0 usesrc hdr_ip(x-forwarded-for)
        server server1 10.1.0.2:80 weight 1 check maxconn 270
        option redispatch


Hoping this helps,
Willy


Reply via email to