20307 Commits

Author SHA1 Message Date
Christopher Faulet
8e08a635eb MINOR: muxes: Support an optional ALPN string when defining mux protocols
When a multiplexer protocol is defined, it is now possible to specify the
ALPN it supports, in binary format. This info is optionnal. For now only the
h2 and the h1 multiplexers define an ALPN because this will be mandatory for
a fix. But this could be used in future for different purpose.

This patch will be mandatory for the next fix.
2025-11-20 16:14:52 +01:00
Olivier Houchard
e9d34f991e BUG/MEDIUM: queues: Don't forget to unlock the queue before exiting
In assign_server_and_queue(), there's a rare case when the server was
full, so we created a pendconn, another server was considered but in the
meanwhile the pendconn was unqueued already, so we just left the
function. We did so, however, while still holding the queue lock, which
will ultimately lead to a deadlock, and ultimately the watchdog would
kill the process.
To fix that, just unlock the queue before leaving.

This should be backported to 3.2.
2025-11-20 13:57:06 +01:00
William Lallemand
e0665d4ffe BUG/MINOR: acme: alert when the map doesn't exist at startup
When configuring an acme section with the 'map' keyword, the user must
use an existing map. If the map doesn't exist, a log will be emitted
when trying to add the challenge to the map.

This patch change the behavior by checking at startup if the map exists,
so haproxy would warn and won't start with a non-existing map.

This must be backported in 3.2.
2025-11-20 12:22:19 +01:00
Frederic Lecaille
fab7da0fd0 BUG/MEDIUM: quic-be/ssl_sock: TLS callback called without connection
Contrary to TCP, QUIC does not SSL_free() its SSL *  object when its ->close()
XPRT callback is called. This has as side effect to trigger some BUG_ON(!conn)
with <conn> the connection from TLS callbacks registered at configuration
parsing time, so after this <conn> have been released.

This is the case for instance with ssl_sock_srv_verifycbk() whose role is to
add some checks to the built-in server certificate verification process.

This patch prevents the pointer to <conn> dereferencing inside several callbacks
shared between TCP and QUIC.

Thank you to @InputOutputZ for its report in GH #3188.

As the QUIC backend feature arrived with the current 3.3 dev, no need to backport.
2025-11-20 11:36:57 +01:00
Willy Tarreau
8438ca273f MINOR: limits: explain a bit better what to do when fd limits are exceeded
As shown in github issue #3191, the error message shown when FD limits
are exceeded is not very useful as-is, since the current hard limit is
not displayed, and no suggestion is made about what to change in the
config. Let's explain about maxconn/ulimit-n/fd-hard-limit, suggest
dropping them or setting them to a context-based value at roughly 49%
of the current limit minus the known used FDs for listeners and checks.
This allows common "large" hard limits to report mostly round maxconns.
Example:

  [ALERT]    (25330) : [haproxy.main()] Cannot raise FD limit to 4001020,
  current limit is 1024 and hard limit is 4096. You may prefer to let
  HAProxy adjust the limit by itself; for this, please just drop any
  'maxconn' and 'ulimit-n' from the global section, and possibly add
  'fd-hard-limit' lower than this hard limit. You may also force a new
  'maxconn' value that is a bit lower than half of the hard limit minus
  listeners and checks. This results in roughly 1500 here.
2025-11-20 08:44:52 +01:00
Willy Tarreau
91d4f4f618 MINOR: limits: keep a copy of the rough estimate of needed FDs in global struct
It's always a pain to guess the number of FDs that can be needed by
listeners, checks, threads, pollers etc. We have this estimate in
global.maxsock before calling set_global_maxconn(), but we lose it
the line after. Let's copy it into global.est_fd_usage and keep it.
This will be helpful to try to provide more accurate suggestions for
maxconn.
2025-11-20 08:44:52 +01:00
Frederic Lecaille
2c6720a163 MINOR: quic: uneeded xprt context variable passed as parameter
This quic_conn ->xrpt_ctx is passed to qc_send_ppkts(), the quic_conn is retrieved
from this context to be used inside this function and it is not used at all
by this function.

