Skip to content

Commit

Permalink
MINOR: quic: implement reject quic-initial action
Browse files Browse the repository at this point in the history
Implement 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 support CONNECTION_CLOSE emission on reject, 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.
  • Loading branch information
a-denoyelle committed Jul 25, 2024
1 parent 55758be commit 466db34
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 13 deletions.
9 changes: 7 additions & 2 deletions doc/configuration.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11009,6 +11009,7 @@ quic-initial <action> [ { if | unless } <condition> ]
minimal list of actions is supported :
- accept
- dgram-drop
- reject


rate-limit sessions <rate>
Expand Down Expand Up @@ -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 - -
Expand Down Expand Up @@ -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
Expand All @@ -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 and the client receives a CONNECTION_REFUSED
error code prior to the SSL handshake execution.


replace-header <name> <match-regex> <replace-fmt>
Usable in: QUIC Ini| TCP RqCon| RqSes| RqCnt| RsCnt| HTTP Req| Res| Aft
Expand Down
4 changes: 4 additions & 0 deletions include/haproxy/quic_sock-t.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down
18 changes: 18 additions & 0 deletions src/quic_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 */ },
}
};
Expand Down
27 changes: 16 additions & 11 deletions src/quic_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 466db34

Please sign in to comment.