mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-17 19:16:56 +00:00
BUG/MINOR: quic: adjust restriction for stateless reset emission
Review RFC 9000 and ensure restriction on Stateless reset are properly enforced. After careful examination, several changes are introduced. First, redefine minimal Stateless Reset emitted packet length to 21 bytes (5 random bytes + a token). This is the new default length used in every case, unless received packet which triggered it is 43 bytes or smaller. Ensure every Stateless Reset packets emitted are at 1 byte shorter than the received packet which triggered it. No Stateless reset will be emitted if this falls under the above limit of 21 bytes. Thus this should prevent looping issues. This should be backported up to 2.6.
This commit is contained in:
parent
f55748a422
commit
5764bc50b5
@ -176,8 +176,15 @@ enum quic_pkt_type {
|
||||
*/
|
||||
#define QUIC_CONN_MAX_PACKET 64
|
||||
|
||||
#define QUIC_STATELESS_RESET_PACKET_HEADER_LEN 5
|
||||
#define QUIC_STATELESS_RESET_PACKET_MINLEN (22 + QUIC_HAP_CID_LEN)
|
||||
/* RFC 9000 10.3. Stateless Reset
|
||||
*
|
||||
* To entities other than its intended recipient, a Stateless Reset will
|
||||
* appear to be a packet with a short header. For the Stateless Reset to
|
||||
* appear as a valid QUIC packet, the Unpredictable Bits field needs to
|
||||
* include at least 38 bits of data (or 5 bytes, less the two fixed
|
||||
* bits).
|
||||
*/
|
||||
#define QUIC_STATELESS_RESET_PACKET_MINLEN (5 + QUIC_STATELESS_RESET_TOKEN_LEN)
|
||||
|
||||
/* Similar to kernel min()/max() definitions. */
|
||||
#define QUIC_MIN(a, b) ({ \
|
||||
|
@ -1687,6 +1687,9 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
|
||||
}
|
||||
}
|
||||
else if (!qc) {
|
||||
/* Stateless Reset sent even for Long header packets as haproxy
|
||||
* emits stateless_reset_token in its TPs.
|
||||
*/
|
||||
TRACE_PROTO("RX non Initial pkt without connection", QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
|
||||
if (!send_stateless_reset(l, &dgram->saddr, pkt))
|
||||
TRACE_ERROR("stateless reset not sent", QUIC_EV_CONN_LPKT, qc);
|
||||
|
@ -981,24 +981,38 @@ int send_stateless_reset(struct listener *l, struct sockaddr_storage *dstaddr,
|
||||
|
||||
TRACE_ENTER(QUIC_EV_STATELESS_RST);
|
||||
|
||||
/* RFC 9000 10.3. Stateless Reset
|
||||
*
|
||||
* Endpoints MUST discard packets that are too small to be valid QUIC
|
||||
* packets. To give an example, with the set of AEAD functions defined
|
||||
* in [QUIC-TLS], short header packets that are smaller than 21 bytes
|
||||
* are never valid.
|
||||
*
|
||||
* [...]
|
||||
*
|
||||
* RFC 9000 10.3.3. Looping
|
||||
*
|
||||
* An endpoint MUST ensure that every Stateless Reset that it sends is
|
||||
* smaller than the packet that triggered it, unless it maintains state
|
||||
* sufficient to prevent looping. In the event of a loop, this results
|
||||
* in packets eventually being too small to trigger a response.
|
||||
*/
|
||||
if (rxpkt->len <= QUIC_STATELESS_RESET_PACKET_MINLEN) {
|
||||
TRACE_DEVEL("rxpkt too short", QUIC_EV_STATELESS_RST);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
prx = l->bind_conf->frontend;
|
||||
prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
|
||||
/* 10.3 Stateless Reset (https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3)
|
||||
* The resulting minimum size of 21 bytes does not guarantee that a Stateless
|
||||
* Reset is difficult to distinguish from other packets if the recipient requires
|
||||
* the use of a connection ID. To achieve that end, the endpoint SHOULD ensure
|
||||
* that all packets it sends are at least 22 bytes longer than the minimum
|
||||
* connection ID length that it requests the peer to include in its packets,
|
||||
* adding PADDING frames as necessary. This ensures that any Stateless Reset
|
||||
* sent by the peer is indistinguishable from a valid packet sent to the endpoint.
|
||||
|
||||
/* RFC 9000 10.3. Stateless Reset
|
||||
*
|
||||
* An endpoint that sends a Stateless Reset in response to a packet that is
|
||||
* 43 bytes or shorter SHOULD send a Stateless Reset that is one byte shorter
|
||||
* than the packet it responds to.
|
||||
*/
|
||||
|
||||
/* Note that we build at most a 42 bytes QUIC packet to mimic a short packet */
|
||||
pktlen = rxpkt->len <= 43 ? rxpkt->len - 1 : 0;
|
||||
pktlen = QUIC_MAX(QUIC_STATELESS_RESET_PACKET_MINLEN, pktlen);
|
||||
pktlen = rxpkt->len <= 43 ? rxpkt->len - 1 :
|
||||
QUIC_STATELESS_RESET_PACKET_MINLEN;
|
||||
rndlen = pktlen - QUIC_STATELESS_RESET_TOKEN_LEN;
|
||||
|
||||
/* Put a header of random bytes */
|
||||
|
Loading…
Reference in New Issue
Block a user