mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-11 03:31:36 +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 on - - X X
|
||||||
stick store-request - - X X
|
stick store-request - - X X
|
||||||
stick-table - - X X
|
stick-table - - X X
|
||||||
|
tcp-request accept - X X -
|
||||||
tcp-request content accept - X X -
|
tcp-request content accept - X X -
|
||||||
tcp-request content reject - X X -
|
tcp-request content reject - X X -
|
||||||
tcp-request inspect-delay - X X -
|
tcp-request inspect-delay - X X -
|
||||||
|
tcp-request reject - X X -
|
||||||
timeout check X - X X
|
timeout check X - X X
|
||||||
timeout client X X X -
|
timeout client X X X -
|
||||||
timeout clitimeout (deprecated) 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.
|
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>]
|
tcp-request content accept [{if | unless} <condition>]
|
||||||
Accept a connection if/unless a content inspection condition is matched
|
Accept a connection if/unless a content inspection condition is matched
|
||||||
May be used in sections : defaults | frontend | listen | backend
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
@ -5164,6 +5198,45 @@ tcp-request inspect-delay <timeout>
|
|||||||
"timeout client".
|
"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>
|
timeout check <timeout>
|
||||||
Set additional check timeout, but only after a connection has been already
|
Set additional check timeout, but only after a connection has been already
|
||||||
established.
|
established.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* AF_INET/AF_INET6 SOCK_STREAM protocol layer (tcp)
|
* 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
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* 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;
|
const char *ptr = NULL;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
int retlen;
|
int retlen;
|
||||||
|
int action;
|
||||||
|
int warn = 0;
|
||||||
|
int pol = ACL_COND_NONE;
|
||||||
|
struct acl_cond *cond;
|
||||||
|
struct tcp_rule *rule;
|
||||||
|
|
||||||
if (!*args[1]) {
|
if (!*args[1]) {
|
||||||
snprintf(err, errlen, "missing argument for '%s' in %s '%s'",
|
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")) {
|
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) {
|
if (curpx == defpx) {
|
||||||
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
|
snprintf(err, errlen, "%s %s is not allowed in 'defaults' sections",
|
||||||
args[0], args[1]);
|
args[0], args[1]);
|
||||||
@ -819,9 +818,69 @@ static int tcp_parse_tcp_req(char **args, int section_type, struct proxy *curpx,
|
|||||||
return warn;
|
return warn;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(err, errlen, "unknown argument '%s' after '%s' in %s '%s'",
|
/* OK so we're in front of plain L4 rules */
|
||||||
args[1], args[0], proxy_type_str(proxy), curpx->id);
|
if (!strcmp(args[1], "accept"))
|
||||||
return -1;
|
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