]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement send-retry quic-initial rules
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 22 Jul 2024 11:29:04 +0000 (13:29 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 25 Jul 2024 13:39:39 +0000 (15:39 +0200)
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.

doc/configuration.txt
include/haproxy/quic_sock-t.h
src/quic_rules.c
src/quic_rx.c

index 022712df251ef5593921bdc671b901e3243b3fd8..b7408186396e825676f3e66356c0e40ad5f92848 100644 (file)
@@ -11010,6 +11010,7 @@ quic-initial <action> [ { if | unless } <condition> ]
     - accept
     - dgram-drop
     - reject
+    - send-retry
 
 
 rate-limit sessions <rate>
@@ -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(<sc-id>) { <int> | <expr> }
   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 <engine-name> <group-name>
   Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
                     - |          -  |   -  |   X  |   X  |          X |  X |  -
index ed396b18057f208ff1eb36a239029bc9b51f4783..69f52b45faf02f8806902342c23216dbd9d26196 100644 (file)
@@ -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 {
index 103833cf859cd1bd1e703e1ab259ff87f503d03f..b9242095309c6b86bf93b37922a30bd30bdca7ab 100644 (file)
@@ -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 */ },
        }
 };
index 3f77078c03a49da872fe812eb3bf4abfb5100c5b..a2254e5e5117ea5fc5ad0ba966d316dd60f4ea93 100644 (file)
@@ -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);