mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-01 22:48:25 +00:00
[MEDIUM] config: parse tcp layer4 rules (tcp-request accept/reject)
These rules currently only support the "accept" and "reject" actions. They will apply on pure layer 4 and will not support any content.
This commit is contained in:
parent
ab786194f0
commit
1a68794418
@ -907,9 +907,11 @@ stick match - - X X
|
||||
stick on - - X X
|
||||
stick store-request - - X X
|
||||
stick-table - - X X
|
||||
tcp-request accept - X X -
|
||||
tcp-request content accept - X X -
|
||||
tcp-request content reject - X X -
|
||||
tcp-request inspect-delay - X X -
|
||||
tcp-request reject - X X -
|
||||
timeout check X - X X
|
||||
timeout client X X X -
|
||||
timeout clitimeout (deprecated) X X X -
|
||||
@ -5061,6 +5063,38 @@ stick-table type {ip | integer | string [len <length>] } size <size>
|
||||
about time format.
|
||||
|
||||
|
||||
tcp-request accept [{if | unless} <condition>]
|
||||
Accept an incoming connection if/unless a layer 4 condition is matched
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
no | yes | yes | no
|
||||
|
||||
Immediately after acceptance of a new incoming connection, it is possible to
|
||||
evaluate some conditions to decide whether this connection must be accepted
|
||||
or dropped. Those conditions cannot make use of any data contents because the
|
||||
connection has not been read from yet, and the buffers are not yet allocated.
|
||||
This can be used to selectively and very quickly accept or drop connections
|
||||
from various sources with a very low overhead. If some contents need to be
|
||||
inspected in order to take the decision, the "tcp-request content" statements
|
||||
must be used instead.
|
||||
|
||||
This statement accepts the connection if the condition is true (when used
|
||||
with "if") or false (when used with "unless"). It is important to understand
|
||||
that "accept" and "reject" rules are evaluated in their exact declaration
|
||||
order, so that it is possible to build complex rules from them. There is no
|
||||
specific limit to the number of rules which may be inserted.
|
||||
|
||||
Note that the "if/unless" condition is optional. If no condition is set on
|
||||
the action, it is simply performed unconditionally.
|
||||
|
||||
If no "tcp-request" rules are matched, the default action is to accept the
|
||||
connection, which implies that the "tcp-request accept" statement will only
|
||||
make sense when combined with another "tcp-request reject" statement.
|
||||
|
||||
See section 7 about ACL usage.
|
||||
|
||||
See also : "tcp-request reject" and "tcp-request content"
|
||||
|
||||
|
||||
tcp-request content accept [{if | unless} <condition>]
|
||||
Accept a connection if/unless a content inspection condition is matched
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
@ -5164,6 +5198,45 @@ tcp-request inspect-delay <timeout>
|
||||
"timeout client".
|
||||
|
||||
|
||||
tcp-request reject [{if | unless} <condition>]
|
||||
Reject an incoming connection if/unless a layer 4 condition is matched
|
||||
May be used in sections : defaults | frontend | listen | backend
|
||||
no | yes | yes | no
|
||||
|
||||
Immediately after acceptance of a new incoming connection, it is possible to
|
||||
evaluate some conditions to decide whether this connection must be accepted
|
||||
or dropped. Those conditions cannot make use of any data contents because the
|
||||
connection has not been read from yet, and the buffers are not yet allocated.
|
||||
This can be used to selectively and very quickly accept or drop connections
|
||||
from various sources with a very low overhead. If some contents need to be
|
||||
inspected in order to take the decision, the "tcp-request content" statements
|
||||
must be used instead.
|
||||
|
||||
This statement rejects the connection if the condition is true (when used
|
||||
with "if") or false (when used with "unless"). It is important to understand
|
||||
that "accept" and "reject" rules are evaluated in their exact declaration
|
||||
order, so that it is possible to build complex rules from them. There is no
|
||||
specific limit to the number of rules which may be inserted.
|
||||
|
||||
Note that the "if/unless" condition is optional. If no condition is set on
|
||||
the action, it is simply performed unconditionally.
|
||||
|
||||
If no "tcp-request" rules are matched, the default action is to accept the
|
||||
connection, which implies that the "tcp-request accept" statement will only
|
||||
make sense when combined with another "tcp-request reject" statement.
|
||||
|
||||
Rejected connections are accounted in stats but are not logged. The reason is
|
||||
that these rules should only be used to filter extremely high connection
|
||||
rates such as the ones encountered during a massive DDoS attack. Under these
|
||||
conditions, the simple action of logging each event would make the system
|
||||
collapse and would considerably lower the filtering capacity. If logging is
|
||||
absolutely desired, then "tcp-request content" rules should be used instead.
|
||||
|
||||
See section 7 about ACL usage.
|
||||
|
||||
See also : "tcp-request accept" and "tcp-request content"
|
||||
|
||||
|
||||
timeout check <timeout>
|
||||
Set additional check timeout, but only after a connection has been already
|
||||
established.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* AF_INET/AF_INET6 SOCK_STREAM protocol layer (tcp)
|
||||
*
|
||||
* Copyright 2000-2008 Willy Tarreau <w@1wt.eu>
|
||||
* Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -717,6 +717,11 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
||||
const char *ptr = NULL;
|
||||
unsigned int val;
|
||||
int retlen;
|
||||
int action;
|
||||
int warn = 0;
|
||||
int pol = ACL_COND_NONE;
|
||||
struct acl_cond *cond;
|
||||
struct tcp_rule *rule;
|
||||
|
||||
if (!*args[1]) {
|
||||
snprintf(err, errlen, "missing argument for '%s' in %s '%s'",
|
||||
@ -758,12 +763,6 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
||||
}
|
||||
|
||||
if (!strcmp(args[1], "content")) {
|
||||
int action;
|
||||
int warn = 0;
|
||||
int pol = ACL_COND_NONE;
|
||||
struct acl_cond *cond;
|
||||
struct tcp_rule *rule;
|
||||
|
||||
if (curpx == defpx) {
|
||||
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
|
||||
args[0], args[1]);
|
||||
@ -819,9 +818,69 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
||||
return warn;
|
||||
}
|
||||
|
||||
snprintf(err, errlen, "unknown argument '%s' after '%s' in %s '%s'",
|
||||
args[1], args[0], proxy_type_str(proxy), curpx->id);
|
||||
return -1;
|
||||
/* OK so we're in front of plain L4 rules */
|
||||
if (!strcmp(args[1], "accept"))
|
||||
action = TCP_ACT_ACCEPT;
|
||||
else if (!strcmp(args[1], "reject"))
|
||||
action = TCP_ACT_REJECT;
|
||||
else {
|
||||
retlen = snprintf(err, errlen,
|
||||
"'%s' expects 'inspect-delay', 'content', 'accept' or 'reject', in %s '%s' (was '%s')",
|
||||
args[0], proxy_type_str(curpx), curpx->id, args[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (curpx == defpx) {
|
||||
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
|
||||
args[0], args[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pol = ACL_COND_NONE;
|
||||
cond = NULL;
|
||||
|
||||
if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
|
||||
if ((cond = build_acl_cond(NULL, 0, curpx, (const char **)args+2)) == NULL) {
|
||||
retlen = snprintf(err, errlen,
|
||||
"error detected in %s '%s' while parsing '%s' condition",
|
||||
proxy_type_str(curpx), curpx->id, args[2]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (*args[2]) {
|
||||
retlen = snprintf(err, errlen,
|
||||
"'%s %s' only accepts 'if' or 'unless', in %s '%s' (was '%s')",
|
||||
args[0], args[1], proxy_type_str(curpx), curpx->id, args[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cond && (cond->requires & (ACL_USE_RTR_ANY|ACL_USE_L6_ANY|ACL_USE_L7_ANY))) {
|
||||
struct acl *acl;
|
||||
const char *name;
|
||||
|
||||
acl = cond_find_require(cond, ACL_USE_RTR_ANY|ACL_USE_L6_ANY|ACL_USE_L7_ANY);
|
||||
name = acl ? acl->name : "(unknown)";
|
||||
|
||||
if (acl->requires & (ACL_USE_L6_ANY|ACL_USE_L7_ANY)) {
|
||||
retlen = snprintf(err, errlen,
|
||||
"'%s %s' may not reference acl '%s' which makes use of payload in %s '%s'. Please use '%s content' for this.",
|
||||
args[0], args[1], name, proxy_type_str(curpx), curpx->id, args[0]);
|
||||
return -1;
|
||||
}
|
||||
if (acl->requires & ACL_USE_RTR_ANY)
|
||||
retlen = snprintf(err, errlen,
|
||||
"acl '%s' involves some response-only criteria which will be ignored.",
|
||||
name);
|
||||
|
||||
warn++;
|
||||
}
|
||||
|
||||
rule = (struct tcp_rule *)calloc(1, sizeof(*rule));
|
||||
rule->cond = cond;
|
||||
rule->action = action;
|
||||
LIST_INIT(&rule->list);
|
||||
LIST_ADDQ(&curpx->tcp_req.l4_rules, &rule->list);
|
||||
return warn;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user