]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http-request tarpit deny_status.
authorJarno Huuskonen <jarno.huuskonen@uef.fi>
Mon, 6 Mar 2017 12:56:36 +0000 (14:56 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 14 Mar 2017 09:41:54 +0000 (10:41 +0100)
Implements deny_status for http-request tarpit rule (allows setting
custom http status code). This commit depends on:
MEDIUM: http_error_message: txn->status / http_get_status_idx.

doc/configuration.txt
src/proto_http.c

index 3ca40c3a6c5a6474d547c28fe05779c88710800c..a505f70adaad1ade4e0190125b632e37f86527af 100644 (file)
@@ -3652,8 +3652,8 @@ http-check send-state
 
   See also : "option httpchk", "http-check disable-on-404"
 
-http-request { allow | tarpit | auth [realm <realm>] | redirect <rule> |
-              deny [deny_status <status>] |
+http-request { allow | auth [realm <realm>] | redirect <rule> |
+              tarpit [deny_status <status>] | deny [deny_status <status>] |
               add-header <name> <fmt> | set-header <name> <fmt> |
               capture <sample> [ len <length> | id <id> ] |
               del-header <name> | set-nice <nice> | set-log-level <level> |
@@ -3697,7 +3697,8 @@ http-request { allow | tarpit | auth [realm <realm>] | redirect <rule> |
     - "tarpit" : this stops the evaluation of the rules and immediately blocks
       the request without responding for a delay specified by "timeout tarpit"
       or "timeout connect" if the former is not set. After that delay, if the
-      client is still connected, an HTTP error 500 is returned so that the
+      client is still connected, an HTTP error 500 (or optionally the status
+      code specified as an argument to "deny_status") is returned so that the
       client does not suspect it has been tarpitted. Logs will report the flags
       "PT". The goal of the tarpit rule is to slow down robots during an attack
       when they're limited on the number of concurrent requests. It can be very
index 9239823326fd85b631e71b268458d54b7c4925c0..7fed50e6515c8fb0abcb9108d77a5ec0ee5e0d98 100644 (file)
@@ -4410,8 +4410,10 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
                if (txn->flags & TX_CLDENY)
                        goto deny;
 
-               if (txn->flags & TX_CLTARPIT)
+               if (txn->flags & TX_CLTARPIT) {
+                       deny_status = HTTP_ERR_500;
                        goto tarpit;
+               }
        }
 
        /* add request headers from the rule sets in the same order */
@@ -4500,6 +4502,8 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
        if (s->be->cookie_name || sess->fe->capture_name)
                manage_client_side_cookies(s, req);
 
+       txn->status = http_err_codes[deny_status];
+
        req->analysers &= AN_REQ_FLT_END; /* remove switching rules etc... */
        req->analysers |= AN_REQ_HTTP_TARPIT;
        req->analyse_exp = tick_add_ifset(now_ms,  s->be->timeout.tarpit);
@@ -4929,7 +4933,6 @@ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
         */
        s->logs.t_queue = tv_ms_elapsed(&s->logs.tv_accept, &now);
 
-       txn->status = 500;
        if (!(req->flags & CF_READ_ERROR))
                http_reply_and_close(s, txn->status, http_error_message(s));
 
@@ -9075,15 +9078,21 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                goto out_err;
        }
 
-       rule->deny_status = HTTP_ERR_403;
        if (!strcmp(args[0], "allow")) {
                rule->action = ACT_ACTION_ALLOW;
                cur_arg = 1;
-       } else if (!strcmp(args[0], "deny") || !strcmp(args[0], "block")) {
+       } else if (!strcmp(args[0], "deny") || !strcmp(args[0], "block") || !strcmp(args[0], "tarpit")) {
                int code;
                int hc;
 
-               rule->action = ACT_ACTION_DENY;
+               if (!strcmp(args[0], "tarpit")) {
+                   rule->action = ACT_HTTP_REQ_TARPIT;
+                   rule->deny_status = HTTP_ERR_500;
+               }
+               else {
+                       rule->action = ACT_ACTION_DENY;
+                       rule->deny_status = HTTP_ERR_403;
+               }
                cur_arg = 1;
                 if (strcmp(args[cur_arg], "deny_status") == 0) {
                         cur_arg++;
@@ -9103,13 +9112,10 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li
                         }
 
                         if (hc >= HTTP_ERR_SIZE) {
-                                Warning("parsing [%s:%d] : status code %d not handled, using default code 403.\n",
-                                        file, linenum, code);
+                                Warning("parsing [%s:%d] : status code %d not handled, using default code %d.\n",
+                                        file, linenum, code, http_err_codes[rule->deny_status]);
                         }
                 }
-       } else if (!strcmp(args[0], "tarpit")) {
-               rule->action = ACT_HTTP_REQ_TARPIT;
-               cur_arg = 1;
        } else if (!strcmp(args[0], "auth")) {
                rule->action = ACT_HTTP_REQ_AUTH;
                cur_arg = 1;