[MEDIUM] tcp: accept the "track-counters" in "tcp-request content" rules

Doing so allows us to track counters from backends or depending on contents.
For instance, it now becomes possible to decide to track a connection based
on a Host header if enough time is granted to parse the HTTP request. It is
also possible to just track frontend counters in the frontend and unconditionally
track backend counters in the backend without having to write complex rules.

The first track-fe-counters rule executed is used to track counters for
the frontend, and the first track-be-counters rule executed is used to track
counters for the backend. Nothing prevents a frontend from setting a track-be
rule nor a backend from setting a track-fe rule. In fact these rules are
arbitrarily split between FE and BE with no dependencies.
This commit is contained in:
Willy Tarreau 2010-08-03 19:34:32 +02:00
parent f059a0f63a
commit d1f9652d90
2 changed files with 106 additions and 10 deletions

View File

@ -5023,6 +5023,43 @@ int check_config_validity()
}
}
/* find the target table for 'tcp-request' layer 6 rules */
list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
struct proxy *target;
if (trule->action != TCP_ACT_TRK_FE_CTR && trule->action != TCP_ACT_TRK_BE_CTR)
continue;
if (trule->act_prm.trk_ctr.table.n)
target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
else
target = curproxy;
if (!target) {
Alert("Proxy '%s': unable to find table '%s' referenced by track-counter.\n",
curproxy->id, trule->act_prm.trk_ctr.table.n);
cfgerr++;
}
else if (target->table.size == 0) {
Alert("Proxy '%s': table '%s' used but not configured.\n",
curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
cfgerr++;
}
else if (trule->act_prm.trk_ctr.type != target->table.type) {
Alert("Proxy '%s': type of track-counters pattern not usable with type of stick-table '%s'.\n",
curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
cfgerr++;
}
else {
free(trule->act_prm.trk_ctr.table.n);
trule->act_prm.trk_ctr.table.t = &target->table;
/* Note: if we decide to enhance the track-counters syntax, we may be able
* to pass a list of counters to track and allocate them right here using
* stktable_alloc_data_type().
*/
}
}
if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
!LIST_ISEMPTY(&curproxy->uri_auth->req_acl) &&
(curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {

View File

@ -623,6 +623,8 @@ void tcpv6_add_listener(struct listener *listener)
int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
{
struct tcp_rule *rule;
struct stksess *ts;
struct stktable *t;
int partial;
DPRINTF(stderr,"[%u] %s: session=%p b=%p, exp(r,w)=%u,%u bf=%08x bl=%d analysers=%02x\n",
@ -684,8 +686,36 @@ int tcp_inspect_request(struct session *s, struct buffer *req, int an_bit)
s->flags |= SN_FINST_R;
return 0;
}
else if (rule->action == TCP_ACT_TRK_FE_CTR) {
if (!s->fe_tracked_counters) {
/* only the first valid track-counters directive applies.
* Also, note that right now we can only track SRC so we
* don't check how to get the key, but later we may need
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
if (ts)
session_track_fe_counters(s, t, ts);
}
}
else if (rule->action == TCP_ACT_TRK_BE_CTR) {
if (!s->be_tracked_counters) {
/* only the first valid track-counters directive applies.
* Also, note that right now we can only track SRC so we
* don't check how to get the key, but later we may need
* to consider rule->act_prm->trk_ctr.type.
*/
t = rule->act_prm.trk_ctr.table.t;
ts = stktable_get_entry(t, tcpv4_src_to_stktable_key(s));
if (ts)
session_track_be_counters(s, t, ts);
}
}
else {
/* otherwise accept */
break;
break;
}
}
}
@ -819,19 +849,48 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
arg = 1;
if (!strcmp(args[1], "content")) {
arg++;
if (curpx == defpx) {
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
args[0], args[1]);
goto error;
}
if (!strcmp(args[2], "accept"))
if (!strcmp(args[2], "accept")) {
arg++;
rule->action = TCP_ACT_ACCEPT;
else if (!strcmp(args[2], "reject"))
}
else if (!strcmp(args[2], "reject")) {
arg++;
rule->action = TCP_ACT_REJECT;
}
else if (strcmp(args[2], "track-fe-counters") == 0) {
int ret;
arg++;
ret = parse_track_counters(args, &arg, section_type, curpx,
&rule->act_prm.trk_ctr, defpx, err, errlen);
if (ret < 0) /* nb: warnings are not handled yet */
goto error;
rule->action = TCP_ACT_TRK_FE_CTR;
}
else if (strcmp(args[2], "track-be-counters") == 0) {
int ret;
arg++;
ret = parse_track_counters(args, &arg, section_type, curpx,
&rule->act_prm.trk_ctr, defpx, err, errlen);
if (ret < 0) /* nb: warnings are not handled yet */
goto error;
rule->action = TCP_ACT_TRK_BE_CTR;
}
else {
retlen = snprintf(err, errlen,
"'%s %s' expects 'accept' or 'reject', in %s '%s' (was '%s')",
"'%s %s' expects 'accept', 'reject', 'track-fe-counters' or 'track-be-counters' in %s '%s' (was '%s')",
args[0], args[1], proxy_type_str(curpx), curpx->id, args[2]);
goto error;
}
@ -839,18 +898,18 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
pol = ACL_COND_NONE;
rule->cond = NULL;
if (strcmp(args[3], "if") == 0 || strcmp(args[3], "unless") == 0) {
if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+3)) == NULL) {
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
if ((rule->cond = build_acl_cond(NULL, 0, curpx, (const char **)args+arg)) == NULL) {
retlen = snprintf(err, errlen,
"error detected in %s '%s' while parsing '%s' condition",
proxy_type_str(curpx), curpx->id, args[3]);
proxy_type_str(curpx), curpx->id, args[arg]);
goto error;
}
}
else if (*args[3]) {
else if (*args[arg]) {
retlen = snprintf(err, errlen,
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[3]);
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg]);
goto error;
}
@ -907,7 +966,7 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
}
else {
retlen = snprintf(err, errlen,
"'%s' expects 'inspect-delay', 'content', 'accept', 'reject', 'track-fe-counters' or 'track-be-counters' in %s '%s' (was '%s')",
"'%s' expects 'inspect-delay', 'content', 'accept', 'reject', 'track-fe-counters' or 'track-be-counters' in %s '%s' (was '%s')",
args[0], proxy_type_str(curpx), curpx->id, args[1]);
goto error;
}