This patch simply directly passes the quic_conn to qc_send_ppkts(). This is only
what this function needs.
2025-11-20 08:17:44 +01:00
Amaury Denoyelle
d54d78fe9a BUG/MINOR: quic: fix FD usage for quic_conn_closed on backend side
On the frontend side, QUIC transfer can be performed either via a
connection owned FD or multiplex on the listener one. When a quic_conn
is freed and converted to quic_conn_closed instance, its FD if open is
closed and all exchanges are now multiplex via the listener FD.

This is different for the backend as connections only has the choice to
use their owned FD. Thus, special care care must be taken when freeing a
connection and converting it to a quic_conn_closed instance. In this
case, qc_release_fd() is delayed to the quic_conn_closed release.

Furthermore, when the FD is transferred, its iocb and owner fields are
updated to the new quic_conn_closed instance. Without it, a crash will
occur when accessing the freed quic_conn tasklet. A newly dedicated
handler quic_conn_closed_sock_fd_iocb is used to ensure access to
quic_conn_closed members only.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
46c5c232d7 BUG/MINOR: quic: do not decrement jobs for backend conns
jobs is a global counter which serves to account activity through the
whole process. Soft-stop procedure will wait until this counter is
resetted to the nul value.

jobs is not used for backend connections. Thus, it is not incremented
when a QUIC backend connection is instantiated as expected. However,
decrement is performed on all sides during quic_conn_release(). This
causes the counter wrapping.

Fix this by decrementing jobs only for frontend connections. Without
this patch, soft stop procedure will hang indefinitely if QUIC backend
connections were in use.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
1a22caa6ed MINOR: quic: fix trace on quic_conn_closed release
Adjust leaving trace of quic_release_cc_conn() so that the end of the
function is properly reported.
2025-11-19 16:02:22 +01:00
Amaury Denoyelle
e55bcf5746 BUG/MINOR: mux-quic: implement max-reuse server parameter
Properly implement support for max-reuse server keyword. This is done by
adding a total count of streams seen for the whole connection. This
value is used in avail_streams callback.
2025-11-19 16:02:22 +01:00
William Lallemand
c8540f7437 BUG/MINOR: ssl: remove dead code in ssl_sock_from_buf()
When haproxy is compiled in -O0, the SSL_get_max_early_data() symbol is
used in the generated assembly, however -O2 seems to remove this symbol
when optimizing the code.

It happens because `if conn_is_back(conn)` and `if
(objt_listener(conn->target))` are opposed conditions, which mean we
never use the branch when objt_listener(conn->target) is true.

This patch removes the dead code. Bonus: SSL_get_max_early_data() is not
implemented in rustls, and that's the only thing preventing to start
with it.

This can be backported in every stable branches.
2025-11-19 11:00:05 +01:00
William Lallemand
177816d2b8 BUG/MINOR: acme: P-256 doesn't work with openssl >= 3.0
When trying to use the P-256 curve in the acme configuration with
OpenSSL 3.x, the generation of the account was failing because OpenSSL
doesn't return a NIST or SECG curve name, but a ANSI X9.62 one.

Since the ANSI X9.62 curve names were not in the list, it couldn't match
anything supported.

This patch fixes the issue by adding both prime192v1 and prime256v1 name
in the struct curve array which is used during curve parsing.

Must be backported to 3.2.
2025-11-18 11:34:28 +01:00
William Lallemand
9bf01a0d29 BUG/MINOR: mworker: wrong signals during startup
Since the new master-worker model in 3.1, signals are registered in
step_init_3(). However, those signals were supposed to be registered
only for the worker or the standalone mode. It would call the wrong
callback in the master even during configuration parsing.

The patch set the signals handler to NULL for the master so it does
nothing until they really are registered.

Must be backported as far as 3.1.
2025-11-18 10:27:34 +01:00
William Lallemand
709cde6d08 BUG/MEDIUM: mworker: signals inconsistencies during startup and reload
Since haproxy 3.1, the master-worker mode changed to let the worker
parse the configuration instead of the master.

Previously, signals were blocked during configuration parsing and
unblocked before entering the polling loop of the master. This way it
was impossible to start a reload during the configuration parsing.

But with the new model, the polling loop is started in the master before
the configuration parsing is finished, and the signals are still
unblocked at this step. Meaning that it is possible to start a reload
while the configuration is parsing.

This patch reintroduce the behavior of blocking the signals during
configuration parsing adapted to the new model:

