Re: implementing delay...

From: Andrew Azarov <equand#gmail.com>
Date: Sun, 02 Aug 2009 21:16:44 +0200


Hi William,

diff -c -r ./haproxy-1.3.19/include/common/regex.h ../haproxy-1.3.19/include/common/regex.h
*** ./haproxy-1.3.19/include/common/regex.h Mon Jul 27 19:39:21 2009
--- ../haproxy-1.3.19/include/common/regex.h Sat Aug 1 20:51:33 2009


  struct hdr_exp {

      struct hdr_exp *next;
diff -c -r ./haproxy-1.3.19/include/proto/proto_http.h ../haproxy-1.3.19/include/proto/proto_http.h
*** ./haproxy-1.3.19/include/proto/proto_http.h Mon Jul 27 19:39:21 2009
--- ../haproxy-1.3.19/include/proto/proto_http.h Sat Aug 1 22:21:42 2009


diff -c -r ./haproxy-1.3.19/include/proto/proxy.h ../haproxy-1.3.19/include/proto/proxy.h
*** ./haproxy-1.3.19/include/proto/proxy.h Mon Jul 27 19:39:21 2009
--- ../haproxy-1.3.19/include/proto/proxy.h Sat Aug 1 22:22:18 2009


  /* transaction flags dedicated to cookies : bits values 0x40, 0x80 (0-3 shift 6) */
diff -c -r ./haproxy-1.3.19/include/types/proxy.h ../haproxy-1.3.19/include/types/proxy.h
*** ./haproxy-1.3.19/include/types/proxy.h Mon Jul 27 19:39:21 2009
--- ../haproxy-1.3.19/include/types/proxy.h Sat Aug 1 22:01:57 2009


        /* OK let's go on with the BODY now */
        return 1;

+       txn->status = 500;
+       if (req->flags != BF_READ_ERROR)
+               stream_int_retnclose(req->prod, error_message(s, 
HTTP_ERR_500));
+       return 0;
+       //req->analysers = 0;
+         //req->analyse_exp = TICK_ETERNITY;
+                 
+         //s->fe->failed_req++;
+         //if (!(s->flags & SN_ERR_MASK))
+         //        s->flags |= SN_ERR_PRXCOND;
+         //if (!(s->flags & SN_FINST_MASK))
+         //        s->flags |= SN_FINST_T;
+         //return 0;
+         //if ((req->flags & (BF_READ_ERROR | BF_SHUTR)) == 0)
+               //s->logs.tv_request = now;
+               //req->analysers &= ~AN_REQ_HTTP_DELAY;
+               //txn->flags &= ~TX_CLDELAY;
+               //req->analyse_exp = TICK_ETERNITY;
+               //return 1;
+       //s->logs.tv_request = now;
+         //stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_500));
+       //req->analysers = 0;
+       //req->analyse_exp = TICK_ETERNITY;
+
+         //s->fe->failed_req++;
+         //if (!(s->flags & SN_ERR_MASK))
+         //        s->flags |= SN_ERR_PRXCOND;
+         //if (!(s->flags & SN_FINST_MASK))
+         //        s->flags |= SN_FINST_R;
+         //return 0;

+ }
  /* This function is an analyser which processes the HTTP request body. It looks
                cur_idx = txn->hdr_idx.v[old_idx].next;
--- 3120,3127 ----
                else if (unlikely(txn->flags & TX_CLALLOW) &&
                         (exp->action == ACT_ALLOW ||
                          exp->action == ACT_DENY ||
!                         exp->action == ACT_TARPIT ||
!                         exp->action == ACT_DELAY))
                        return 0;
 
                cur_idx = txn->hdr_idx.v[old_idx].next;

                        case ACT_REPLACE:
                                len = exp_replace(trash, cur_ptr, 
exp->replace, pmatch);
                case ACT_REPLACE:
                        *cur_end = term; /* restore the string terminator */

                                if (s->req->analysers & AN_REQ_HTTP_BODY)
                                        if 
(!http_process_request_body(s, s->req))
                                                break;
 
                                /* Just make sure that nobody set a 
wrong flag causing an endless loop */
!                               s->req->analysers &= AN_REQ_INSPECT | 
AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_BODY;  
                                /* we don't want to loop anyway */
                                break;
--- 751,766 ----
                                        if (!http_process_tarpit(s, s->req))
                                                break;
 
+                               if (s->req->analysers & AN_REQ_HTTP_DELAY)
+                                       if (!http_process_delay(s, s->req))
+                                               break;
+
                                if (s->req->analysers & AN_REQ_HTTP_BODY)
                                        if 
(!http_process_request_body(s, s->req))
                                                break;
 
                                /* Just make sure that nobody set a 
wrong flag causing an endless loop */
!                               s->req->analysers &= AN_REQ_INSPECT | 
AN_REQ_HTTP_HDR | AN_REQ_HTTP_TARPIT | AN_REQ_HTTP_DELAY | AN_REQ_HTTP_BODY;  
                                /* we don't want to loop anyway */
                                break;


Here's the diff, it's not perfect though (I've been doing it in ee in Freebsd to test on working system), more like a hack. Then in config (I do it in the frontend) you should write something like:

timeout delay 30s
reqidelay ^.*Opera.*$

Though this diff skips the delay at all :( dunno why.

Willy Tarreau wrote:

> On Sun, Aug 02, 2009 at 03:29:35PM +0200, Andrew Azarov wrote:
>   
>> I've done everything you suggested, now upon the match it gives right 
>> away 400 error (passes through the request processing further)... Maybe 
>> I should loop inside function to check for the tick? (or maybe shouldn't 
>> because it might block?)
>>     
>
> your analyser must always check the ticks, yes, as it may be called for
> any reason.
>
>   
>> Also is 1.4-dev1 stable enough for production?
>>     
>
> yes till now it is (and is used by a few sites who are taking profit of
> its ability to slightly reduce the number of packets per session). It's
> also why I wanted to release it now, before breaking it into pieces due
> to more sensible changes. I'd say that right now it's 1.3.19 + a few
> features. Of course the risk of regression is never 100% null, but it is
> very close right now.
>
>   
>> We are kicking ddos bots 
>> with haproxy (and very successfully), just that haproxy doesn't have 
>> rate limit per ip
>>     
>
> planned but not done yet :-/
>
>   
>> and delay per request
>>     
>
> same :-)
>
>   
>> and cookie management 
>> (redirecting request, setting and keeping random cookie in memory for 1 
>> ip for X time) with bouncing of if cookie is ! .
>>     
>
> I had written something on that, with a very complete algorithm which would
> count the number of cookies assigned to clients, as well as the number of
> times a cookie was reused. All that in order to prevent DDoS boxes from
> connecting to your site without analysing your response.
>
>   
>> Thought I'd start implementing from the least problematic :) however the 
>> arch of this program is complex so I need some time to analyse it, and I 
>> don't have that time unfortunately.
>>     
>
> Please send me your current patch and config, I can help on this and we'll
> both save some time.
>
> Regards,
> Willy
>
>
>   

Best Regards,
Andrew Received on 2009/08/02 21:16

This archive was generated by hypermail 2.2.0 : 2009/08/02 21:30 CEST