4 ms·
> Speaking of which, it'd be nice to make the TLS end-to-end: from the user through a proxy that doesn't decrypt all the way to the application server. But I'm
by anderspitman 5y ago
> Speaking of which, it'd be nice to make the TLS end-to-end: from the user through a proxy that doesn't decrypt all the way to the application server. But I'm not sure what the state of the art there is. It used to be possible to dispatch based on the SNI traffic and then proxy at the TCP level, but I know TLS 1.3 added encrypted SNI. Not sure if the proxy can force clients fall back to non-encrypted SNI. I could imagine the spec authors making a point of not allowing this so a man-in-the-middle can't find the intended host. Maybe the two legs just have to be encrypted separately now.
My boringproxy[0] project has a mode for doing SNI routing at the reverse proxy, and tunneling it all the way back to a local client machine which handles the actual TLS termination. The client also gets certs automatically from Let's Encrypt. So you end up with automated end-to-end encryption where the boringproxy server/VPS can't decrypt any of the traffic.
Early versions of boringproxy acted as a more traditional reverse proxy, terminating the TLS at the server then making a new HTTP request upstream. Eventually I added the ability to move the HTTP proxy into the client to enable e2ee. Most recently I implemented raw TLS all the way. There are tradeoffs:
Pros:
* End-to-end encryption.
* Simplicity. You just need to peek at the SNI and look up what TCP tunnel to pipe into.
* Things like WebSockets and other hop-by-hop requests don't need to be implemented by the proxy.
Cons:
* You lose the ability to do compression/caching/CDN/etc at the server.
* You can't support new protocols like HTTP/2, HTTP/3, etc at your server because it only understands TCP wrapped in TLS.
In practice, I think these tradeoffs are totally worth it for self-hosting. I've found performance to be great for my purposes.
As for encrypted SNI (ESNI, now wrapped into encrypted client hello, ECH), I'm pretty sure it will be implemented in a tiered approach like you surmise. So in my case the boringproxy server will have the keys to decrypt the client hello, but the origin servers will still control the actual TLS decryption.
[0]: https://boringproxy.io https://boringproxy.io