From e30bcfe6cda364620451062a606eaa6636f1a3f6 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 19 May 2026 16:30:40 +0200 Subject: [PATCH] MINOR: proxy/server: reject TCP ALPN h3 without experimental Add a postparsing check on TCP ALPN bind and server setting. An error is reported if the token "h3" is present and expose-experimental-directives is not globally activated. This ensures that QMux protocol won't be selected if experimental features are not explicitely requested. The check is not performed though if "proto qmux" is explicitely defined, as this setting already checks for experimental support. Currently, it's not possible to activate QMux without any explicit "proto qmux" config. However, this will be implemented in a next patch, so this check will become necessary. --- src/proxy.c | 16 ++++++++++++++++ src/server.c | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/proxy.c b/src/proxy.c index f0667228c..d328031ad 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -1778,6 +1778,22 @@ int proxy_finalize(struct proxy *px, int *err_code) } #endif /* TLSEXT_TYPE_application_layer_protocol_negotiation */ } /* HTTP && bufsize < 16384 */ + +#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation + if (px->mode == PR_MODE_HTTP && !bind_conf->mux_proto && + bind_conf->ssl_conf.alpn_str && + strstr(bind_conf->ssl_conf.alpn_str, "\002h3")) { + if (!experimental_directives_allowed) { + ha_alert("HTTP/3 on TCP listed via ALPN on frontend '%s' at [%s:%d] relies on the experimental QMux protocol, " + "must be allowed via a global 'expose-experimental-directives'.\n", + px->id, bind_conf->file, bind_conf->line); + cfgerr++; + } + + mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED); + } +#endif /* TLSEXT_TYPE_application_layer_protocol_negotiation */ + #endif /* USE_OPENSSL */ #ifdef USE_QUIC diff --git a/src/server.c b/src/server.c index 94105518c..9d6a2f481 100644 --- a/src/server.c +++ b/src/server.c @@ -4036,6 +4036,18 @@ static int _srv_parse_finalize(char **args, int cur_arg, return ERR_ALERT | ERR_FATAL; #endif } + else { + if (srv->proxy->mode == PR_MODE_HTTP && !srv->mux_proto && + srv->ssl_ctx.alpn_str && strstr(srv->ssl_ctx.alpn_str, "\002h3")) { + if (!experimental_directives_allowed) { + ha_alert("HTTP/3 on TCP listed via ALPN requires the QMUX protocol which is experimental, " + "must be allowed via a global 'expose-experimental-directives'.\n"); + return ERR_ALERT | ERR_FATAL; + } + + mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED); + } + } if (!(srv->proxy->cap & PR_CAP_LB)) { /* No need to wait for effective proxy mode, it is already known: