Elektrine lite

← Feed

@patrick@retro.social

Post #2018740

2026-05-02 09:52 UTC

I built a TLS router that forwards connections based on SNI (Server Name Indication). That means, it accepts TLS connections (like https), checks the desired target hostname, then forwards the encrypted stream to the backend that's configured for the hostname. It hands off the actual forwarding task to the Linux kernel via eBPF, which makes this a zero-copy operation. As a result, services behind the router are _noticably_ snappier than with the userspace based solutions (that copied the incoming data to userland, copied it from one socket to the other there, back to kernel for further distribution) that I used until now. Through that, it keeps the client's IP address visible to the client natively instead of fronting everything with the proxy's address. As a convenience, it can figure out the backend by docker/podman container name, removing the need to "expose" the ports through docker/podman own infrastructure (which is, again, a copy via userspace in some scenarios), including figuring out the new IP address on container restarts. Other implementations parse out the TLS records manually, trying to get to the SNI data in the ClientHello record with the least amount of effort possible. In contrast, my router uses the Go TLS library, which should make it generally more robust and future proof, given that the library is in use in much more critical scenarios than mine. It also means that ECH (Encrypted ClientHello) should work to hide the target domain name from the outside world (the router still needs the private key used for ECH to figure out routing, but even with that, it still can't read the data stream itself). That said, I don't have the ECH setup to test it, so that's more of a theoretical option for now. It runs on my personal infra and makes Jellyfin much snappier, and I'll roll it out to more servers that I maintain as I gain confidence that it's robust enough. Still cleaning up the code, but I'll release it as Free Software sometimes soon. #freesoftware #Linux #networking

Replies (4)

  • @patrick@retro.social 2026-05-03 21:36

    There it is: https://codeberg.org/pgeorgi/SNappI GPL-2.0, the setup is still a pain (ip link commands, manual nft setup), but WorksForMe™ There's an example config in doc/ and I hope the format is somewhat understandable.

    Open ##2019970

  • @yala@degrowth.social 2026-05-02 18:46

    @patrick Nice! Is that also compatible with rootless Podman pasta network stack in userspace? Docker/Podman has me believe this means the rootful variant, where actual network interfaces come into play.

    Open ##2019981

  • @jamey@toot.cat 2026-05-02 18:59

    @patrick I'm happy to see another SNI middlebox! I like the concept; I wrote about the advantages a few years ago: https://jamey.thesharps.us/2020/04/24/most-general-reverse-proxy/ How are you using eBPF to make the client address visible to the backend? I had looked into that but it seemed like the best I could do was passing SKBs from one socket to another, which I thought wouldn't carry the remote address info along. I also considered using Unix socket file descriptor-passing, but then needed some way to peek at the initial part of the stream without consuming it, and also would have needed to modify backends to get incoming sockets that way instead of by calling accept. So I'd love to hear how you apparently got the best of all worlds!

    Open ##2019984

  • @kevin@mastodon.km6g.us 2026-05-02 20:45

    @patrick This would replace a bunch of NGINX in my network that are just plain reverse proxies, although it sounds like it would require the backend to also terminate TLS and some of my devices can't do that.

    Open ##2019986