mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-05-16 22:58:02 +00:00
MINOR: quic: support ACL for quic-initial rules
Add ACL condition support for quic-initial rules. This requires the extension of quic_parse_quic_initial() to parse an extra if/unless block. Only layer4 client samples are allowed to be used with quic-initial rules. However, due to the early execution of quic-initial rules prior to any connection instantiation, some samples are non supported. To be able to use the 4 described samples, a dummy session is instantiated before quic-initial rules execution. Its src and dst fields are set from the received datagram values.
This commit is contained in:
parent
cafe596608
commit
1259700763
@ -10981,7 +10981,7 @@ persist rdp-cookie(<name>)
|
||||
See also : "balance rdp-cookie", "tcp-request" and the "req.rdp_cookie" ACL.
|
||||
|
||||
|
||||
quic-initial <action>
|
||||
quic-initial <action> [ { if | unless } <condition> ]
|
||||
Perform an action on an incoming QUIC Initial packet. Contrary to
|
||||
"tcp-request connection", this is executed prior to any connection element
|
||||
instantiation and starting and completion of the SSL handshake, which is more
|
||||
@ -10996,6 +10996,15 @@ quic-initial <action>
|
||||
<action> defines the action to perform if the condition applies. See
|
||||
below.
|
||||
|
||||
<condition> is a standard layer4-only ACL-based condition (see section 7).
|
||||
However, QUIC initial rules are executed too early even for
|
||||
some layer4 sample fetch methods despite no configuration
|
||||
warning and may result in unspecified runtime behavior,
|
||||
although they will not crash. Consider that only internal
|
||||
samples and layer4 "src*" and "dst*" are considered as
|
||||
supported for now.
|
||||
|
||||
|
||||
This action is executed early during QUIC packet parsing. As such, only a
|
||||
minimal list of actions is supported :
|
||||
- accept
|
||||
|
@ -1,13 +1,17 @@
|
||||
#ifndef _HAPROXY_QUIC_RULES_H
|
||||
#define _HAPROXY_QUIC_RULES_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <haproxy/action-t.h>
|
||||
|
||||
struct listener;
|
||||
|
||||
extern struct action_kw_list quic_init_actions_list;
|
||||
|
||||
int quic_init_exec_rules(struct listener *li);
|
||||
int quic_init_exec_rules(struct listener *li,
|
||||
struct sockaddr_storage *saddr,
|
||||
struct sockaddr_storage *daddr);
|
||||
|
||||
struct action_kw *action_quic_init_custom(const char *kw);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <string.h>
|
||||
#include <netinet/udp.h>
|
||||
|
||||
#include <haproxy/acl.h>
|
||||
#include <haproxy/action.h>
|
||||
#include <haproxy/api.h>
|
||||
#include <haproxy/cfgparse.h>
|
||||
@ -345,10 +346,16 @@ static int quic_parse_quic_initial(char **args, int section_type, struct proxy *
|
||||
const struct proxy *defpx, const char *file, int line,
|
||||
char **err)
|
||||
{
|
||||
const struct acl *acl;
|
||||
struct act_rule *rule;
|
||||
struct action_kw *kw;
|
||||
const char *acl_kw;
|
||||
unsigned int where;
|
||||
int warn = 0;
|
||||
int arg = 1;
|
||||
|
||||
where = SMP_VAL_FE_CON_ACC;
|
||||
|
||||
if (curpx == defpx && strlen(defpx->id) == 0) {
|
||||
memprintf(err, "%s is not allowed in anonymous 'defaults' sections",
|
||||
args[0]);
|
||||
@ -397,12 +404,54 @@ static int quic_parse_quic_initial(char **args, int section_type, struct proxy *
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (strcmp(args[arg], "if") == 0 || strcmp(args[arg], "unless") == 0) {
|
||||
if ((rule->cond = build_acl_cond(file, line, &curpx->acl, curpx, (const char **)args+arg, err)) == NULL) {
|
||||
memprintf(err,
|
||||
"'%s %s %s' : error detected in %s '%s' while parsing '%s' condition : %s",
|
||||
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg], *err);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else if (*args[arg]) {
|
||||
memprintf(err,
|
||||
"'%s %s %s' only accepts 'if' or 'unless', in %s '%s' (got '%s')",
|
||||
args[0], args[1], args[2], proxy_type_str(curpx), curpx->id, args[arg]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
acl = rule->cond ? acl_cond_conflicts(rule->cond, where) : NULL;
|
||||
if (acl) {
|
||||
if (acl->name && *acl->name)
|
||||
memprintf(err,
|
||||
"acl '%s' will never match in '%s' because it only involves keywords that are incompatible with '%s'",
|
||||
acl->name, args[0], sample_ckp_names(where));
|
||||
else
|
||||
memprintf(err,
|
||||
"anonymous acl will never match in '%s' because it uses keyword '%s' which is incompatible with '%s'",
|
||||
args[0],
|
||||
LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw,
|
||||
sample_ckp_names(where));
|
||||
|
||||
warn++;
|
||||
}
|
||||
else if (rule->cond && acl_cond_kw_conflicts(rule->cond, where, &acl, &acl_kw)) {
|
||||
if (acl->name && *acl->name)
|
||||
memprintf(err,
|
||||
"acl '%s' involves keyword '%s' which is incompatible with '%s'",
|
||||
acl->name, acl_kw, sample_ckp_names(where));
|
||||
else
|
||||
memprintf(err,
|
||||
"anonymous acl involves keyword '%s' which is incompatible with '%s'",
|
||||
acl_kw, sample_ckp_names(where));
|
||||
warn++;
|
||||
}
|
||||
|
||||
/* the following function directly emits the warning */
|
||||
warnif_misplaced_quic_init(curpx, file, line, args[0]);
|
||||
|
||||
LIST_APPEND(&curpx->quic_init_rules, &rule->list);
|
||||
|
||||
return 0;
|
||||
return warn;
|
||||
|
||||
err:
|
||||
free_act_rule(rule);
|
||||
|
@ -6,10 +6,14 @@
|
||||
#include <haproxy/listener.h>
|
||||
#include <haproxy/proxy-t.h>
|
||||
#include <haproxy/sample-t.h>
|
||||
#include <haproxy/session-t.h>
|
||||
|
||||
/* Execute registered quic-initial rules on proxy owning <li> listener. */
|
||||
int quic_init_exec_rules(struct listener *li)
|
||||
int quic_init_exec_rules(struct listener *li,
|
||||
struct sockaddr_storage *saddr,
|
||||
struct sockaddr_storage *daddr)
|
||||
{
|
||||
static THREAD_LOCAL struct session rule_sess;
|
||||
struct act_rule *rule;
|
||||
enum acl_test_res ret;
|
||||
struct proxy *px;
|
||||
@ -17,11 +21,19 @@ int quic_init_exec_rules(struct listener *li)
|
||||
|
||||
px = li->bind_conf->frontend;
|
||||
|
||||
/* Initialize session elements specific to the current datagram. All
|
||||
* others members are set to 0 thanks to static storage class.
|
||||
*/
|
||||
rule_sess.fe = px;
|
||||
rule_sess.listener = li;
|
||||
rule_sess.src = saddr;
|
||||
rule_sess.dst = daddr;
|
||||
|
||||
list_for_each_entry(rule, &px->quic_init_rules, list) {
|
||||
ret = ACL_TEST_PASS;
|
||||
|
||||
if (rule->cond) {
|
||||
ret = acl_exec_cond(rule->cond, px, NULL, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
||||
ret = acl_exec_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
|
||||
ret = acl_pass(ret);
|
||||
if (rule->cond->pol == ACL_COND_UNLESS)
|
||||
ret = !ret;
|
||||
@ -29,7 +41,7 @@ int quic_init_exec_rules(struct listener *li)
|
||||
|
||||
if (ret) {
|
||||
if (rule->action_ptr) {
|
||||
switch (rule->action_ptr(rule, px, NULL, NULL, 0)) {
|
||||
switch (rule->action_ptr(rule, px, &rule_sess, NULL, 0)) {
|
||||
case ACT_RET_CONT:
|
||||
break;
|
||||
case ACT_RET_DONE:
|
||||
|
@ -1607,7 +1607,7 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!quic_init_exec_rules(l)) {
|
||||
if (!quic_init_exec_rules(l, &dgram->saddr, &dgram->daddr)) {
|
||||
TRACE_USER("drop datagram on quic-initial rules", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
goto err;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user