From: Amaury Denoyelle Date: Mon, 22 Jul 2024 11:29:04 +0000 (+0200) Subject: MINOR: quic: implement send-retry quic-initial rules X-Git-Tag: v3.1-dev5~77 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08515af9dfd99bc0c1c7989c95ea03049ff67062;p=thirdparty%2Fhaproxy.git MINOR: quic: implement send-retry quic-initial rules Define a new quic-initial "send-retry" rule. This allows to force the emission of a Retry packet on an initial without token instead of instantiating a new QUIC connection. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 022712df25..b740818639 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -11010,6 +11010,7 @@ quic-initial [ { if | unless } ] - accept - dgram-drop - reject + - send-retry rate-limit sessions @@ -14389,6 +14390,7 @@ sc-inc-gpc0 - X X X X X X sc-inc-gpc1 - X X X X X X X sc-set-gpt - X X X X X X X sc-set-gpt0 - X X X X X X X +send-retry X - - - - - - - send-spoe-group - - - X X X X - set-bandwidth-limit - - - X X X X - set-bc-mark - - - X - X - - @@ -15263,6 +15265,16 @@ sc-set-gpt0() { | } See also the "sc-set-gpt" action. +send-retry + Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft + X | - | - | - | - | - | - | - + + This action forces the emission of a Retry packet in response to a client + Initial packet without token. This is useful to ensure client address is + validated prior to instantiating any connection elements and starting the + handshake. + + send-spoe-group Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft - | - | - | X | X | X | X | - diff --git a/include/haproxy/quic_sock-t.h b/include/haproxy/quic_sock-t.h index ed396b1805..69f52b45fa 100644 --- a/include/haproxy/quic_sock-t.h +++ b/include/haproxy/quic_sock-t.h @@ -27,6 +27,7 @@ struct quic_receiver_buf { }; #define QUIC_DGRAM_FL_REJECT 0x00000001 +#define QUIC_DGRAM_FL_SEND_RETRY 0x00000002 /* QUIC datagram */ struct quic_dgram { diff --git a/src/quic_rules.c b/src/quic_rules.c index 103833cf85..b924209530 100644 --- a/src/quic_rules.c +++ b/src/quic_rules.c @@ -100,6 +100,14 @@ static enum act_return quic_init_action_reject(struct act_rule *rule, struct pro return ACT_RET_DONE; } +static enum act_return quic_init_action_send_retry(struct act_rule *rule, struct proxy *px, + struct session *sess, struct stream *s, int flags) +{ + struct quic_dgram *dgram = __objt_dgram(sess->origin); + dgram->flags |= QUIC_DGRAM_FL_SEND_RETRY; + return ACT_RET_DONE; +} + static enum act_parse_ret parse_reject(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err) @@ -109,6 +117,15 @@ static enum act_parse_ret parse_reject(const char **args, int *orig_arg, return ACT_RET_PRS_OK; } +static enum act_parse_ret parse_send_retry(const char **args, int *orig_arg, + struct proxy *px, + struct act_rule *rule, char **err) +{ + rule->action = ACT_CUSTOM; + rule->action_ptr = quic_init_action_send_retry; + return ACT_RET_PRS_OK; +} + /* List head of all known action keywords for "quic-initial" */ struct action_kw_list quic_init_actions_list = { .list = LIST_HEAD_INIT(quic_init_actions_list.list) @@ -129,6 +146,7 @@ static struct action_kw_list quic_init_actions = { ILH, { { "accept", parse_accept, 0 }, { "dgram-drop", parse_dgram_drop, 0 }, { "reject", parse_reject, 0 }, + { "send-retry", parse_send_retry, 0 }, { /* END */ }, } }; diff --git a/src/quic_rx.c b/src/quic_rx.c index 3f77078c03..a2254e5e51 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -1615,7 +1615,8 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt, /* No need to emit Retry if connection is refused. */ if (!pkt->token_len && !(dgram->flags & QUIC_DGRAM_FL_REJECT)) { if ((l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) || - HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold) { + HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold || + (dgram->flags & QUIC_DGRAM_FL_SEND_RETRY)) { TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);