Hi, HAProxy 3.4.0 was released on 2026/06/03. It added 92 new commits after version 3.4-dev14.
We were right to emit another -dev last week. It allowed everyone to focus a bit more on stabilization and it left time for several last-minute issues to surface and be addressed, which was pretty much the point. It's great that this feedback on -dev14 arrived, really! Better late than never! I'll try to summarize here by categories the changes since 3.3. If the frame here looks suspiciously similar to the one used in 3.2, it's not a coincidence (summarizing and classifying 6 months of changes is always a super hard exercise and it worked out well for 3.2 so I shamelessly reused the same organization). [ As a side note, it's not an intentional easter egg, but I've spread this task over 2 days and I'm pretty sure I've lost a left-over draft paragraph from 3.2 when I stopped the first day, that I couldn't spot later after re-reading 3 times. So if you feel very surprised to discover something new announced here that we already had, that might be it ;-) ] And as most already expect it, a detailed overview will appear soon on the HAProxyTech blog here: https://www.haproxy.com/blog/announcing-haproxy-3-4 1) Core ------- - Performance & scalability: - CPU topology made much easier to drive on large systems. "cpu-affinity" chooses how threads are pinned within a group (all cores of the group, of the CCX, just their own core, or their own CPU thread); "cpu-policy" gains "threads-per-core 1" to start a single thread per physical core (leaving room for the NIC driver, or for the new process during reloads); and "max-threads-per-group" creates more, smaller groups on CPUs with large unified L3 caches. Measured gains range from "same performance with half the threads" up to 10-15%, giving a reasonable toolset for portable configs that adapt to the hardware. - The default "max-threads-per-group" was lowered from 64 to 16 after a lot of experimentation: on large machines this significantly lowers contention (notably at the file-descriptor layer, roughly doubling performance on a 64-core machine) and matches what was already the default on multi-CCX systems such as EPYC. Configs that relied on a single large group are now split into several smaller groups. - A forced "nbthreads" larger than the per-group max (typically 64) used to be silently capped since CPU topology arrived in 3.2; now the required number of thread groups is automatically created to match it, even without a cpu-policy (this was already backported to 3.3). Configs with more than 64 threads and no explicit thread-groups will now actually use all the requested threads. - The hard limit on thread groups was raised from 64 to 32768 (of up to 64 threads each) for more flexible resource allocation on large systems without rebuilding. There should be no visible impact on existing setups. - Extra per-request stats counters were split per thread group internally, removing a contention point on large systems. Reported numbers are unchanged (they're aggregated). On top of that, a new stats directive "calculate-max-counters" lets you drop the shared counters that exist solely to compute the max req/s, max sess/s, etc. that most users no longer look at. Together these showed 16-20% gains on HTTP/1 on systems with many threads per group. - Stick-table contention was reduced further: elements are now moved to a temporary list and freed outside the lock, lowering peak CPU usage in high-update scenarios. - The pattern (maps/ACL) commit phase was reorganized with one tree/list head per generation, turning the post-upload purge of old generations into a cheap batched dequeue instead of a costly scan. Purge time is now fast and deterministic and should no longer trigger watchdog warnings when updating large maps/ACLs. - Scheduler latency improvements under extreme load (attacks or recovery): the CLI in particular now stays responsive even with 100000 tasks in the run queue. - The internal random number generator used by UUID, QUIC retry token, WebSocket secrets and DNS requests was reworked to stop disclosing internal state: its output is now hidden through XXH3(), and is now thread-local and much faster (now scales with threads), removing contention under floods able to trigger many randoms. A minimal backport is planned to harden older releases soon (just the XXH3 part for now, that comes at no cost). - A few locking updates here and there showed up to ~4% performance gains (queue for example). - The QUIC listener RX path now uses a lockless ring instead of an mt_list when not in sock-per-conn mode, to redispatch incoming datagrams to other threads, removing a source of watchdog triggers under high load, and it may significantly lower the CPU usage of moderately loaded systems. - The cache avoids a useless memory copy when storing objects, and the wait-on-body payload is defragmented once up front instead of being copied again later for analysis. - Memory usage: - Multiple buffer sizes at the stream layer. To inspect a request body (look up a user ID, scan for bad patterns, etc.) you no longer have to raise "tune.bufsize" globally: set "tune.bufsize.large" and let "wait-for-body" allocate a large buffer only when the default one fills up, instead of paying the large-buffer footprint in every mux. Please test if you use a non-standard bufsize. - And the opposite: small buffers for queued/retained requests! The new backend "option use-small-buffers" reallocates a small buffer (sized via "tune.bufsize.small") for a request that only waits in queue or is duplicated for an L7 retry, saving memory on overloaded nodes. It can make a difference when using maxconn while dealing with large request floods, as most requests (especially from attacks) can be small (e.g. 1kB) dividing by 16 the memory consumed to keep the request in the queue. - Reliability / hardening: - Pool creation now rejects bogus sizes cleanly and reports the offending value (some tunables could otherwise fail a pool and be caught too late; from the ANSSI/Almond audit), and malloc()-style size multiplications were moved to an overflow-checking helper in 25 places. - "balance random" fairness was improved for large farms with very low per-server load (0-1 connection): when two servers have the same number of concurrent connections, recent traffic (req/s) is used as a second guess, cutting the 2-3:1 imbalance down to a few percent. This was also backported to 3.3. - A startup timing test now warns if a userlist password hash takes more than 10ms, to catch web-unsuitable hash choices before production (due to some algorithms being so slow they take servers down in production). - Other: - Filters reworked toward decompression: filters can now be direction- specific (request vs response), the compression filter was split into two, and a new "filter-sequence" directive sets the per-direction filter order. This is the groundwork for upcoming decompression (and may be useful on its own). - some master process management refinements bringing the master-worker model an increased robustness against various startup races 2) HTTP ------- - Easier HTTP version reporting: getting a correct HTTP version into logs has long been complicated, because the version lives at different layers depending on the protocol (H2/H3 carry no version string, H1 has it in the message). This was refactored so "req.ver"/"res.ver" always report the real version in "major.minor" form, "capture.*" returns the same with "HTTP/" prepended (for compatibility), and requests/responses to/from internal applets now reflect the other side's version instead of a hardcoded 1.1. This means that for a response served from the cache or received by the httpclient, logs now report the actual mux version (such as 2.0 behind mux-h2). This is more natural and more in line with users expectations. - HTTP/2 hardening against floods and abusive streams: - "tune.h2.fe.max-frames-at-once" / "tune.h2.be.max-frames-at-once" cap how many frames are processed per call (helps with very large multi-MB tune.bufsize where many small frames would cause latency), and "tune.h2.fe.max-rst-at-once" yields more often on RST_STREAM. Setting the latter to a low value (e.g. "1") is extremely effective against RST_STREAM floods. Glitches are also now counted for RST_STREAM frames received before the task even had a chance to run (a strong flood indicator). - The maximum number of concurrent streams (tune.h2.fe.max-concurrent- streams) can now be made dynamic and follow the executing thread's load, so connections are smoothly throttled under floods instead of streams being rejected. Example used in local tests to cut run-queue size and latency under attack: tune.h2.fe.max-total-streams 10000 tune.h2.fe.max-concurrent-streams 100 rq-load auto min 12 - A new "tune.h2.log-errors" directive decides whether logs are emitted for H2 stream errors, connection errors, or never, to avoid per-request log pollution from certain request errors in exposed environments. - Stricter HTTP/1 parsing: chunk extensions are now parsed more strictly (even though not used), and an H2 preface received while H2 upgrade is disabled now returns "405 Method Not Allowed" instead of "400". This could change a little bit status codes distribution in logs for those disabling the upgrade, when dealing with scanners. - Streams elasticity ("tune.streams-elasticity"): a global streams-to- connections target to be enforced when reaching frontend saturation, with unused streams reallocated to existing connections at lower load, to limit the excess amount of streams during incidents or attacks. H2 and the QUIC mux share the same total stream budget, but H2 allocates the resource once for all on a connection while QUIC is able to re-adjust the limit as the traffic flows. - New bulk header actions "set-headers-bin", "add-headers-bin" and "del-headers-bin" process a whole group of headers at once (a prefix filters which ones), to ease passing groups of headers from servers, filters or SPOA, or to snapshot and later restore a set of headers. 3) SSL ------ - ACME matured a lot since its experimental arrival in 3.2: - DNS-01 challenge support, with optional pre-checking of the challenge propagation via periodic TXT-record probes ("challenge-ready dns" in the "acme" section, so we don't ask the ACME server to verify too early; "challenge-ready cli" lets you validate propagation manually). - The "dns-persist-01" challenge: create one DNS entry once and you're done, getting the best of both worlds (wildcards without handing full DNS-zone access to the tool). For now only LetsEncrypt staging servers support it. - IP SAN in certificate requests (certs usable when connecting by raw IP), and ACME "profiles" so the CA can pick the issuance policy (classic, shortlived, etc.). - External Account Binding (EAB), to issue certificates using an account from another service. - "tune.ssl.certificate-compression" can forcefully disable TLS certificate compression (with OpenSSL >= 3.2), essentially as a hardening knob; the default is unchanged. - OpenSSL 4.0 support: with the change to use X509_STORE_get1_objects(), it now builds and runs. - private-key load failures are reported more precisely now. - Better handling of "proto"/"alpn"/explicit protocol for backend connections and checks, so that e.g. a check can use a QUIC address and the QUIC mux is selected automatically for such address classes; - JWT / JWE / JWS got a lot of udpates this cycle (useful for token validation and now decryption at the edge): - New decryption converters jwt_decrypt_cert() (asymmetric) and jwt_decrypt_secret() (symmetric), plus jwt_decrypt_jwk() taking an RSA key in JWK format. - jwt_decrypt_cert() supports EC certs, and ECDH-ES algorithms are supported. - The JWE code can restrict the list of supported algorithms (and disables the deprecated RSA1_5 by default). JWS now supports HMAC for signing. - As a by-product, generic AES-CBC converters aes_cbc_enc() / aes_cbc_dec() were added. 4) QUIC / HTTP/3 ---------------- - QMUX (HTTP/3 over TCP), formerly "QUIC over streams": a preliminary, fully experimental implementation of the latest IETF draft, on frontend and backend, enabled with "proto qmux" on "bind"/"server" lines, or automatically enabled on "bind" lines via the presence of "h3" in the ALPN string (not present by default). The goal is to carry HTTP/3 over TCP, e.g. as a more modern alternative to HTTP/2. Do not use it outside the lab yet; it stays behind the experimental directive (we haven't yet enabled it on haproxy.org, though we might at some point). - "tune.quic.fe.stream-max-total" enforces a maximum number of total streams per connection (like H2), which can force clients to periodically renew a connection (potentially useful to mitigate some attack classes). - QUIC now produces termination events ("term_events"), far more detailed than the usual 2-character termination codes, that are already used by h1 and h2. - the "quic-cc-algo" directive is supported on servers, permitting to choose the congestion-control algorithm for outgoing QUIC connections. 5) Dynamic backends ------------------- This was one of the most requested long-term features, and a lot of it landed during 3.4. It's a big step toward orchestrated, reload-free deployments. - Backend creation from the CLI: create a backend from an existing named "defaults" section, add servers to it, then publish/enable it. See "add backend", "add server" and "publish backend" in the management doc. - Publish / unpublish: publishing is more or less to a backend what maintenance mode is to a server: "use_backend" rules pointing to an unpublished backend are skipped and the next matching rule is evaluated. "force-persist" rules are now allowed in the frontend (e.g. a secret key granting early access to a not-yet-published backend for testing). The backend status is reflected on the stats page. - Backend deletion: a backend that is no longer referenced, has no server and no connection can be deleted with "del backend". A few corner cases may still take time or be unsupported (active connection to a local applet such as the cache, or QUIC on the backend whose connections aren't listed yet). - Dynamic backends can now depend on a named "defaults" section that uses "http-errors" (was a 3.3 limitation). 6) Sample fetch functions / converters / actions ------------------------------------------------ - New converters "reverse" and "reverse_dom" (reverse a string / a domain name), e.g. combine "reverse_dom" with "map_beg()" to do longest-match from the end of a hostname (foo.example.com vs example.com). The doc has examples. - New "fe_exists()" converter tests whether a frontend named by the input sample exists. - New "dump_all_vars()" sample fetch dumps all or a scoped/prefixed subset of variables as a single delimited string, handy to pass timing or trust info to a backend in one rule instead of many. - Connection-time sample fetch functions: "fc.timer.handshake()" and other fc_* values from tcp_info can now be evaluated (and stored in session variables) in the connection or session rulesets instead of being recomputed per stream for values that won't change. - "fc_saved_syn" TCP sample fetch function returns a binary dump of the recorded TCP SYN packet on modern Linux (needs bind option "tcp-ss" = "1" ip+tcp or "2" eth+ip+tcp). About 20 converters extract fields from it (source IP, TCP window, MSS, ...) and "ip.fp" builds a fingerprint from mostly-invariant parts. This is meant to help preserve access for innocent users behind a shared IP (CGNAT) during DDoS. Still experimental in spirit. - "cpu_usage_proc", "cpu_usage_grp" and "cpu_usage_thr" report respectively the average CPU usage of the process, current thread-group and current thread between 0 and 100 over the last polling loop. It varies very fast but can be useful combined with other rules to take actions on attacks. - "thread" and "tgroup" report the current thread number and thread group, may be useful in logs to understand load discrepancies. - The "set-timeout" action now covers the connect, tarpit and queue timeouts (on top of the ones already supported), so these can be driven dynamically from rules -- e.g. generic defaults with map-driven, application-specific overrides -- instead of being hardcoded per proxy. - the "do-log" action accepts "profile <name>" to pick the log profile. 7) Lua ------ - "tune.lua.openlibs" selects which default Lua libraries are loaded at boot. Since we don't actually need to expose e.g. os.xxx(), you can now host Lua much more securely by removing everything non-essential, typically removing syscall and FS access from untrusted scripts. - initial support for Lua 5.5 (it builds; the extent of testing is still limited). We fixed the makefile at the last minute to properly search for it and figured that it could mixup includes and libs from different versions on distros featuring only the oldest ones in a named directory. This was addressed but please report it if you spot any build failure. 8) Management / Integration --------------------------- - Reusable health checks: a new "healthcheck" section holds check rules that multiple servers share via the new "healthcheck" server directive, letting different servers in a backend run different checks (e.g. advanced on most important servers, light on backup/extra servers). Health checks can now also send a unique-id. - The default systemd unit file supports a "conf.d" directory (defaults to /etc/haproxy/conf.d, and will be mandatory at startup with that unit file). You don't have to move existing configs; the current main file is still used. This helps distros keep process-wide sections (global, peers, traces, logs...) central and one application per file. - "chroot auto" creates an empty chroot on the fly (create the directory, enter it, remove it, chroot there), guaranteeing an empty dir with no "." or ".." and nothing writable inside, and removing the need to know an existing empty path... one less filesystem entry for packaging. (Switching to "chroot auto" by default is being considered for 3.5). - on Linux with CONFIG_USER_NS, unprivileged users can now chroot too, removing one reason why starting unprivileged was less secure. What happens is that if chroot() fails with -EPERM, we'll retry inside a user namespace. - "mysql-check" now supports the MySQL 8.0 authentication scheme via the "post-80" keyword, so MySQL 8.x servers are checkable again. - CLI / stats / observability: - CLI large payloads: dynamic payloads up to 128kB by default (configurable via "tune.cli.max-payload-size"), useful for large maps or certificates. The payload delimiter can be enlarged to up to 64 chars (e.g. a random sha256sum). - "show proc" is no longer truncated by the output buffer (it used to stop around ~202 processes). - "show fd" prepares for a future "show fd <tgid>/fd" form (for 3.5), so 3.5-dev monitoring scripts stay compatible with 3.4 to ease testing of 3.5 later. - The HAProxy version is no longer shown on the stats page by default (one less detail disclosed to anyone who can reach it), but you can re-enable it with "stats show-version" in the proxy delivering the page if your tools or checks rely on it or just if you've been used to look at the version to make sure a deployment was done (like I'm doing with haproxy.org since we run development versions). - Debugging: - command-line "-dKall" now also dumps the "userlist" section keywords. - request routing / LB: - For consistent hashing, server "hash-key" gained "id32" (use the full 32 bits of the ID instead of just 28 currently) and "guid" (hash on the GUID, convenient across large deployments). - idle connection sharing: "tune.idle-pool.shared" gains "full" to share idle connections across all thread groups (useful at low loads with many idle connections); this replaces "tune.takeover-other-tg-connections" which is now deprecated (introduced in 3.3 so shouldn't affect many users). - easier TLS captures via the new HAPROXY_KEYLOG_FC_LOG_FMT / HAPROXY_KEYLOG_BC_LOG_FMT env vars for the SSL keylog format. - smaller stuff: new Prometheus metric "haproxy_sticktable_local_updates" (stick-table update rate); thread-group count in "show info"; a separate "haproxy -vv" line for runtime-detected features (sorted); The "haproxy-reload" script was converted to POSIX-shell for easier integration. 9) Integrations and add-ons --------------------------- - OpenTelemetry: the long-awaited OTEL filter was integrated in its own repository, because the OTEL libraries pull in a huge dependency chain that we expect will initially require more frequent tweaks than we'll issue LTS releases. Also some of these components are already external (namely the otel C wrapper), so it was pointless to force it into the main repo. Check the detailed build instructions on: https://github.com/haproxytech/haproxy-opentelemetry It is still experimental: though latest versions no longer need "insecure-fork-wanted" (but the OTEL SDK still creates threads at boot time). It is meant to replace OpenTracing, which is now deprecated and will be removed entirely in 3.5. - "haterm": the venerable httpterm benchmark tool was rewritten on top of current master, both as an "haterm" frontend mode and a standalone "haterm" program (argument-based config needing just a port or two). It supports SSL, H1/H2/H3, automatic thread binding, zero-copy/splicing and even kTLS. It reaches millions of req/s and hundreds of Gb/s on a single host, making reproducible benchmarks cheap. It also offers developers a new way to stress the lower layers. 10) Troubleshooting / observability ---------------------------------- - Memory profiling is now refined by execution context (sample fetch, converter, filter, applet, CLI keyword group, ...), so an alloc function called from many places (e.g. deep in the SSL stack) shows distinct lines per context, making leaks easier to spot and understand. It has helped once already during -dev. - "set-dumpable" has a new "libs" option: HAProxy keeps all its dependent libraries in memory so a crash core contains them, and a "libs-from-core" tool extracts them afterwards. Only the core is needed, not the binary or matching libs. This will avoid multiple round trips between reporters and developers, and will be particularly convenient in the common cases of mismatched packages (crash after package upgrade but on old version), and with containers. Since we realized that it was convenient but users have not yet deployed it, a command-line "-dA" creates the same archive but at boot and into the specified file, allowing to post-produce that archive (assuming no package update happened since the last version that crashed). - Stream dumps (in "show threads" / watchdog output) now show the rule currently being evaluated and the current filter. 11) Development / build ----------------------- - build-time modularity started: "USE_TRACE=0" disables traces, reducing the smallest binary by up to ~10% -- useful for embedded/low-footprint builds. More USE_xxx options to disable big subsystems (H2, FCGI, SPOE, QUIC-while- keeping-QMUX-without-SSL, ...) are being considered for small deployments and some of them will likely be merged early in 3.5. - internal cleanups toward future modularity: the long hated stconn "app_ops" descriptors (carried since ~1.5) were finally removed, and with it, that "app_ops_embedded-that-we-never-know-exactly-when-it's- used-but-breaks-if-we-delete-it". This alone is a source of more long-term stability. - LB-algo declaration now uses a descriptor table instead of copy-pasted function pointers. This should ease addition and registration of new LB algos (or even experimenting with them). We're not yet at the point of just declaring them though, but not far. - SSL/QUIC reg tests were unified (written once per SSL version/feature combo and included from SSL/TCP or QUIC definitions), significantly increasing QUIC coverage. - certificate management cleanups: the "new/set/commit ssl cert" code was refactored for maintainability. - Internally the QUIC mux was renamed from "qmux" to "qcm" to avoid confusion with the protocol (the old "qmux" trace source still works). Note that those using traces for debugging may notice a change of the source name, but given that source file names also change between versions, this is not something new nor unexpected. - The "-dt" trace startup is processed slightly later (no visible effect) to allow registering traces at runtime or from Lua later. 12) Behavior changes and deprecations ------------------------------------- A few changes are worth mentioning since they're likely to be noticed: - Starting as root with no "chroot" directive now emits a warning. If that is really intended, use "chroot /" to acknowledge it and silence the warning (will be backwards-compatible). The goal here is to encourage users to secure their processes at least a little bit with what is easily available. - "tune.takeover-other-tg-connections" is deprecated, replaced by the new "full" value of "tune.idle-pool.shared". - OpenTracing is deprecated and emits a deprecation warning at boot. It remains available in 3.4 and will be removed in 3.5 (non-fatal notice in 3.3); OpenTelemetry is the intended replacement. - Empty arguments in the config file: the tightening that started in 3.2/3.3 continues, allowing to catch misspelled variables (e.g. a list of ACL patterns to match against and that matches nothing due to letter inversion in the variable name). They are now also caught in disabled ".if/.else" blocks. Double-check configs that rely on possibly-empty environment variables, and as usual, report any dead-end you might fall into. Oh and as every year I took this opportunity to declare 2.4 end-of-life, and 2.8 enters critical fixes status now. ... And that's about all I could gather! If I had to say all this, I would be thirsty now :-) A big thanks again to everyone who tested, reported bugs, helped users, operated CI and infrastructure, fixed docs and sent patches. The final third of this development cycle was more focused on stabilization due to an inrush of AI-assisted bug reports resulting in many fixes, which should result in this version being one of the cleanest and most reliable .0 over a number of releases. As usual, we'll see how long this claim lasts, but for this you have to deploy it. I already did (well it's 3.5-dev0 but they're the same). Please find the usual URLs below : Site index : https://www.haproxy.org/ Documentation : https://docs.haproxy.org/ Wiki : https://github.com/haproxy/wiki/wiki Discourse : https://discourse.haproxy.org/ Slack channel : https://slack.haproxy.org/ Issue tracker : https://github.com/haproxy/haproxy/issues Q&A from devs : https://github.com/orgs/haproxy/discussions Sources : https://www.haproxy.org/download/3.4/src/ Git repository : https://git.haproxy.org/git/haproxy-3.4.git/ Git Web browsing : https://git.haproxy.org/?p=haproxy-3.4.git Changelog : https://www.haproxy.org/download/3.4/src/CHANGELOG Dataplane API : https://github.com/haproxytech/dataplaneapi/releases/latest OpenTelemetry : https://github.com/haproxytech/haproxy-opentelemetry Pending bugs : https://www.haproxy.org/l/pending-bugs Reviewed bugs : https://www.haproxy.org/l/reviewed-bugs Code reports : https://www.haproxy.org/l/code-reports Latest builds : https://www.haproxy.org/l/dev-packages Willy --- Final changelog since 3.4-dev14: Amaury Denoyelle (10): BUG/MEDIUM: qmux: do not crash on too large record BUG/MEDIUM: qmux: do not crash on receiving an invalid first frame BUG/MINOR: qmux: reject too large initial record MINOR: mux_quic/flags: add missing flags BUG/MINOR: mux_quic: open an idle QCS on reset on BE side BUG/MINOR: mux_quic: fix BE conn removal on app shutdown BUG/MINOR: mux_quic: prevent BE reuse with an errored conn CLEANUP: fix comment typo BUG/MEDIUM: h3: fix MAX_PUSH_ID handling REGTESTS: add basic QMux tests Chad Lavoie (1): BUG/MINOR: mux-h1: H2 preface rejection doesn't update stick-table glitches Christopher Faulet (12): BUG/MINOR: tcpcheck: Check LDAP response to not read more data than available Revert "BUG/MEDIUM: dns: fix long loops in additional records parse on name failure" BUG/MINOR: mux-h2: Count padding for connection flow control on error path BUG/MINOR: cache: Fix copy of value when parsing maxage BUG/MEDIUM: mux-h1: Dup connection/upgrade value to parse it when making headers BUG/MEDIUM: htx: Fix headers rollback on partial copy in htx_xfer() BUG/MINOR: applet: Commit changes into input buffer after sending HTX data BUG/MINOR: mux-spop: Fix possible off-by-one OOB read in spop_get_varint() BUG/MINOR: http-act: Properly handle final evaluation in pause action BUG/MEDIUM: channel: Fix condition to know if a channel may send BUG/MEDIUM: vars: Properly eval set-var-fmt action for emtpy log-format string BUG/MEDIUM: stream: Don't use small buffer on queuing with a request data filter Frederic Lecaille (15): BUG/MINOR: qpack: Fix index calculation in debug functions BUG/MINOR: qpack: fix potential null-pointer dereference in qpack_dht_insert() CLEANUP: qpack: fix copy-paste typo in value Huffman debug string BUG/MINOR: qpack: fix sign bit mask in qpack_decode_fs_pfx() CLEANUP: qpack: fix copy-paste typo in value Huffman debug string for WLN BUG/MINOR: qpack: fix huff_dec() error handling in qpack_decode_fs() CLEANUP: qpack: move encoded macros to qpack-t.h to avoid duplication BUG/MEDIUM: quic: handle ECONNREFUSED on RX side BUG/MINOR: quic: Fix memory leak in quic_deallocate_dghdlrs() BUG/MINOR: quic: fix ack range node pool_free call passing wrong pointer type MEDIUM: quic: optimize HKDF operations by reusing per-thread contexts BUG/MEDIUM: quic: reset cwnd in slow_start on persistent congestion (cubic) BUG/MEDIUM: quic: reset consecutive_losses on exit from recovery period (cubic) BUG/MINOR: quic: update drs->lost before calling on_ack_recv Revert "MEDIUM: quic: optimize HKDF operations by reusing per-thread contexts" Ilia Shipitsin (4): CLEANUP: addons/51degrees: initialize variables MINOR: addons/51degrees: handle memory allocation failures CLEANUP: ncbmbuf: improve handling of memory allocation errors in unit tests CLEANUP: admin/halog: improve handling of memory allocation errors Maxime Henrion (2): BUG/MINOR: cache: fix cache tree iteration BUG/MINOR: startup: unbreak chroot with CAP_SYS_CHROOT Olivier Houchard (8): BUG/MEDIUM: cpu-topo: Enforce thread-hard-limit on policy BUG/MINOR: quic: Fix another buffer overflow with sockaddr_in46 MINOR: quic: Copy sin6_flowinfo and sin6_scope_id too BUG/MEDIUM: resolvers: Wait a bit before calling the xprt prepare_srv BUG/MEDIUM: qmux: Close connection on invalid frame BUG/MEDIUM: ssl: Make sure the alpn length is small enough BUG/MEDIUM: leastconn: Unlock the write lock on allocation failure BUG/MINOR: tasks: Increase the right niced_task counter William Lallemand (10): BUG/MINOR: ssl-gencert: validate SNI characters to prevent SAN certificate injection BUG/MEDIUM: lua: defer Lua VM initialisation to the first Lua config keyword REGTESTS: lua: fix tune.lua.openlibs in Lua reg-tests BUILD: addons: convert 51d addon to EXTRA_MAKE BUILD: addons: convert deviceatlas addon to EXTRA_MAKE BUILD: addons: convert WURFL addon to EXTRA_MAKE BUG/MEDIUM: lua: register hlua_init() as a pre-check to fix crash without Lua config BUILD: Makefile: put EXTRA_MAKE help at the right place CI: github: replace cirrus by a vmactions/freebsd-vm job CI: github: run illumos job weekly on Mondays at 03:00 instead of monthly Willy Tarreau (30): REGTESTS: quic: disable quic/ocsp_auto_update for now BUG/MINOR: threads: set at least grp_max when mtpg is too small BUG/MEDIUM: threads: ignore max-threads-per-group when thread-groups is set CLEANUP: thread: indicate when max-threads-per-group is ignored MINOR: cpu-topo: notify when cpu-policy is ignored due to other settings MINOR: thread: report when thread-groups or nbthread results in less threads BUILD: makefile: include EXTRA_MAKE in the .build_opts construction DOC: internals: clarify ambiguous wording in core-principles DOC: internals: add a threat model definition DOC: add security.txt describing how to report security issues DOC: security: also add a note to exclude dev/ and admin/ MINOR: deinit: release the in-memory copy of shared libs MINOR: debug: add -dA to dump an archive of all dependencies BUILD: makefile: search for Lua 5.5 as well DEV: dev/gdb: improve ebtree pointer handling DEV: dev/gdb: add simple task dump DEV: dev/gdb: add simple thread dump DEV: dev/gdb: add fdtab dump DOC: config: add a few more explanation in http-reusee regarding sni-auto BUILD: makefile/lua: use the system's default library before all other variants BUG/MINOR: haterm: do not try to bind QUIC when not supported BUG/MINOR: haterm: also apply the tcp-bind-opts to clear TCP "bind" lines CLEANUP: haterm: do not try to bind to SSL when not built in MINOR: haterm: enable ktls on the SSL bind line when supported BUILD: makefile: fix build error with GNU make 4.2.1 and /bin/dash BUG/MINOR: jwe: don't write randoms past MAX_DECRYPTED_CEK_LEN in RSA_PKCS1_PADDING BUG/MEDIUM: chunk: do not rely on small trash by default for expressions CLEANUP: map: always test pat->ref in sample_conv_map_key() DEV: patchbot: prepare for new version 3.5-dev MINOR: version: mention that it's 3.4 LTS now. ---

