Fluxheim 1.5.19
Fluxheim 1.5.19 Release Notes
Fluxheim 1.5.19 moves the Fluxheim-owned load-balancer core into the internal
fluxheim-load-balancer workspace crate and includes security hardening found
during the v1.5.19 review cycle.
Security Fixes
- Fixed fallback proxy cache auth ordering so cache fallback handling cannot
run before the configured authorization decision. - Rejected ambiguous dot-segment proxy request paths before route selection,
route-local policy checks, cache keying, or upstream forwarding. - Treated incoming method casing as equivalent for route method filters so
lowercase HTTP/1 method tokens cannot miss method-scoped route policy. - Restricted accepted inbound request IDs to an identifier-safe alphabet so
URL-like or email-like values are regenerated before reaching logs, traces,
templates, or upstream headers. - Released response-compression output buffers after each emitted chunk while
preserving the cumulativemax_output_bytescap. - Made route prefix matching and prefix stripping path-segment aware so sibling
paths such as/repoadmincannot enter a/reporoute or rewrite to
unintended upstream paths. - Percent-encoded URI-special bytes in route regex capture substitutions before
applying rewrite templates, preserving slash-spanning captures while removing
raw matrix/userinfo/list delimiters from rewritten upstream paths. - Normalized
Set-CookieDomainandPathattribute values before response
rewrites, covering leading-dot domains, quoted attribute values, and trailing
ASCII whitespace so alternate cookie syntax cannot bypass configured rewrite
rules. - Hardened range slice-cache origin fill so dynamic-only upstream discovery
cannot fall back to the default loopback upstream, unsafe dot-segment origin
paths are rejected, and multipart range requests are bounded by range count
and response-wrapper overhead. - Resolved exact local-static purge identities through the same route rewrite
logic used by static serving, includingrewrite_prefix. - Applied decoded route matching to edge policy checks, closing mismatches
between encoded request paths and policy enforcement. - Preserved private cache-control directives for status-specific TTL handling
so restrictive origin cache headers are not weakened by cache policy. - Hardened PHP-FPM path handling by denying scripts after resolved-path
normalization and covering directory-index resolution under denied PHP path
prefixes. - Fixed proxy-only route decode feature wiring so shared path safety remains
available in proxy builds without cache. - Isolated upstream CA bundle material in peer reuse keys to avoid reusing
upstream TLS peers across distinct trust material. - Added a default stream proxy connection cap to avoid unbounded accepted TCP
stream connections. - Detached self-healing probes from public proxy traffic paths.
- Preserved restrictive PHP cache headers when PHP-FPM responses are converted
into Fluxheim responses. - Rejected PHP-FPM
PHP_VALUEandPHP_ADMIN_VALUEstyle ini-control
parameters so configured PHP params cannot rewrite php-fpm runtime policy. - Cleaned pending PHP request-body spool files on retry/error paths.
- Added
php.max_in_flight, defaulting to8, to cap concurrent PHP-FPM
requests before request body buffering and FastCGI dispatch. - Added
proxy.load_balance.passive_health.min_healthy_backends, defaulting to
1, so passive outlier ejection cannot fail-closed an entire load-balanced
pool by default. Operators can set it to0to retain strict fail-closed
passive-health behavior. - Hardened managed-cookie load-balancer persistence so invalid affinity
cookies no longer create server-side persistence-table entries, while newly
issued signed cookies immediately record one bounded table entry for the
selected backend so the next request remains pinned. - Rejected verified HTTP proxy upstream TLS configs that target an IP-addressed
upstream without explicitupstream_sni, preventing the Pingora connector
from falling into empty-SNI certificate-verification bypass behavior. - Hardened HTTP load-balancer discovery so private, loopback, link-local,
metadata, multicast, reserved, and documentation IP-literal backends are
rejected by default unless the operator explicitly enables
proxy.upstreams_http_allow_private_backends. - Added
proxy.downstream_read_timeout_secs, defaulting to 60 seconds, and
wired it into vendored Pingora HTTP/2 downstream request-body reads so
slow-body clients cannot hold proxy forwarding tasks indefinitely while
withholding DATA frames or END_STREAM. - Applied the downstream read timeout before PHP-FPM request-body collection and
drain paths, covering PHP routes that read the body before FastCGI execution
begins. - Revalidated managed PHP-FPM binary paths immediately before spawning child
processes and rejected symlinked binaries at config validation so local path
swaps cannot replace the supervised executable between reload and spawn. - Hardened downstream HTTP/2 flow-control defaults by capping per-stream send
buffering at 256 KiB, keeping DATA frames at 16 KiB, fixing the receive
window at 64 KiB, and reducing pending-accept reset-stream pressure. - Removed encrypted filesystem disk-cache fill heap amplification for the local
provider by committing streamed cache bodies through bounded AEAD chunks, and
bounded the OpenBao Transit whole-object fallback heap budget. - Hardened DNS-refreshed upstream discovery against DNS rebinding pivots by
rejecting private, loopback, link-local, multicast, reserved, documentation,
metadata, and unspecified resolved addresses unless
proxy.upstream_dns_allow_private_backends = trueis set. - Hardened HTTP and DNS discovery backend filtering by applying the IPv4
private address policy to IPv4-mapped and IPv4-compatible IPv6 literals
before they can be accepted as upstream addresses. - Hardened split-config trusted-proxy handling by extending
server.trusted_proxiesfragments instead of replacing the main list, and by
rejecting catch-all or near-global trusted-proxy ranges such as0.0.0.0/0
and::/0. - Hardened split-config proxy handling by applying field-level
[proxy]
fragment merges so a later timeout-only proxy fragment cannot silently clear
upstream TLS verification, auth request, mirror, or load-balancer policy. - Completed recursive split-config merges for
[proxy.auth_request],
[proxy.mirror], and[proxy.load_balance]so partial nested fragments
cannot reset established auth, shadow-traffic, persistence, health-check,
retry, or load-balancer selection policy back to defaults. - Hardened split-config handling for
[compression],[cache],
[cache_purger],[web], and[stream]so partial fragments cannot
silently drop previously configured compression limits, cache encryption,
static-file safety policy, or stream routes. - Hardened split-config admin handling by applying field-level
[admin]
fragment merges so a later ops-socket or health-only admin fragment cannot
silently disable the admin API or clear token and snapshot-store settings. - Hardened cache peer-fill request construction so peer lookups use the
selected vhost's canonicalHost, while client-controlledHostheaders
and absolute-form URI authorities cannot pivot peer requests to another
vhost. - Added an inbound peer-fill recursion guard so requests marked with
X-Fluxheim-Peer-Fill: 1cannot launch another outbound peer-fill fetch in
cyclic peer topologies. - Decoded percent-encoded cache bypass query names and values before comparing
bypass_query_paramsandbypass_query_values, closing encoded preview or
private-mode cache bypass evasion. - Aligned configured cache Vary request headers with the 16-field runtime Vary
cap and rejected effective origin-plus-configured Vary overflows at cache
admission instead of dropping variance. - Hardened auth-request response header handling so allowed auth response
headers cannot override Fluxheim's upstream request header policy on name
collisions. - Hardened auth-request forwarded context handling so allow-listed
X-Original-URI,X-Forwarded-For,X-Real-IP,X-Forwarded-Host, and
X-Forwarded-Protovalues are synthesized from Fluxheim's trusted request
context instead of copied from spoofable client headers. - Matched auth-request split
Cookiehandling to the origin request path by
joining repeatedCookiefields with;instead of,before sending
the authorization subrequest. - Hardened Unix admin-token and file-log opening by using rustix
architecture-correctNOFOLLOWflags instead of hand-coded constants. - Hardened trusted-proxy
X-Forwarded-Forparsing so any malformed hop rejects
the forwarded chain and falls back to the direct peer IP instead of silently
attributing traffic to a trusted proxy hop. - Normalized IPv4-mapped IPv6 client addresses before trusted-proxy,
access-policy, rate-limit, and GeoIP decisions so IPv4 CIDR policy also
applies on dual-stack listeners that report IPv4 peers as::ffff:.... - Restricted WebSocket-enabled proxy routes to the
websocketupgrade token so
valid but unrelated protocol upgrades such ash2care not forwarded to
upstreams. - Stripped HTTP/1
ConnectionandUpgraderequest headers when
proxy.websocket = false, preventing normal proxy routes from tunneling
upgraded protocols by accident. - Removed vendored Pingora upstream TLS underscore-to-hyphen hostname
verification rewriting so certificates are checked against the exact
configured SNI or alternative name. - Stripped client-controlled hop-by-hop request headers before forwarding to
upstreams, includingConnection-listed extension headers and non-WebSocket
Upgradevalues. - Hardened response
LocationandRefreshprefix rewrites so absolute URL
prefixes only match the intended authority boundary and cannot rewrite
userinfo-style URLs such ashttp://origin@evil.example/. - Rejected redirect templates that place
{query}inside the URL authority so
attacker-controlled query strings cannot turn operator redirect rules into
authority-changing redirects. - Hardened Host and authority normalization by rejecting percent signs,
consecutive dots, leading/trailing label hyphens, overlong labels, and
numeric-only final labels in DNS hostnames. - Hardened OpenBao Transit cache encryption calls by disabling HTTP redirects
and reading Transit JSON responses through a bounded buffer before parsing. - Hardened PHP-FPM path handling by rejecting protocol-relative directory-slash
redirects and decoded control characters in path-derived FastCGI params. - Hardened PHP-FPM TCP endpoint validation by rejecting unsafe IP literals and
requiringallow_private_tcp_upstreams = truefor loopback,
private/link-local IPs. - Rejected stream routes that enable upstream TLS certificate verification for
IP-addressed upstreams without an explicitupstream_sni, matching the HTTP
proxy validation rule and avoiding runtime hostname-verification skips. - Hardened traffic mirroring by rejecting unsafe mirrored paths/queries before
outbound URL construction and suppressing recursive mirror requests marked
withX-Fluxheim-Mirror. - Added stream route
allow_sourcesanddeny_sourcesIP/CIDR policies so raw
TCP stream listeners can reject unauthorized sources before connecting
upstream. - Hardened stream hostname upstreams against DNS-rebinding pivots by rejecting
private or reserved DNS answers unless the route explicitly sets
upstream_dns_allow_private_addresses = true. - Rejected horizontal tabs in configured static header values so operator
header policies cannot pass HTTP/1.x-only whitespace into HTTP/2 upstream
requests or responses. - Rewrote quoted
Refreshresponse URLs for configured prefix rewrite rules,
covering both single-quoted and double-quoted URL forms. - Hardened runtime file-log opening by rejecting symlinked log path components
immediately before creating or appending the log file. - Hardened
Accept-Encodingqvalue parsing so non-finite or malformed values
such asNaNandInfinitycannot influence compression negotiation. - Added
admin.ops_socket.require_bearer_tokenso local Unix ops-socket status
endpoints can require the same bearer token as the TCP admin control plane. - Required bearer-token authentication for
GET /_fluxheim/snapshotson the
Unix ops socket even when other read-only status endpoints are local-only.
What Changed
- Added
crates/fluxheim-load-balanceras the internal owner of load-balancer
backend snapshots, discovery adapters, active health checks, selection
algorithms, runtime policy overrides, persistence, queue policy, state files,
background task glue, and tests. - Kept root
crate::load_balanceras a compatibility shim so admin, proxy,
runtime, status endpoints, release profiles, RPM/container packaging, and
operator config syntax remain unchanged. - Preserved the existing
profile-load-balancer-edgeimage/profile and the
full build's load-balancer support. - Added narrow integration hooks for root-owned metrics recording and
compliance HMAC signing, avoiding a dependency from the load-balancer crate
back into proxy, admin, cache, web, or PHP internals. - Kept the load-balancer crate's tests with the code they review, including
selection, passive health, discovery, runtime mutation, persistence, and
database/protocol health-check coverage.
Compatibility
- Existing config files remain valid.
- Stream routes that use hostname upstreams resolving to private or reserved
addresses must now setupstream_dns_allow_private_addresses = truewhen
that resolution is intentional. IP-literal upstreams are unchanged. - Existing admin load-balancer status and mutation APIs remain unchanged.
- Existing feature profiles and release artifact names are unchanged.
- Existing RPM and container production feature sets are unchanged.
fluxheim-load-balanceris an internal workspace crate and is not published
to crates.io.
Not Included
- No new load-balancer features in this release.
- No removal of
pingora-load-balancingyet. - No removal of
pingora-cacheyet. - No cache, web, PHP, or HTTP proxy orchestrator crate extraction in this
release. - No production UDP/GSLB promotion, HTTP/3/QUIC, WAF, VPN/firewall appliance
behavior, Wasm/iRules/Lua runtime, or full Pingora HTTP proxy replacement in
this release.
Checksums And Signatures
- Commit:
c023072af80522f1ac452b56468b42044d43d501 - Local gate: GitHub CI green before tag; local release metadata checks passed
- CodeQL/code scanning: no open release-blocking alerts before tag
- Source archive checksums:
6f2885fa0e5523f5d85a240375026ee73471c83778b6657a2719c383df168856 fluxheim-1.5.19.tar.gz8b33b7d64d1524d08575449db45bd51138cc99df6f6f07fcaed7794f9efc9e20 fluxheim-1.5.19.zip
- Binary checksums:
- x86_64:
7c9f28f36deb0799aa67021c1b6cc5e72d544dac780b86bb58c25bfd70a0baa9 fluxheim-1.5.19-full-x86_64-linux.tar.gz2ae793e9636034f7fc34d32ae040bd43868899c4a7e6998633cf3cae41da7593 fluxheim-1.5.19-cache-x86_64-linux.tar.gz0767357500b063a93d892c0596d07f97b69eded6d6cfe3177b193720194061eb fluxheim-1.5.19-proxy-x86_64-linux.tar.gz847dd0150616527807ddab4c83931226b3479981d310ab10c4a0ddcce4e2326e fluxheim-1.5.19-php-x86_64-linux.tar.gz8272b181754f48c83b71eea7110e3acf43f693a0a39e49c146e1944198ce2fe3 fluxheim-1.5.19-load-balancer-x86_64-linux.tar.gzb05df828b2df6663cbeb61c4c75c1810184068b054a1b62dd4f3f26fc3a554a3 fluxheim-1.5.19-config-tester-x86_64-linux.tar.gz
- aarch64:
5b679b6c152897fc8cb02e7165f335d3b7cb94fc990bf8e29656ce9608b5c627 fluxheim-1.5.19-full-aarch64-linux.tar.gz244d256d57a2bbd0e53be384327738c1d38284d626963814010249f8d0763b59 fluxheim-1.5.19-cache-aarch64-linux.tar.gz66f199561774fa3dfda2570383bf501153fd39342d6dbe7beb6b2610b812a3c2 fluxheim-1.5.19-proxy-aarch64-linux.tar.gz988b6b770e2698b5e01cf6f9c569e334667bcd6a9e60151e0bd34a709518891a fluxheim-1.5.19-php-aarch64-linux.tar.gz2b3812b38c52f795dc1544668ed3fdcedf9febca7912d3d286ee06a7db25a1ec fluxheim-1.5.19-load-balancer-aarch64-linux.tar.gzdd7c7b0a088fc0545804beee4e16509e302b2d21ad5bcf49e1d2d96111745750 fluxheim-1.5.19-config-tester-aarch64-linux.tar.gz
- macos:
6d961b53506e2b3961fd57bd6c16dd0af04f1edb828882c970938244ef17f43c fluxheim-1.5.19-dev-aarch64-macos.tar.gz
- x86_64:
- SBOM checksums:
8d1aadfd6f8bf313dec9f24b7f73cc76e1501aa035c7806b7a8b64e1e72e13c6 fluxheim.spdx.jsond2499d0440169122893ea9dee045ff100a0e55d0a22fd8ed57fc4535c9558e98 fluxheim.cyclonedx.json
- Reproducible build:
4b9eb7315cec85a10e3ca50270e762540b3e69a37894b6168ac635e18d74c669x86_64735b24b8ca8b5b54d113fa357923f81efaaf1e2e0c0c8423e539c399808c1aa5aarch64e6498738cb2794924394f71b7e3ad568c546a1a4524b6671eb1361a8a382ad57macos
- Full Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:89f72c7aaad412287c1461c6475bd15f4d7ad48504c02d05148712c01b93cad6 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:5518609d7b3ae41a4ffcd17996a43dc5e6e52dd9ee7376778e11945cdf3a3c27 - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:ed951bb848f0867c09ff82722a4af86b8955287e64a6e30ae1e6cfa491119fe3 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:affaa0dd2478beabc6043543670a764e75d9bcf09d680b87dd81a6a246384c37
- Wolfi:
- Cache Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:3a9bb2535fb8f0c6aa462ccaa7751618ef037fc303283f22b5242a84f51fb39e - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:4486a27d28b03d79a19023e4e73ecdd2c5e91a7fe22057a376720536211e6dc8 - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:0e45a8e8506f9a9db4bf3f7432b7b89d02570f231285c14a302a9c8323c163eb - Debian:
ghcr.io/valkyoth/fluxheim@sha256:bc6e76719666359516686d15766d8b0afb700c15731d34628a2457792bd7a067
- Wolfi:
- Proxy Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:00b7cef0322e24d00dd5ad0afecc853e9088518e7ef1c3a1c7024f2be2c2e05a - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:707fca2a2ec1084e9a9e9c95eb78b26d335ca365a3b14d028f4f1c7c59432d43 - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:51a2a83e2d64700c233c5546dc173f971655a8196bf6d5a42cb977ee6bc6a5c6 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:6453f14391a2ec2e65165fa3cc0b46caa7290db06f69bebc3e332ad942d91414
- Wolfi:
- PHP Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:6325764ccecdd28937eb93c7042d3aafcc87902a1d1319b31e912cfe64272e9f - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:50e918b5fe165e2734b67daeb209f02b273e1e3e51a85c743a415107f9f87589 - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:85a3b74c07e6ebe6f0816c117bba3332d3be6ddea78fb033246d704353349cbe - Debian:
ghcr.io/valkyoth/fluxheim@sha256:b186e9dfae9d3c85309be0c6dd4d6034946aec89588f7126602d7daf3211005f
- Wolfi:
- Load Balancer Build Container digests:
- Wolfi:
ghcr.io/valkyoth/fluxheim@sha256:3c18f897fbc7ed33a59e2ade2cc1b05ecf6d04015dc9e4e6fb07ef60fcc6cb00 - Alpine:
ghcr.io/valkyoth/fluxheim@sha256:47dff871329ba4d1322dc5b190243bc36155a10ea87d1f4186f1514cb9d9ce1e - SUSE Micro:
ghcr.io/valkyoth/fluxheim@sha256:7f28c0b0703d5b49d0c4617b29a9d5c1155005e039ddefd557faaf256d93f3d5 - Debian:
ghcr.io/valkyoth/fluxheim@sha256:772747290623df54ac6299843bd95e0ff4e158e0d9a36b74e28d2e91251034d3
- Wolfi:
- Tag signature:
Good "git" signature for 1921261+eldryoth@users.noreply.github.com with ED25519 key SHA256:EoLRQ5k4J5pYz3UMFmkrV798gYFNkToGS2xEPvebqB4