Hello Willy,
Thanks for your reply and the solution suggested, i just try it and it work as expected. But, in my particular case, ia'ts a bit mess putting this conf, duplicating various lines in a dozen of backends. For the moment i will continue with keep alive disabled and when the option is available, i will be one of the first that trying it. I understand the difficult to full implement the http-request track-sc, really is very tricky. Thanks for your time. Ricardo F. ---------------------------------------- > Date: Sat, 31 Aug 2013 09:20:29 +0200 > From: [email protected] > To: [email protected] > CC: [email protected] > Subject: Re: Issue with tcp-request content and keep alive > > Hello Ricardo, > > On Fri, Aug 30, 2013 at 11:27:45AM +0200, Ricardo F wrote: >> Hello, >> >> I have an issue when trying to track a connection based on a header, with >> tcp-request, and with keep alive enable in a listen section. >> Over the haproxy i have a cdn, which pass the ip of the client at the >> beginning of the X-Forwarded-For header. All the requests are pass through >> this cdn. >> >> This is the configuration: >> >> global >> maxconn 1000 >> log 127.0.0.1 local5 info err >> stats socket /var/run/haproxy.sock mode 0600 level admin >> pidfile /var/run/haproxy.pid >> >> defaults >> mode http >> log global >> retries 3 >> option redispatch >> timeout connect 5s >> timeout client 10s >> timeout server 10s >> timeout http-keep-alive 60s >> timeout http-request 5s >> >> listen proxy-http 192.168.1.100:80 >> mode http >> maxconn 1000 >> balance roundrobin >> stats enable >> option httplog >> option http-server-close >> #option httpclose >> option forwardfor >> >> stick-table type ip size 128m expire 30m store gpc0 >> tcp-request inspect-delay 5s >> tcp-request content track-sc0 req.hdr_ip(X-Forwarded-For,1) if HTTP >> >> acl rule_marked_deny sc0_get_gpc0 gt 0 >> >> use_backend back-deny if rule_marked_deny >> >> default_backend back-http >> >> backend back-deny >> server web-deny 192.168.1.133:80 >> >> backend back-http >> server web-http 192.168.1.101:80 >> >> >> With this conf, all the requests with the header X-Forwarded-For are tracked >> in the sc0 counter with the ip included in it. >> >> If the counter of one ip is update to number one, the request will be send to >> back-deny, this is doing by writing directly in the unix socket from other >> software. Like the example: >> >> # echo "set table proxy-http key 88.64.32.11 data.gpc0 1" | socat stdio >> /var/run/haproxy.sock >> >> Since the moment that this are doing (with keep alive enable) i see that in >> the log of the web-deny backserver (the log are modified for register the >> x-forwarded-for ip instead of the real tcp connection): >> >> 88.64.32.11 - - [30/Aug/2013:09:08:22 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 157.55.32.236 - - [30/Aug/2013:09:08:27 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 88.64.32.11 - - [30/Aug/2013:09:08:27 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 157.55.32.236 - - [30/Aug/2013:09:08:28 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 88.64.32.11 - - [30/Aug/2013:09:08:29 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 157.56.93.186 - - [30/Aug/2013:09:08:31 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> 157.56.93.186 - - [30/Aug/2013:09:08:31 +0200] www.server.com "GET /some/url >> HTTP/1.1" 301 208 >> >> As can see, there are other ips there and only one is with the "1" in the >> table of the Haproxy. This is a small piece of log, but when i try that in a >> server with more traffic, the problem is worse, more ips are redirected to >> this backend without marked for it. >> >> But, if i change the listen secion to "option httpclose", all works well, >> only the marked ips are redirected. Problem solved, but why? >> >> The tcp inspect have problems tracking the request when these are passed >> through the cdn, which route more than one request of various clients in the >> same tcp connection? > > I like your detailed analysis, you almost found the reason. This is because > tcp-request inspects traffic at the beginning of a *session*, not for each > request. BUT! there is a trick to help you do what you need. > > A tcp-request rule put in a backend will be evaluated each time a session > is transferred to a backend. Since the keep-alive with the client is handled > in the frontend, each new request will cause the session to be connected to > the backend, and the tcp-request rules in the backend will see all requests > (which is another reason why server-side keep-alive is a nightmare to > implement). > > So I suggest that you split your "listen" into "frontend" + "backend" and > move the tcp-request rule in the backend. > > I know, you'll tell me "but I can't put a use_backend rule in a backend". > Then simply use "use-server" with a server weight of zero, which will never > be used by regular traffic. > >> Probably the next feature (in the roadmap) http-request track-sc will solve >> this? > > Yes definitely. However for having looked at how to implement it, the > remaining hair on my head stood up straight and remained like this for > 2 days :-) > > The real issues with track-counters is to track events that happened > before the track rule. For example, you decide that you track a session > based on an HTTP request. But then if you want to check sc0_conn_rate, > you expect to find there the connection rate for the criterion you're > tracking. But the connection was already established before you decided > to track the element, so you have to guess that you need to count it > anyway without having an event to do so. That's extremely tricky with > keep-alive because you need to know if the connection was the same as > the last one or a new one... and this for every criterion. I don't have > a complete solution to this yet, it still requires more thinking. > > Regards, > Willy > >

