BUG/MEDIUM: quic: use datagram destination as source for Retry · haproxy/haproxy@a0ddcac · GitHub
Skip to content

Commit a0ddcac

Browse files
ygkata-denoyelle
authored andcommitted
BUG/MEDIUM: quic: use datagram destination as source for Retry
When a QUIC listener is bound on a wildcard address, the local address targeted by the client is retrieved on reception via IP_PKTINFO or equivalent. It is then used as source address for all datagrams of the connection, either by binding the connection socket on it, or via ancillary data when the listener socket is used. Without it, the kernel selects the source address from the route to the client, which may differ from the one targeted by the client. This is typically the case when several addresses are assigned to the host, for example VIPs configured on a loopback interface behind a load balancer in direct routing mode. As QUIC clients usually rely on connected UDP sockets, datagrams from another address are then silently dropped by their kernel. However, Retry packets are emitted before any connection exists, via send_retry() which used a bare sendto() on the listener socket without source address. In the above conditions, the client never receives the Retry and keeps retransmitting its Initial packet until it gives up. Retry is emitted in particular when quic-force-retry is set on the bind line, when a quic-initial send-retry rule matches, or when the number of half-open connections reaches tune.quic.fe.sec.retry-threshold, so handshakes may also fail only intermittently under load. Apart from not using Retry at all, which removes client address validation, the usual workaround is to explicitly bind each address, in addition to or instead of the wildcard one. Fix this by adding a source address parameter to send_retry(), before the destination one. Its callers set it to the datagram destination address, and emission now relies on quic_lstnr_sock_send(), which only uses it if the listener is bound on a wildcard address. Apart from the source address, the emission is unchanged. Also fix the trace emitted on send failure, which was a copy of the previous one. This should fix github issue #3503. This should be backported up to 2.8. Note that it relies on the two previous patches: - MINOR: quic: use the listener for Retry and Version Negotiation emission - MINOR: quic: define a function to emit a datagram on a listener socket Prior to 3.4, quic_dgram addresses are of sockaddr_storage type, so the casts are not necessary. Prior to 2.9, send_retry() is a static function defined in quic_conn.c.
1 parent 5090b6b commit a0ddcac

3 files changed

Lines changed: 14 additions & 8 deletions

File tree

‎include/haproxy/quic_tx.h‎

Lines changed: 2 additions & 1 deletion

‎src/quic_rx.c‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1845,7 +1845,9 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
18451845
/* Validate the token, retry or not only when connection is unknown. */
18461846
if (!quic_token_validate(pkt, dgram, l, qc, &token_odcid)) {
18471847
if (dgram->flags & QUIC_DGRAM_FL_SEND_RETRY) {
1848-
if (send_retry(l, (struct sockaddr_storage *)&dgram->saddr, pkt, pkt->version)) {
1848+
if (send_retry(l, (struct sockaddr_storage *)&dgram->daddr,
1849+
(struct sockaddr_storage *)&dgram->saddr,
1850+
pkt, pkt->version)) {
18491851
TRACE_ERROR("Error during Retry generation",
18501852
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
18511853
}
@@ -1875,7 +1877,9 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
18751877

18761878
TRACE_PROTO("Initial without token, sending retry",
18771879
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
1878-
if (send_retry(l, (struct sockaddr_storage *)&dgram->saddr, pkt, pkt->version)) {
1880+
if (send_retry(l, (struct sockaddr_storage *)&dgram->daddr,
1881+
(struct sockaddr_storage *)&dgram->saddr,
1882+
pkt, pkt->version)) {
18791883
TRACE_ERROR("Error during Retry generation",
18801884
QUIC_EV_CONN_LPKT, NULL, NULL, NULL, pkt->version);
18811885
goto out;

‎src/quic_tx.c‎

Lines changed: 6 additions & 5 deletions

0 commit comments

Comments
 (0)