SNI passthrough: route TLS by domain without terminating (L4 phase A) #2
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Execution tracker for Phase A of the L4 passthrough design.
Spec (source of truth): Obsidian —
Personal/Projects/edge-router/specs/2026-07-06-l4-passthrough-and-grpc-design.mdScope
Peek the ClientHello on the existing :443 listener, match SNI against a new
l4_routestable, and tunnel matching connections raw to their backend (copy_bidirectional) — TLS never terminated, so backend-owned certs and TLS-layer mTLS survive end-to-end. Non-matching connections fall through to the existing terminating acceptor unchanged.Independent value: front services that hold their own certificates without storing their keys; genuine end-to-end TLS for sensitive backends. First consumer: Playground's agent orchestration endpoint.
Key design points (from the spec)
server::Acceptorso bytes stay replayable (LazyConfigAcceptorconsumes the stream — wrong tool)l4_routestable +POST/GET/PATCH/DELETE /api/l4endpoints,[[l4_routes]]TOML parity, dashboard listingMust-pass test
rustls client presenting a client certificate → through passthrough → rustls backend requiring client auth: handshake succeeds, cert visible to backend. Plus: non-matching SNI regression, fragmented ClientHello, existing-behaviour regression suite.
Out of scope (later phases in the same spec)
mode='tcp')Phase A (SNI passthrough) complete — implemented across 13 tasks, each individually reviewed, plus a final whole-branch review. Pushed to
mainatfca0b42(19 commits from baseline4004265).Delivered: ClientHello SNI peek via rustls' sans-io
server::Acceptor, raw-byte tunnel (copy_bidirectional) preserving end-to-end TLS/mTLS, fulll4_routesREST API + TOML config parity, per-routemax_connectionslimiting, connection/byte metrics, a TLS-handshake health checker, and a dashboard section — plus the fragmented-ClientHello and mTLS-survival tests called out in the original design spec's "must-pass" cases.Two deliberate deviations from the spec, both confirmed before merging:
/api/services, not master-key-only.Non-blocking follow-ups filed as separate issues: #4 (route list re-queries the DB on every HTTPS connection — perf), #5–#9 (various minor polish/observability items).
Phase B (raw TCP forwarding) and Phase C (h2c/gRPC upstream) remain as documented next phases in the design spec, not started.