BUG/MINOR: quic-be: handshake errors without connection stream closure

This bug was revealed on backend side by reg-tests/ssl/del_ssl_crt-list.vtc when
run wich QUIC connections. As expected by the test, a TLS alert is generated on
servsr side. This latter sands a CONNECTION_CLOSE frame with a CRYPTO error
(>= 0x100). In this case the client closes its QUIC connection. But
the stream connection was not informed. This leads the connection to
be closed after the server timeout expiration. It shouls be closed asap.
This is the reason why reg-tests/ssl/del_ssl_crt-list.vtc could succeeds
or failed, but only after a 5 seconds delay.

To fix this, mimic the ssl_sock_io_cb() for TCP/SSL connections. Call
the same code this patch implements with ssl_sock_handle_hs_error()
to correctly handle the handshake errors. Note that some SSL counters
were not incremented for both the backends and frontends. After such
errors, ssl_sock_io_cb() start the mux after the connection has been
flagged in error. This has as side effect to close the stream
in conn_create_mux().

Must be backported to 3.3 only for backends. This is not sure at this time
if this bug may impact the frontends.
This commit is contained in:
Frederic Lecaille
2025-11-28 11:27:54 +01:00
parent 63273c795f
commit c36e27d10e
3 changed files with 79 additions and 50 deletions

View File

@@ -30,6 +30,7 @@
#include <haproxy/proxy-t.h>
#include <haproxy/quic_conn-t.h>
#include <haproxy/ssl_sock-t.h>
#include <haproxy/stats.h>
#include <haproxy/thread.h>
extern struct list tlskeys_reference;
@@ -89,6 +90,7 @@ unsigned int ssl_sock_get_verify_result(struct connection *conn);
void ssl_sock_update_counters(SSL *ssl,
struct ssl_counters *counters,
struct ssl_counters *counters_px, int backend);
void ssl_sock_handle_hs_error(struct connection *conn);
#if (defined SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB && TLS_TICKETS_NO > 0)
int ssl_sock_update_tlskey_ref(struct tls_keys_ref *ref,
struct buffer *tlskey);
@@ -241,6 +243,30 @@ static inline struct connection *ssl_sock_get_conn(const SSL *s, struct ssl_sock
return ret;
}
/* Set at <counters> and <counters_px> addresses the SSL statistical counters */
static inline void ssl_sock_get_stats_counters(struct connection *conn,
struct ssl_counters **counters,
struct ssl_counters **counters_px)
{
switch (obj_type(conn->target)) {
case OBJ_TYPE_LISTENER: {
struct listener *li = __objt_listener(conn->target);
*counters = EXTRA_COUNTERS_GET(li->extra_counters, &ssl_stats_module);
*counters_px = EXTRA_COUNTERS_GET(li->bind_conf->frontend->extra_counters_fe,
&ssl_stats_module);
break;
}
case OBJ_TYPE_SERVER: {
struct server *srv = __objt_server(conn->target);
*counters = EXTRA_COUNTERS_GET(srv->extra_counters, &ssl_stats_module);
*counters_px = EXTRA_COUNTERS_GET(srv->proxy->extra_counters_be,
&ssl_stats_module);
break;
}
default:
break;
}
}
#endif /* USE_OPENSSL */
#endif /* _HAPROXY_SSL_SOCK_H */