From 800d1761d0bb2ee2d0951d2e39b8b163479158cd Mon Sep 17 00:00:00 2001 From: Jarno Huuskonen Date: Mon, 6 Mar 2017 14:56:36 +0200 Subject: [PATCH] MINOR: http-request tarpit deny_status. 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 | 7 ++++--- src/proto_http.c | 26 ++++++++++++++++---------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 3ca40c3a6..a505f70ad 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -3652,8 +3652,8 @@ http-check send-state See also : "option httpchk", "http-check disable-on-404" -http-request { allow | tarpit | auth [realm ] | redirect | - deny [deny_status ] | +http-request { allow | auth [realm ] | redirect | + tarpit [deny_status ] | deny [deny_status ] | add-header | set-header | capture [ len | id ] | del-header | set-nice | set-log-level | @@ -3697,7 +3697,8 @@ http-request { allow | tarpit | auth [realm ] | redirect | - "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 diff --git a/src/proto_http.c b/src/proto_http.c index 923982332..7fed50e65 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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;