]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Anti-amplification implementation
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 10 Nov 2021 16:30:15 +0000 (17:30 +0100)
committerFrédéric Lécaille <flecaille@haproxy.com>
Fri, 19 Nov 2021 13:37:35 +0000 (14:37 +0100)
A QUIC server MUST not send more than three times as many bytes as received
by clients before its address validation.

include/haproxy/xprt_quic-t.h
src/xprt_quic.c

index be3e8d087cadd21f27bc2d4f0430efe7e2ef59ba..86629456c0a5b113a9f8d912844669703e0fb649 100644 (file)
@@ -606,6 +606,8 @@ struct rxbuf {
 /* Flag the packet number space as requiring an ACK frame to be sent. */
 #define QUIC_FL_PKTNS_ACK_REQUIRED_BIT 0
 #define QUIC_FL_PKTNS_ACK_REQUIRED  (1UL << QUIC_FL_PKTNS_ACK_REQUIRED_BIT)
+
+#define QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED (1UL << 1)
 struct quic_conn {
        uint32_t version;
        /* QUIC transport parameters TLS extension */
@@ -650,6 +652,8 @@ struct quic_conn {
                int rbuf;
                /* Number of sent bytes. */
                uint64_t bytes;
+               /* Number of bytes for prepared packets */
+               uint64_t prep_bytes;
                /* The number of datagrams which may be sent
                 * when sending probe packets.
                 */
index 27b67ee64f83cff4da4f3c1ba5e15c4335afb053..a5740dbcb6b8fc7a52b263353a27a79ba40adaa9 100644 (file)
@@ -644,9 +644,14 @@ static inline void qc_set_timer(struct ssl_sock_ctx *ctx)
                goto out;
        }
 
-       /* XXX TODO: anti-amplification: the timer must be
+       /* anti-amplification: the timer must be
         * cancelled for a server which reached the anti-amplification limit.
         */
+       if (qc->flags & QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED) {
+               TRACE_PROTO("anti-amplification reached", QUIC_EV_CONN_STIMER, ctx->conn);
+               qc->timer = TICK_ETERNITY;
+               goto out;
+       }
 
        if (!qc->path->ifae_pkts && quic_peer_validated_addr(ctx)) {
                TRACE_PROTO("timer cancellation", QUIC_EV_CONN_STIMER, ctx->conn);
@@ -2204,7 +2209,14 @@ static int qc_prep_hdshk_pkts(struct qring *qr, struct ssl_sock_ctx *ctx)
                if (!prv_pkt) {
                        /* Leave room for the datagram header */
                        pos += dg_headlen;
-                       end = pos + qc->path->mtu;
+                       if (!quic_peer_validated_addr(ctx) && objt_listener(ctx->conn->target)) {
+                               if (qc->tx.prep_bytes >= 3 * qc->rx.bytes)
+                                       qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED;
+                               end = pos + QUIC_MIN(qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes);
+                       }
+                       else {
+                               end = pos + qc->path->mtu;
+                       }
                }
 
                cur_pkt = qc_build_pkt(&pos, end, qel, qc, dglen, padding,
@@ -4496,6 +4508,7 @@ static struct quic_tx_packet *qc_build_pkt(unsigned char **pos,
                goto err;
        }
 
+       qc->tx.prep_bytes += pkt->len;
        /* Now that a correct packet is built, let us consume <*pos> buffer. */
        *pos = end;
        /* Attach the built packet to its tree. */