]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement reject quic-initial action
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 19 Jul 2024 15:39:04 +0000 (17:39 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 25 Jul 2024 13:39:39 +0000 (15:39 +0200)
Define a new quic-initial action named "reject". Contrary to dgram-drop,
the client is notified of the rejection by a CONNECTION_CLOSE with
CONNECTION_REFUSED error code.

To be able to emit the necessary CONNECTION_CLOSE frame, quic_conn is
instantiated, contrary to dgram-drop action. quic_set_connection_close()
is called immediatly after qc_new_conn() which prevents the handshake
startup.

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

index 0af6bb04fdf6ce2531dfbdf5e0472fc8f638645e..022712df251ef5593921bdc671b901e3243b3fd8 100644 (file)
@@ -11009,6 +11009,7 @@ quic-initial <action> [ { if | unless } <condition> ]
   minimal list of actions is supported :
     - accept
     - dgram-drop
+    - reject
 
 
 rate-limit sessions <rate>
@@ -14374,7 +14375,7 @@ expect-netscaler-cip           -           X     -     -     -            -   -
 expect-proxy layer4            -           X     -     -     -            -   -   -
 normalize-uri                  -           -     -     -     -            X   -   -
 redirect                       -           -     -     -     -            X   X   -
-reject                         -           X     X     X     X            X   -   -
+reject                         X           X     X     X     X            X   -   -
 replace-header                 -           -     -     -     -            X   X   X
 replace-path                   -           -     -     -     -            X   -   -
 replace-pathq                  -           -     -     -     -            X   -   -
@@ -14932,7 +14933,7 @@ redirect <rule>
 
 reject
   Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
-                    - |          X  |   X  |   X  |   X  |          X |  - |  -
+                    X |          X  |   X  |   X  |   X  |          X |  - |  -
 
   This stops the evaluation of the rules and immediately closes the connection
   without sending any response. For HTTP rules, it acts similarly to the
@@ -14955,6 +14956,10 @@ reject
   information from leaking, typically after inspecting contents in conjunction
   with the "wait-for-body" action.
 
+  This action can also be used in "quic-initial" rules. The newly opened QUIC
+  connection is immediately closed without any SSL handshake processing and the
+  client is notified via a CONNECTION_REFUSED error code.
+
 
 replace-header <name> <match-regex> <replace-fmt>
   Usable in:  QUIC Ini|    TCP RqCon| RqSes| RqCnt| RsCnt|    HTTP Req| Res| Aft
index 631cd3e1064d2dbf23c932a8dc48601504b43293..ed396b18057f208ff1eb36a239029bc9b51f4783 100644 (file)
@@ -26,6 +26,8 @@ struct quic_receiver_buf {
        struct mt_list rxbuf_el; /* list element into receiver.rxbuf_list. */
 };
 
+#define QUIC_DGRAM_FL_REJECT                   0x00000001
+
 /* QUIC datagram */
 struct quic_dgram {
        enum obj_type obj_type;
@@ -40,6 +42,8 @@ struct quic_dgram {
 
        struct list recv_list; /* element pointing to quic_receiver_buf <dgram_list>. */
        struct mt_list handler_list; /* element pointing to quic_dghdlr <dgrams>. */
+
+       int flags; /* QUIC_DGRAM_FL_* values */
 };
 
 /* QUIC datagram handler */
index 97984243308fc69e1e09597378619e7d75453ffd..103833cf859cd1bd1e703e1ab259ff87f503d03f 100644 (file)
@@ -92,6 +92,23 @@ static enum act_parse_ret parse_dgram_drop(const char **args, int *orig_arg,
        return ACT_RET_PRS_OK;
 }
 
+static enum act_return quic_init_action_reject(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_REJECT;
+       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)
+{
+       rule->action     = ACT_CUSTOM;
+       rule->action_ptr = quic_init_action_reject;
+       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)
@@ -111,6 +128,7 @@ struct action_kw *action_quic_init_custom(const char *kw)
 static struct action_kw_list quic_init_actions = { ILH, {
                { "accept",           parse_accept,            0 },
                { "dgram-drop",       parse_dgram_drop,        0 },
+               { "reject",           parse_reject,            0 },
                { /* END */ },
        }
 };
index fc1a4acd987ade7c393e6cf0ff7bdd7ed6ea1521..3f77078c03a49da872fe812eb3bf4abfb5100c5b 100644 (file)
@@ -1612,20 +1612,22 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
                                goto err;
                        }
 
-                       if (!pkt->token_len &&
-                           ((l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) ||
-                            HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold)) {
+                       /* 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) {
+
+                                       TRACE_PROTO("Initial without token, sending retry",
+                                                   QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+                                       if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
+                                               TRACE_ERROR("Error during Retry generation",
+                                                           QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+                                               goto out;
+                                       }
 
-                               TRACE_PROTO("Initial without token, sending retry",
-                                           QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
-                               if (send_retry(l->rx.fd, &dgram->saddr, pkt, pkt->version)) {
-                                       TRACE_ERROR("Error during Retry generation",
-                                                   QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
+                                       HA_ATOMIC_INC(&prx_counters->retry_sent);
                                        goto out;
                                }
-
-                               HA_ATOMIC_INC(&prx_counters->retry_sent);
-                               goto out;
                        }
 
                        /* RFC 9000 7.2. Negotiating Connection IDs:
@@ -1679,6 +1681,9 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
                                eb64_insert(qc->cids, &conn_id->seq_num);
                                /* Initialize the next CID sequence number to be used for this connection. */
                                qc->next_cid_seq_num = 1;
+
+                               if (dgram->flags & QUIC_DGRAM_FL_REJECT)
+                                       quic_set_connection_close(qc, quic_err_transport(QC_ERR_CONNECTION_REFUSED));
                        }
 
                        if (*new_tid != -1)