MEDIUM: http: emulate "block" rules using "http-request" rules

The "block" rules are redundant with http-request rules because they
are performed immediately before and do exactly the same thing as
"http-request deny". Moreover, this duplication has led to a few
minor stats accounting issues fixed lately.

Instead of keeping the two rule sets, we now build a list of "block"
rules that we compile as "http-request block" and that we later insert
at the beginning of the "http-request" rules.

The only user-visible change is that in case of a parsing error, the
config parser will now report "http-request block rule" instead of
"blocking condition".
This commit is contained in:
Willy Tarreau 2014-04-28 22:06:57 +02:00
parent 353bc9f43f
commit b3dc39dfe1

View File

@ -2874,28 +2874,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name); curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
} }
else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */ else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
struct http_req_rule *rule;
if (curproxy == &defproxy) { if (curproxy == &defproxy) {
Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]); Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL; err_code |= ERR_ALERT | ERR_FATAL;
goto out; goto out;
} }
if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) { /* emulate "block" using "http-request block". Since these rules are supposed to
Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n", * be processed before all http-request rules, we put them into their own list
file, linenum, args[0]); * and will insert them at the end.
err_code |= ERR_ALERT | ERR_FATAL; */
rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
if (!rule) {
err_code |= ERR_ALERT | ERR_ABORT;
goto out; goto out;
} }
err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) { err_code |= warnif_cond_conflicts(rule->cond,
Alert("parsing [%s:%d] : error detected while parsing blocking condition : %s.\n", (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
file, linenum, errmsg); file, linenum);
err_code |= ERR_ALERT | ERR_FATAL; LIST_ADDQ(&curproxy->block_rules, &rule->list);
goto out;
}
LIST_ADDQ(&curproxy->block_rules, &cond->list);
warnif_misplaced_block(curproxy, file, linenum, args[0]);
} }
else if (!strcmp(args[0], "redirect")) { else if (!strcmp(args[0], "redirect")) {
struct redirect_rule *rule; struct redirect_rule *rule;
@ -6189,6 +6189,16 @@ int check_config_validity()
} }
} }
/* move any "block" rules at the beginning of the http-request rules */
if (!LIST_ISEMPTY(&curproxy->block_rules)) {
/* insert block_rules into http_req_rules at the beginning */
curproxy->block_rules.p->n = curproxy->http_req_rules.n;
curproxy->http_req_rules.n->p = curproxy->block_rules.p;
curproxy->block_rules.n->p = &curproxy->http_req_rules;
curproxy->http_req_rules.n = curproxy->block_rules.n;
LIST_INIT(&curproxy->block_rules);
}
if (curproxy->table.peers.name) { if (curproxy->table.peers.name) {
struct peers *curpeers = peers; struct peers *curpeers = peers;