The kernel fast path
A plain TCP or UDP passthrough gains nothing from a proxy in the middle. Where a service is only that, SSLB3 hands it to nftables or IPVS and keeps the work only it can do.
Without it, SSLB3 accepts a connection, opens a second one, and copies bytes between them — two sockets and a pair of buffers per connection, to do what the kernel already does. With it, the packets are forwarded by the kernel and SSLB3 supervises: health checking with real semantics, deciding which backends exist, reconciling that against what the kernel holds, and reporting all of it.
Two decisions, not one
Confusing them is how an operator ends up believing a setting did nothing. Which services move is SSLB3's decision, from configuration alone. Which facility forwards is the helper's, because only the helper can see what the kernel actually has.
Which services move
Every condition must hold. Each corresponds to something SSLB3 can only do from inside the path, so failing one is not a limitation to work around — it is the feature that would otherwise be silently removed.
In an HTTP ingress the answer is usually none of them, and that is correct: anything terminating TLS or parsed by the HTTP module stays where it is by definition. What moves is the layer 4 services — an L4Ingress, or a listener configured with Layer7Module = none.
Every listener's verdict is reported whether or not the fast path is on. Read that before changing anything: it answers "which of my services would this actually move" without moving any of them.
Which facility forwards
auto prefers IPVS because IPVS is a load balancer: a service handed to it keeps a real scheduling algorithm and reports connections and bytes in both directions. nftables forwards correctly but distributes by an incrementing counter and can only count connections.
"Nothing forwards" is an ordinary answer, not a failure. It is what a host without the modules reports, what a container without the capability reports, and what every platform but Linux reports.
Availability is asked, not assumed
IPVS is detected by a generic netlink family lookup. nftables by a generation request and a throwaway nat chain, created and removed — because whether nf_tables answers is not the same question as whether it can make the chain this needs. A kernel can have one without the other, and a container can be missing the capability while the socket opens perfectly well. Both would otherwise be reported as usable and fail at the first rule.
The source rewrite
Neither forwarder rewrites the source on its own. Without one the backend sees the client's address and answers the client directly — and the client discards a reply from an address it never spoke to, so the connection hangs rather than failing. So SourceNat is on by default, and the reply comes back through this host.
Turn it off where the backends already route their replies back here — a classic director with the real servers behind it — because there the rewrite does nothing except hide the client's address from a backend that may need it. And for direct server return.
Source filters travel with the service
An allowSourceRange or denySourceRange becomes an nftables filter chain ahead of the forwarding. It has to: a forwarded connection is one SSLB3 never accepts, so a filter left behind would not be a slower filter — it would be no filter, and the kernel would carry exactly the addresses the configuration refuses.
text
table inet sslb3 {
chain prerouting-filter {
type filter hook prerouting priority -300; policy accept;
tcp dport 19001 ip saddr 10.10.10.10 counter packets 0 bytes 0 drop
}
}Rules are ordered most specific first, with deny ahead of allow at equal length — SSLB3 resolves by specificity while nftables resolves by rule order, and the ordering is what turns one into the other. A forwarder that cannot enforce a filter is refused the service rather than given it, reported as source-filter.
Intrusion detection is not offloaded
A farm whose connection detector is enforcing is never handed over — it is reported threat-enforcement and SSLB3 keeps serving it.
This is a deliberate limit, not an oversight. The block list could be expressed in the kernel — an nftables set with per-element timeouts is close to purpose-built for it — but the connection detector learns by counting accepts, and a forwarded service produces none. Enforcing the list in the kernel would apply the blocks already known and make that service invisible to the detector that maintains them, so no new abuser on it would ever be found. Offloading the enforcement would quietly switch off the detection.
What the counters mean
Neither forwarder counts the way SSLB3 does, and the differences are not cosmetic.
IPVS reports connections and bytes in both directions, all real. nftables reports connections only: its rules sit in a nat chain, so the byte figure it holds is each connection's first packet, and reporting that as traffic would show a few hundred bytes for a farm carrying megabytes. Its connection count is a floor rather than an exact tally — a client fast enough to reuse a source port reuses a conntrack entry, and the rule is not entered again.
All of them belong to the current rules and return to zero when a service is reprogrammed. They are read back from the kernel each pass rather than accumulated, so a helper restart does not invent history.
Host requirements
The helper reports what is missing and declines the facility rather than programming rules that would silently drop traffic.
In Kubernetes
/proc/sys is read-only in a container, so the helper cannot set those switches itself. ip_forward is inherited from the node and usually already on; net.ipv4.vs.conntrack is per network namespace with a hard default of 0 and is not inherited, so setting it on the node does not reach a pod.
config.fastpath.privilegedSysctlInit runs a privileged init container that sets them in the pod's own namespace and exits — the same shape OpenSearch uses for vm.max_map_count. It is off by default because PodSecurity baseline and restricted reject a privileged container outright, and defaulting it on would stop the chart installing at all on a cluster enforcing either. Leaving it off is a good answer: nftables forwards correctly and needs neither switch.
Where the privilege lives
SSLB3 holds no capabilities. Netlink needs CAP_NET_ADMIN at every call rather than once at startup, so a balancer that programmed the kernel itself would keep it for life — and that balancer runs Lua, terminates TLS and parses requests from strangers. It drops every capability at startup and verifies it cannot regain them.
A separate helper does the netlink work over a Unix socket: no Lua, no TLS, no request parsing, no network listener. What a compromised balancer can ask of it is the list of ports to forward, what is being forwarded, and to remove it all.
Teardown happens three times, because the one that matters is the one that did not happen: at startup before anything is created, when the balancer disconnects, and on shutdown.