mtrudel / bandit

Bandit is a pure Elixir HTTP server for Plug & WebSock applications
MIT License
1.67k stars 80 forks source link

The Proxy Protocol for Bandit? #379

Closed lawik closed 2 months ago

lawik commented 2 months ago

Hey

Had a very good time today spelunking through and trying to get this done but in the end I have to concede I should maybe do it some more boring and simple way. But I think this is a valid feature request and something to have on the radar:

The Proxy Protocol Particularly Version 2, the binary one.

Born at haproxy but used here and there. For example, Fly supports it.

Cowboy/Ranch has it (via this library)[https://github.com/heroku/ranch_proxy_protocol]

When building NervesCloud and using device certificates we need to pass TLS straight through Fly so they can't add the original IP as a header because it is all encrypted traffic. So the option they can offer is to add the information via PROXY protocol and then the terminating app needs to know how to do it.

I started poking at it via a mix of a transport_module and a handler_module. The tricky part is the sneak-peak Bandit already takes on the wire with InitialHandler is pretty much what this would also need.

Essentially:

Suddenly, connection data flows once more :) Let me know if you have questions.

I got it to parse in a transport, but handing that off to a handler was a lot of pain and all I wanted was to get back to the default Bandit handlers.

lawik commented 2 months ago

If this is welcome I think I could take a decent first run at a PR from what I hacked on earlier today. But I think it does better being in Bandit than trying to wire it up from outside. And I have no idea where the right place for the resulting information is so it becomes accessible in the app later :)

mtrudel commented 2 months ago

I'm conflicted here. I'm of a pretty strong conviction that the Thousand Island / Bandit stack only considers published (and ideally non-deprecated) RFCs; I've been taking this position since the beginning. So, an adhoc standard such as this isn't really something I want to consider for inclusion in the stack itself.

However, I also think it's a thing that should exist and I'd love to see it happen; I just don't think it belongs in the core stack. I'm happy to help with this where possible, but I have a fair bit of ongoing work in the core stack that precludes me from helping much in terms of actual implementation.

As a plan of attack, you should be able to do this with a custom transport protocol in Thousand Island (one which you could / should publish as an add-on module in the same spirit as heroku's ranch add-on above). A custom transport_module that knows how to answer the relevant peer / local functions in the context of the proxied connection should plumb through fine and 'just work'. A sketch would look like this:

You ought to be able to use this to power any thousand island app (including Bandit) just by specifying it as the underlying transport_module (and optionally any transport_options needed to configure the proxy connection's underlying transport).

Does this make sense?

lawik commented 2 months ago

Oh, I agree if doable it works best outside of the core parts :)

I managed tor oute around the need for now so won't be doing it currently, may run into it again in a few months or so. Closing and will revisit if needed.