Hello, On Fri, Jun 24, James Brown wrote: > +1 I am also using a fake backend with no servers and a 503 errorfile, and > it confuses everybody who looks at the config or the metrics. Being able to > directly emit a 429 would be fantastic.
This is my first attempt in adding deny_status to: http-request tarpit [deny_status <status>] First patch updates parse_http_req_cond so config parser accepts [deny_status <status>] for http-request tarpit (and sets rule->deny_status). The second patch updates http_process_req_common/http_process_tarpit to use deny_status. http_process_tarpit has a switch statement for mapping txn->status (200<->504) to HTTP_ERR_<num>(enum). Is this reasonable ? Do tarpitted (http-request tarpit / req(i)tarpit) requests always go thru http_process_req_common (so txn->status is always set to txn->status = http_err_codes[deny_status]) ? Or is there a possibility that int deny_status could be overwritten in http_process_req_common (with multiple deny/block/tarpit rules) ? Both patches are against 1.7.1, but if this looks otherwise ok then I can modify the patches against 1.8dev and add missing documentation. I've used this minimal config for testing: (missing defaults/global): frontend test bind ipv4@127.0.0.1:8080 http-request tarpit deny_status 429 if TRUE default_backend test_be frontend test2 bind ipv4@127.0.0.1:8081 http-request tarpit if TRUE default_backend test_be frontend test3 bind ipv4@127.0.0.1:8082 reqtarpit . if TRUE default_backend test_be backend test_be server dummy 127.0.0.1:80 id 1 curl -v http://127.0.0.1:8080 should be tarpitted with status 429 and curl -v http://127.0.0.1:8081 (and :8082) with 500. -Jarno -- Jarno Huuskonen
>From 3f82309f1b96330ac75bc53a35b683cdc41ab61d Mon Sep 17 00:00:00 2001 From: Jarno Huuskonen <jarno.huusko...@uef.fi> Date: Mon, 26 Dec 2016 13:47:30 +0200 Subject: [PATCH] parse_http_req_cond: parse deny_status code for http-request tarpit. To: haproxy@formilux.org X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 --- src/proto_http.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index aa8d997..dce1ac7 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -9007,11 +9007,15 @@ struct act_rule *parse_http_req_cond(const char **args, const char *file, int li 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; + } cur_arg = 1; if (strcmp(args[cur_arg], "deny_status") == 0) { cur_arg++; @@ -9031,13 +9035,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, rule->action == ACT_ACTION_DENY ? 403: 500); } } - } 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; -- 1.8.3.1
>From 25b5e0993e3be2af34b0c3c4957e7ddbae50b8f3 Mon Sep 17 00:00:00 2001 From: Jarno Huuskonen <jarno.huusko...@uef.fi> Date: Sun, 1 Jan 2017 12:16:44 +0200 Subject: [PATCH] http_process_tarpit: add deny_status code/message. To: haproxy@formilux.org X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 --- src/proto_http.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/proto_http.c b/src/proto_http.c index dce1ac7..63277e3 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -4347,8 +4347,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 */ @@ -4437,6 +4439,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_FLT_END; /* remove switching rules etc... */ req->analysers |= AN_REQ_HTTP_TARPIT; req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.tarpit); @@ -4843,6 +4847,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit) */ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit) { + int http_err_code_idx; struct http_txn *txn = s->txn; /* This connection is being tarpitted. The CLIENT side has @@ -4863,9 +4868,44 @@ 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, HTTP_ERR_500)); + if (!(req->flags & CF_READ_ERROR)) { + switch(txn->status) { + case 500: + http_err_code_idx = HTTP_ERR_500; + break; + case 403: + http_err_code_idx = HTTP_ERR_403; + break; + case 429: + http_err_code_idx = HTTP_ERR_429; + break; + case 504: + http_err_code_idx = HTTP_ERR_504; + break; + case 503: + http_err_code_idx = HTTP_ERR_503; + break; + case 502: + http_err_code_idx = HTTP_ERR_502; + break; + case 408: + http_err_code_idx = HTTP_ERR_408; + break; + case 405: + http_err_code_idx = HTTP_ERR_405; + break; + case 400: + http_err_code_idx = HTTP_ERR_400; + break; + case 200: + http_err_code_idx = HTTP_ERR_200; + break; + default: + http_err_code_idx = HTTP_ERR_500; + break; + } + http_reply_and_close(s, txn->status, http_error_message(s, http_err_code_idx)); + } req->analysers &= AN_FLT_END; req->analyse_exp = TICK_ETERNITY; -- 1.8.3.1