mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 13:51:26 +02:00
[MEDIUM] added the 'block' keyword to the config language
The new 'block' keyword makes it possible to block a request based on ACL test results. Block accepts two optional arguments : 'if' <cond> and 'unless' <cond>. The request will be blocked with a 403 response if the condition is validated (if) or if it is not (unless). Do not rely on this one too much, as it's more of a proof of concept helping in developing other matches.
This commit is contained in:
parent
8797c06327
commit
5c8e3e09e9
@ -84,6 +84,7 @@ struct proxy {
|
|||||||
char *name; /* default backend name during config parse */
|
char *name; /* default backend name during config parse */
|
||||||
} defbe;
|
} defbe;
|
||||||
struct list acl; /* ACL declared on this proxy */
|
struct list acl; /* ACL declared on this proxy */
|
||||||
|
struct list block_cond; /* early blocking conditions (chained) */
|
||||||
struct server *srv; /* known servers */
|
struct server *srv; /* known servers */
|
||||||
int srv_act, srv_bck; /* # of running servers */
|
int srv_act, srv_bck; /* # of running servers */
|
||||||
int tot_wact, tot_wbck; /* total weights of active and backup servers */
|
int tot_wact, tot_wbck; /* total weights of active and backup servers */
|
||||||
|
@ -494,6 +494,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
|||||||
proxy = curproxy;
|
proxy = curproxy;
|
||||||
LIST_INIT(&curproxy->pendconns);
|
LIST_INIT(&curproxy->pendconns);
|
||||||
LIST_INIT(&curproxy->acl);
|
LIST_INIT(&curproxy->acl);
|
||||||
|
LIST_INIT(&curproxy->block_cond);
|
||||||
|
|
||||||
curproxy->id = strdup(args[1]);
|
curproxy->id = strdup(args[1]);
|
||||||
curproxy->cap = rc;
|
curproxy->cap = rc;
|
||||||
@ -912,6 +913,28 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
|||||||
}
|
}
|
||||||
curproxy->conn_retries = atol(args[1]);
|
curproxy->conn_retries = atol(args[1]);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
|
||||||
|
int pol = ACL_COND_NONE;
|
||||||
|
struct acl_cond *cond;
|
||||||
|
|
||||||
|
if (!strcmp(args[1], "if"))
|
||||||
|
pol = ACL_COND_IF;
|
||||||
|
else if (!strcmp(args[1], "unless"))
|
||||||
|
pol = ACL_COND_UNLESS;
|
||||||
|
|
||||||
|
if (pol == ACL_COND_NONE) {
|
||||||
|
Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
|
||||||
|
file, linenum, args[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cond = parse_acl_cond((const char **)args + 2, &curproxy->acl, pol)) == NULL) {
|
||||||
|
Alert("parsing [%s:%d] : error detected while parsing blocking condition.\n",
|
||||||
|
file, linenum);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LIST_ADDQ(&curproxy->block_cond, &cond->list);
|
||||||
|
}
|
||||||
else if (!strcmp(args[0], "stats")) {
|
else if (!strcmp(args[0], "stats")) {
|
||||||
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
|
if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1674,9 +1674,25 @@ int process_cli(struct session *t)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
struct acl_cond *cond;
|
||||||
struct proxy *rule_set = t->be;
|
struct proxy *rule_set = t->be;
|
||||||
cur_proxy = t->be;
|
cur_proxy = t->be;
|
||||||
|
|
||||||
|
/* first check whether we have some ACLs set to block this request */
|
||||||
|
list_for_each_entry(cond, &cur_proxy->block_cond, list) {
|
||||||
|
int ret = acl_exec_cond(cond, cur_proxy, t, txn);
|
||||||
|
if (cond->pol == ACL_COND_UNLESS)
|
||||||
|
ret = !ret;
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
txn->status = 403;
|
||||||
|
/* let's log the request time */
|
||||||
|
t->logs.t_request = tv_ms_elapsed(&t->logs.tv_accept, &now);
|
||||||
|
client_retnclose(t, error_message(t, HTTP_ERR_403));
|
||||||
|
goto return_prx_cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* try headers filters */
|
/* try headers filters */
|
||||||
if (rule_set->req_exp != NULL) {
|
if (rule_set->req_exp != NULL) {
|
||||||
if (apply_filters_to_request(t, req, rule_set->req_exp) < 0)
|
if (apply_filters_to_request(t, req, rule_set->req_exp) < 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user