- Before the exec() of the reload, signals are blocked.
- When entering the polling loop, the SIGCHLD is unblocked because it is
  required to get a failure during configuration parsing in the worker
- Once the configuration is parsed, upon success in _send_status() or
  upon failure in run_master_in_recovery_mode() every signals are unblocked.

This patch must be backported as far as 3.1.
2025-11-18 10:05:42 +01:00
William Lallemand
b38405d156 CLEANUP: startup: move confusing msg variable
Move the char *msg variable declared in main() in a sub-block since
there's already multiple msg variable in other sub-blocks in this
function.

Also make it const.
2025-11-18 09:43:25 +01:00
Frederic Lecaille
37d01eea37 BUG/MEDIUM: quic-be: prevent use of MUX for 0-RTT sessions without secrets
The QUIC backend crashes when its peer does not support 0-RTT. In this case,
when the sessions are reused, no early-data level secrets are derived by
the TLS stack. This leads to crashes from qc_send_mux() which does not suppose
that both early-data level (qc->eel) and application level (qc->ael) cipher levels
could be non initialized.

To fix this:
  - prevent qc_send_mux() to send data if these two encryption level are not
    intialized. In this case it returns QUIC_TX_ERR_NONE;
  - avoid waking up the MUX from XPRT ->start() callback if the MUX is ready
    but without early-data level secrets to send them;
  - ensure the MUX is woken up by qc_ssl_do_handshake() after handshake completion
    if it is ready calling qc_notify_send()

Thank you to @InputOutputZ for having reported this issue in GH #3188.

No need to backport because QUIC backends is a current 3.3 development feature.
2025-11-17 15:40:24 +01:00
William Lallemand
0367227375 MEDIUM: mworker: set the mworker-max-reloads to 50
There was no mworker-max-reload value by default, it was set to INT_MAX
so this was impossible to reach.

The default value is now 50, which is still high, but no workers should
undergo that much reloads. Meaning that a worker will be killed with
SIGTERM if it reach this much reloads.
2025-11-17 11:54:30 +01:00
Amaury Denoyelle
c67a614e45 MINOR: quic: remove <ipv4> arg from qc_new_conn()
Remove <ipv4> argument from qc_new_conn(). This parameter is unnecessary
as it can be derived from the family type of the addresses also passed
as argument.
2025-11-17 10:20:54 +01:00
Amaury Denoyelle
133f100467 MINOR: quic: refactor qc_new_conn() prototype
The objective of this patch is to streamline qc_new_conn() usage so that
it is similar for frontend and backend sides.

Previously, several parameters were set only for frontend connections.
These arguments are replaced by a single quic_rx_packet argument, which
represents the INITIAL packet triggering the connection allocation on
the server side. For a QUIC client endpoint, it remains NULL. This usage
is consider more explicit.

As a minor change, <target> is moved as the first argument of the
function. This is considered useful as this argument determines whether
the connection is a frontend or backend entry.

Along with these changes, qc_new_conn() documentation has been reworded
so that it is now up-to-date with the newest usage.
2025-11-17 10:13:40 +01:00
Amaury Denoyelle
035c026220 MINOR: quic: support multiple random CID generation for BE side
When a new backend connection is instantiated, a CID is first randomly
generated. It will serve as the first DCID for incoming packets from the
server. Prior to this patch, if the generated CID caused a collision
with an other entries from another connection, an error is reported and
the connection cannot be allocated.

This patch improves this procedure by implementing retries when a
collision occurs. Now, at most three attemps will be performed before
giving up. This is the same procedure already performed for CIDs
instantiated after RETIRE_CONNECTION_ID frame parsing.

Along with this functional change, qc_new_conn() is refactored for
backend instantiation. The CID generation is extracted from it and the
value is passed as an argument. This is considered cleaner as the code
is more similar between frontend and backend sides.
2025-11-17 10:11:04 +01:00
Amaury Denoyelle
8720130cc7 MINOR: quic: do not use quic_newcid_from_hash64 on BE side
quic_newcid_from_hash64 is an external callback. If defined, it serves
as a CID method generation, as an alternative to the default random
implementation.

This mechanism was not correctly implemented on the backend side.
Indeed, <hash64> quic_conn member is only setted for frontend
connections. The simplest solution would be to properly define it also
for backend ones. However, quic_newcid_from_hash64 derivation is really
only useful for the frontend side for now. Thus, this patch disables
using it on the backend side in favor of the default random generator.

