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.
This commit is contained in:
Jarno Huuskonen 2017-03-06 14:56:36 +02:00 committed by Willy Tarreau
parent 9e6906b9ec
commit 800d1761d0
2 changed files with 20 additions and 13 deletions

View 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

View 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;