diff options
author | Frédéric Lécaille <flecaille@haproxy.com> | 2021-11-10 17:30:15 +0100 |
---|---|---|
committer | Frédéric Lécaille <flecaille@haproxy.com> | 2021-11-19 14:37:35 +0100 |
commit | ca98a7f9c01ec03b152dbb8de9e1e953e583caf8 (patch) | |
tree | 1cd714804432ee227c4b4367b4031125d409ee97 | |
parent | a956d151183e412c049b40d11ea384fb9f2fc9b4 (diff) | |
download | haproxy-ca98a7f9c01ec03b152dbb8de9e1e953e583caf8.tar.gz |
MINOR: quic: Anti-amplification implementation
A QUIC server MUST not send more than three times as many bytes as received
by clients before its address validation.
-rw-r--r-- | include/haproxy/xprt_quic-t.h | 4 | ||||
-rw-r--r-- | src/xprt_quic.c | 17 |
2 files changed, 19 insertions, 2 deletions
diff --git a/include/haproxy/xprt_quic-t.h b/include/haproxy/xprt_quic-t.h index be3e8d087..86629456c 100644 --- a/include/haproxy/xprt_quic-t.h +++ b/include/haproxy/xprt_quic-t.h @@ -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. */ diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 27b67ee64..a5740dbcb 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -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. */ |