To implement this, quic_cid_generate() is splitted in two functions, for
both methods of CIDs generation. This is the responsibility of the
caller to select the proper method. On backend side, only random
implementation is now used.
2025-11-17 10:11:04 +01:00
Christopher Faulet
fc6e3e9081 MINOR: stick-tables: Rename stksess shards to use buckets
The shard keyword is already used by the peers and on the server lines. And
it is unrelated with the session keys distribution. So instead of talking
about shard for the session key hashing, we now use the term "bucket".
2025-11-17 07:42:51 +01:00
Frederic Lecaille
54eeda4b01 BUG/MINOR: quic-be: backend SSL session reuse fix (OpenSSL 3.5)
This bug impacts only the QUIC backends when haproxy is compiled against
OpenSSL 3.5 with QUIC API(HAVE_OPENSSL_QUIC).

The QUIC clients could not reuse their SSL session because the TLS tickets
received from the servers could not be provided to the TLS stack. This should
be done when the stack calls ha_quic_ossl_crypto_recv_rcd()
(OSSL_FUNC_SSL_QUIC_TLS_CRYPTO_RECV_RCD callback).

According to OpenSSL team, an SSL_read() call must be done after the handshake
completion. It seems the correct location is at the same level as for
SSL_process_quic_post_handshake() for quictls.

Thank you to @mattcaswell, @Sashan and @vdukhovni for having helped in solving
this issue.

Must be backported to 3.1
2025-11-14 17:50:49 +01:00
Frederic Lecaille
644bf585c3 CLEANUP: quic: Missing succesful SSL handshake backend trace (OpenSSL 3.5)
This very minor issue impacts only the backend when compiled against OpenSSL 3.5
with QUIC API (HAVE_OPENSSL_QUIC).

The "SSL handshake OK" trace was not dumped by a TRACE() call. This was very
annoying when debugging.

Modify the concerned code section which is a bit ugly and simplify it.
The TRACE() call is done at a unique location for now on.

Should be backported to 3.2 to ease any further backport.
2025-11-14 17:50:49 +01:00
Frederic Lecaille
f0c52f7160 BUG/MINOR: quic-be: missing version negotiation
This bug impacts only the QUIC clients (or backends). The version negotiation
was not supported at all for them. This is an oversight.

Contrary to the QUIC server which choose the negotiated version after having
received the transport parameters (into ClientHello message) the client selects
the negotiated version from the first Initial packet version field. Indeed, the
server transport parameters are inside the ServerHello messages ciphered
into Handshake packets.

This non intrusive patch does not impact the QUIC server implementation.
It only selects the negotiated version from the first Initial packet
received from the server and consequently initializes the TLS cipher context.

Thank you to @InputOutputZ for having reporte this issue in GH #3178.

No need to backport because the QUIC backends support arrives with 3.3.
2025-11-14 17:37:34 +01:00
Willy Tarreau
0746aa68b8 BUG/MINOR: check: fix QUIC check test when QUIC disabled
Latest commit ef206d441c ("MINOR: check: ensure QUIC checks configuration
coherency") introduced a regression when QUIC is not compiled in. Indeed,
not specifying a check proto sets mux_proto to NULL, which also happens to
be the value of get_mux_proto("QUIC"), so it complains about QUIC. Let's
add a non-null check in addition to this.

No backport is needed.
2025-11-14 17:27:53 +01:00
Willy Tarreau
4a6dec7193 DEBUG: servers: add a few checks for stress-testing idle conns
The latest idle conns fix 9481cef948 ("BUG/MEDIUM: connection: do not
reinsert a purgeable conn in idle list") addresses a very hard-to-hit
case which manifests itself with an attempt to reuse a connection fails
because conn->mux is NULL:

  Program terminated with signal SIGSEGV, Segmentation fault.
  #0  0x0000655410b8642c in conn_backend_get (reuse_mode=4, srv=srv@entry=0x6554378a7140,
      sess=sess@entry=0x7cfe140948a0, is_safe=is_safe@entry=0,
      hash=hash@entry=910818338996668161) at src/backend.c:1390
  1390     if (conn->mux->takeover && conn->mux->takeover(conn, i, 0) == 0) {

However the condition that leads to this situation can be detected
earlier, by the presence of the connection in the toremove_list, whose
race window is much larger and easier to detect.

This patch adds a few BUG_ON_STRESS() at selected places that an detect
this condition. When built with -DDEBUG_STRESS and run under stress with
two distinct processes communicating over H2 over SSL, under a stress of
400-500k req/s, the front process usually crashes in the first 10-30s
triggering in _srv_add_idle() if the fix above is reverted (and it does
not crash with the fix).

This is mainly included to serve as an illustration of how to instrument
the code for seamless stress testing.
2025-11-14 17:00:17 +01:00
Amaury Denoyelle
9481cef948 BUG/MEDIUM: connection: do not reinsert a purgeable conn in idle list
A recent patch was introduced to fix a rare race condition in idle
connection code which would result in a crash. The issue is when MUX IO
handler run on top of connection moved in the purgeable list. The
connection would be considered as present in the idle list instead, and
reinserted in it at the end of the handler while still in the purge
list.

  096999ee208b8ae306983bc3fd677517d05948d2
  BUG/MEDIUM: connections: permit to permanently remove an idle conn

This patch solves the described issue. However, it introduces another
bug as it may clear connection flag when removing a connection from its
parent list. However, these flags now serve primarily as a status which
indicate that the connection is accounted by the server. When a backend
connection is freed, server idle/used counters are decremented
accordingly to these flags. With the above patch, an incorrect counter
could be adjusted and thus wrapping would occured.

The first impact of this bug is that it may distort the estimated number
of connections needed by servers, which would result either in poor
reuse rate or too many idle connections kept. Another noticeable impact
is that it may prevent server deletion.

The main problem of the original and current issues is that connection
flags are misinterpreted as telling if a connection is present in the
idle list. As already described here, in fact these flags are solely a
status which indicate that the connection is accounted in server
counters. Thus, here are the definitive conclusion that can be learned
here :

* (conn->flags & CO_FL_LIST_MASK) == 1:
  the connection is accounted by the server
  it may or may not be present in the idle list

* (conn->flags & CO_FL_LIST_MASK) == 0
  the connection is not accounted and not present in idle list

The discussion above does not mention session list, but a similar
pattern can be observed when CO_FL_SESS_IDLE flag is set.

To keep the original issue solved and fix the current one, IO MUX
handlers prologue are rewritten. Now, flags are not checked anymore for
list appartenance and LIST_INLIST macro is used instead. This is
definitely clearer with conn_in_list purpose here.

On IO MUX handlers end, conn idle flags may be checked if conn_in_list
was true, to reinsert the connection either in idle or safe list. This
is considered safe as no function should modify idle flags when a
connection is not stored in a list, except during conn_free() operation.

This patch must be backported to every stable versions after revert of
the above commit. It should be appliable up to 3.0 without any issue. On
2.8 and below, <idle_list> connection member does not exist. It should
be safe to check <leaf_p> tree node as a replacement.
2025-11-14 16:06:34 +01:00
Amaury Denoyelle
d79295d89b Revert "BUG/MEDIUM: connections: permit to permanently remove an idle conn"
The target patch fixes a rare race condition which happen when a MUX IO
handler is working on a connection already moved into the purge list. In
this case, the handler will incorrectly moved back the connection into
the idle list.

To fix this, conn_delete_from_tree() was extended to remove flags along
with the connection from the idle list. This was performed when the
connection is moved into the purge list. However, it introduces another
issue related to the idle server connection accounting. Thus it is
necessary to revert it prior to the incoming newer fix.

This patch must be backported to every version where the original commit
is.
2025-11-14 16:06:34 +01:00
Willy Tarreau
6b9c3d0621 CLEANUP: peers: remove an unneeded null check
Coverity reported in GH #3181 that a NULL test was useless, in
peers_trace(), which is true since the peer always belongs to a
peers section and it was already dereferenced. Let's just remove
the test to avoid the confusion.
2025-11-14 13:47:20 +01:00
Amaury Denoyelle
ef206d441c MINOR: check: ensure QUIC checks configuration coherency
QUIC is now supported on the backend side, thus it is possible to use it
with server checks. However, checks configuration can be quite
extensive, differing greatly from the server settings.

This patch ensures that QUIC checks are always performed under a
controlled context. Objectives are to avoid any crashes and ensure that
there is no suprise for users in respect to the configuration.

The first part of this patch ensures that QUIC checks can only be
activated on QUIC servers. Indeed, QUIC requires dedicated
initialization steps prior to its usage.

The other part of this patch disables QUIC usage when one or multiple
specific check connection settings are specified in the configuration,
diverging from the server settings. This is the simplest solution for
now and ensure that there is no hidden behavior to users. This means
that it's currently impossible to perform QUIC checks if other endpoints
that the server itself. However for now there is no real use-case for
this scenario.

Along with these changes, check-proto documentation is updated to
clarify QUIC checks behavior.
2025-11-14 13:42:08 +01:00
Amaury Denoyelle
ca5a5f37a1 MINOR: check: use auto SNI for QUIC checks
By default, check SNI is set to the Host header when an HTTPS check is
performed. This patch extends this mode so that it is also active when
QUIC checks are executed.

This patch should improve reuse rate with checks. Indeed, SNI is also
already automatically set for normal traffic. The same value must be
used during check so that a connection hash match can be found.
2025-11-14 13:42:08 +01:00
Olivier Houchard
333deef485 BUG/MEDIUM: h1: prevent a crash on HTTP/2 upgrade
Change h1_process() to return -2 when the mux is destroyed but the
connection is not, so that we can differentiate between "both mux and
connection were destroyed" and "only the mux was destroyed".
It can happen that only the mux gets destroyed, and the connection is
still alive, if we did upgrade it to HTTP/2.
In h1_wake(), if the connection is alive, then return 0, as the wake
methods should only return -1 if the connection is dead.
This fixes a bug where the ssl xprt would consider the connection
destroyed, and thus would consider its tasklet should die, and return
NULL, and its TASK_RUNNING flag would never be removed, leading to an
infinite loop later on. This would happen anytime an HTTP/2 upgrade was
successful.

This should be backported up to 2.8. While the bug by commit
00f43b7c8b136515653bcb2fc014b0832ec32d61, it was not triggered before
only by chance, and exists in previous releases too.
2025-11-14 12:49:35 +01:00
Olivier Houchard
2f8f09854f MINOR: h1: h1_release() should return if it destroyed the connection
h1_release() is called to destroy everything related to the mux h1,
usually even the connection. However, it handles upgrades to HTTP/2 too,
in which case the h1 mux will be destroyed, but the connection will
still be alive. So make it so it returns 0 if everything is destroyed,
and -1 if the connection is still alive.

This should be backported up to 2.8, as a future bugfix will depend on
it.
2025-11-14 12:49:35 +01:00
Christopher Faulet
14a333c4f4 CLEANUP: stick-tables: Don't needlessly compute shard number in stksess_free()
Since commit 0bda33a3e ("MINOR: stick-tables: remove the uneeded read lock
in stksess_free()"), the lock on the shard is no longer acquired. So it is
useless to still compture the shard number. The result is never used and can
be safely removed.
2025-11-14 11:56:14 +01:00
Christopher Faulet
346d6c3ac7 BUG/MINOR: stick-tables: Fix return value for __stksess_kill()
The commit 9938fb9c7 ("BUG/MEDIUM: stick-tables: Fix race with peers when
killing a sticky session") introduced a regression.

__stksess_kill() must always return 0 if the session cannot be released. But
when the ref_cnt is tested under the update lock, a success is reported if
the session is still in-used. 0 must be returned in that case.

This bug is harmless because callers never use the return value of
__stksess_kill() or stksess_kill().

This bug must be backported as far as 3.0.
2025-11-14 11:56:14 +01:00
Christopher Faulet
bd4fff9a76 BUG/MEDIUM: stick-tables: Always return the good stksess from stktable_set_entry
In stktable_set_entry(), the return value of __stktable_store() is not
tested while it is possible to get an existing session with the same key
instead of the one we want to insert. It happens when we fails to upgrade
the read lock on the bucket to an write lock. In that case, we release the
lock for a short time to get a write lock.

So, to fix the bug, we must check the session returned by __stktable_store()
and take care to return this one.

The bug was introduced by the commit e62885237c ("MEDIUM: stick-table: make
stktable_set_entry() look up under a read lock"). It must be backported as
far as 2.8.
2025-11-14 11:56:12 +01:00
William Lallemand
bf639e581d BUILD: ech: fix clang warnings
No impact as the state is either SHOW_ECH_SPECIFIC or SHOW_ECH_ALL but
never anything else.

src/ech.c:240:6: error: variable 'p' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:275:12: note: uninitialized use occurs here
  275 |         ctx->pp = p;
      |                   ^
src/ech.c:240:2: note: remove the 'if' if its condition is always true
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:228:17: note: initialize the variable 'p' to silence this warning
  228 |         struct proxy *p;
      |                        ^
      |                         = NULL
src/ech.c:240:6: error: variable 'bind_conf' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:276:11: note: uninitialized use occurs here
  276 |         ctx->b = bind_conf;
      |                  ^~~~~~~~~
src/ech.c:240:2: note: remove the 'if' if its condition is always true
  240 |         if (ctx->state == SHOW_ECH_ALL) {
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/ech.c:229:29: note: initialize the variable 'bind_conf' to silence this warning
  229 |         struct bind_conf *bind_conf;
      |                                    ^
      |                                     = NULL
2 errors generated.
make: *** [Makefile:1062: src/ech.o] Error 1
2025-11-14 11:35:38 +01:00
William Lallemand
3d15c07ed0 MINOR: cfgcond: add "awslc_api_atleast" and "awslc_api_before"
AWS-LC features are not easily tested with just the openssl version
constant. AWS-LC uses its own API versioning stored in the
AWSLC_API_VERSION constant.

This patch add the two awslc_api_atleast and awslc_api_before predicates
that help to check the AWS-LC API.
2025-11-14 11:01:45 +01:00
Amaury Denoyelle
8415254cea MINOR: check: clarify check-reuse-pool interaction with reuse policy
check-reuse-pool can only perform as expected if reuse policy on the
backend is set to aggressive or higher. Update the documentation to
reflect this and implement a server diag warning.
2025-11-14 10:44:05 +01:00
Amaury Denoyelle
52a7d4ec39 BUG/MINOR: check: fix reuse-pool if MUX inherited from server
Check reuse is only performed if no specific check connect options are
specified on the configuration. This ensures that reuse won't be
performed if intending to use different connection parameters from the
default traffic.

This relies on tcpcheck_use_nondefault_connect() which indicates if the
check has any specific connection parameters. One of them if check
<mux_proto> field. However, this field may be automatically set during
init_srv_check() in some specific conditions without any explicit
configuration, most notably when using http-check rulesets on an HTTP
backend. Thus, it prevents connection reuse for these checks.

This commit fixes this by adjuting tcpcheck_use_nondefault_connect().
Beside checking check <mux_proto> field, it also detects if it is
different from the server configuration. This is sufficient to know if
the value is derived from the configuration or automatically calculated
in init_srv_check().

Note that this patch introduces a small behavior change. Prior to it,
check reuse were never performed if "check-proto" is explicitely
configured. Now, check reuse will be performed if the configured value
is identical to the server MUX protocol. This is considered as
acceptable as connection reuse is safe when using a similar MUX
protocol.

This must be backported up to 3.2.
2025-11-14 10:44:05 +01:00
Amaury Denoyelle
5d021c028e BUG/MINOR: check: only try connection reuse for http-check rulesets
In 3.2, a new server keyword "check-reuse-pool" has been introduced. It
allows to reuse a connection for a new check, instead of always
initializing a new one. This is only performed if the check does not
rely on specific connection parameters differing from the server.

This patch further restricts reuse for checks only when an HTTP ruleset
is used at the backend level. Indeed, reusing a connection outside of
HTTP is an undefined behavior. The impact of this bug is unknown and
depends on the proxy/server configuration. In the case of an HTTP
backend with non-HTTP checks, check-reuse-pool would probably cause a
drop in reuse rate.

Along this change, implement a new diagnostic warning on servers to
report that check-reuse-pool cannot apply due to an incompatible check
type.

This must be backported up to 3.2.
2025-11-14 10:44:03 +01:00
Amaury Denoyelle
d92f8f84fb MINOR: cfgdiag: adjust diag on servers
Adjust code dealing with diagnostics performed on server. The objective
is to extract the check on duplicate cookies in a dedicated function
outside of the proxies/servers loop.

This does not have any noticeable impact. This patch is merely a code
improvment to implement easily new future diagnostics on servers.
2025-11-14 10:00:26 +01:00
Amaury Denoyelle
d12971dfea MINOR: check: delay MUX init when SSL ALPN is used
When instantiating a new connection for check, its MUX may be
initialized early. This was not performed though if SSL ALPN negotiation
will be used, except if check MUX is already fixed.

However, this method of initialization is problematic when QUIC MUX is
used. Indeed, this multiplexer must only be instantiated after the above
application protocol is known, which is derived from the ALPN
negotiation. If this is not the case a crash will occur in qmux_init().

In fact, a similar problem was already encountered for normal traffic.
Thus, a change was performed in connect_server() : MUX early
initialization is now always skipped if SSL ALPN negotiation is active,
even if MUX is already fixed. This patch introduces a similar change for
checks.

Without this patch, it is not possible to perform check on QUIC servers
as expected. Indeed, when http-check ruleset is active a crash would
occur prior to it.
2025-11-14 09:49:04 +01:00
Damien Claisse
1d46c08689 MINOR: ssl/sample: expose ssl_*c_curve for AWS-LC
The underlying SSL_get_negotiated_group function has been backported
into AWS-LC [1], so expose the feature for users of this TLS stack
as well. Note that even though it was actually added in AWS-LC 1.56.0,
we require AWSLC_API_VERSION >= 35 which was released in AWS-LC 1.57.0,
because API version wasn't incremented after this change. As the delta
is one minor version (less than two weeks), I consider this acceptable
to avoid relying on a proxy constant like TLSEXT_nid_unknown which
might be removed at some point.

[1] d6a37244ad
2025-11-13 17:36:43 +01:00
William Lallemand
b9b158ea4c BUG/MINOR: acme: can't override the default resolver
httpclient_acme_init() was called in cfg_parse_acme() which is at
section parsing. httpclient_acme_init() also calls
httpclient_create_proxy() which could create a "default" resolvers
section if it doesn't exists.

If one tries to override the default resolvers section after an ACME
section, the resolvers section parsing will fail because the section was
already created by httpclient_create_proxy().

This patch fixes the issue by moving the initialization of the ACME
proxy to a pre_check callback, which is called just before
check_config_validity().

Must be backported in 3.2.
2025-11-13 17:17:11 +01:00
William Lallemand
2bdf5a7937 BUG/MEDIUM: acme: move from mt_list to a rwlock + ebmbtree
The current ACME scheduler suffers from problems due to the way the
tasks are stored:

- MT_LIST are not scalables when having a lot of ACME tasks and having
  to look for a specific one.
- the acme_task pointer was stored in the ckch_store in order to not
  passing through the whole list. But a ckch_store can be updated and
  the pointer lost in the previous one.
- when a task fails, the ptr in the ckch_store was not removed because
  we only work with a copy of the original ckch_store, it would need to
  lock the ckchs_tree and remove this pointer.

This patch fixes the issues by removing the MT_LIST-based architecture,
and replacing it by a simple ebmbtree + rwlock design.

The pointer to the task is not stored anymore in the ckch_store, but
instead it is stored in the acme_tasks tree. Finding a task is done by
doing a lookup on this tree with a RDLOCK.
Instead of checking if store->acme_task is not NULL, a lookup is also
done.

This allow to remove the stuck "acme_task" pointer in the store, which
was preventing to restart an acme task when the previous failed for this
specific certificate.

Must be backported in 3.2.
2025-11-13 15:18:12 +01:00
Frederic Lecaille
c76e072e43 MINOR: quic-be: avoid a useless I/O callback wakeup for 0-RTT sessions
For backends and 0-RTT sessions, this patch modifies the ->start() callback to
wake up the I/O callback only if the connection (and the mux) is not ready. Note that
connect_server() has been modified to call this xprt callback just after having
created the mux and installed the mux. Contrary to 1-RTT session, for 0-RTT sessions,
the connections are always ready before calling this ->start xprt callback.
2025-11-13 14:04:31 +01:00
Frederic Lecaille
92d2ab76e0 MINOR: quic-be: do not create the mux after handshake completion (for 0-RTT)
This is required during connection with 0-RTT support, to prevent two mux creations.
Indeed, for 0-RTT sessions, the QUIC mux is already started very soon from
connect_server() (src/backend.c).
2025-11-13 14:04:31 +01:00