Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creating custom cowboy_protocol to deal with proxy protocol #708

Closed
khia opened this issue May 30, 2014 · 13 comments
Closed

Creating custom cowboy_protocol to deal with proxy protocol #708

khia opened this issue May 30, 2014 · 13 comments

Comments

@khia
Copy link

khia commented May 30, 2014

We use cowboy in combination with sockjs library on aws. We need to find out a client's IP address. However ELB cannot provide it in websocket case. Unless we use proxy protocol. Basically what that protocol does is adding single line before the request. We don't want to reimplement the equivalent of cowboy_protocol.erl. We want to extract first line store it in middleware env for example (ideally we want to put it in http header but this is hard to achieve at this stage of request parsing). We want to pass the rest of the request back to existent cowboy_protocol.erl. Since init of cowboy_protocol calls ranch:accept_ack(Ref) we cannot do Transport:recv from our protocol wrapper module. Since init of cowboy_protocol is blocking and wait_request is private we cannot pass the reminder of a request to cowboy_protocol.
What would be the best way to achieve the goal of supporting proxy protocol?

@codmajik
Copy link

i needed this for stud a while back so i implemented in my fork.
you should check it out @ https://github.com/codmajik/cowboy/blob/master/src/cowboy_protocol.erl#L191

I implemented both proxy v1 and v2 (binary)

btw I haven't merged with upstream changes in a while (If needed I can quickly do it).

@essen
Copy link
Member

essen commented May 30, 2014

parse_request is exported specifically so you can do that.

@khia
Copy link
Author

khia commented May 30, 2014

@essen parse_request expects state record which is private for cowboy_protocol.erl.
If init/4 would just do ranch:accept_ack and return state and then the caller of the protocol would start processing through parse_request it would solve the problem. But in this case all users of cowboy_protocol.erl need to aware of this two stage initialization.

@essen
Copy link
Member

essen commented May 30, 2014

Of course it's private. But it doesn't stop you from passing the required tuple directly or copying init in your code.

@khia
Copy link
Author

khia commented May 30, 2014

I'll use one of the proposed approaches, thank you. @essen feel free to close the issue.

@essen
Copy link
Member

essen commented Jun 2, 2014

Closing then, thanks!

@essen essen closed this as completed Jun 2, 2014
@ghost
Copy link

ghost commented Mar 18, 2015

Hi Khia, Essen,
I'm running into this exact problem now. So what do I have to modify exactly? the cowboy_protocol.erl file? Khia, anything you can share?
Thx

@essen
Copy link
Member

essen commented Mar 18, 2015

You have to create your own protocol that parses the beginning and then calls cowboy_protocol:parse_request.

@ghost
Copy link

ghost commented Mar 18, 2015

Got it, thanks.

@ferd
Copy link
Contributor

ferd commented Mar 18, 2015

For what it's worth, Heroku has a Ranch transport we use in production with cowboy for proxy protocol support: https://github.com/heroku/ranch_proxy_protocol

@ghost
Copy link

ghost commented Mar 18, 2015

Excellent, thanks Fred.

@comtihon
Copy link

@ahmadster @ferd
Hi! Is starting cowboy with {ok, _} = ranch:start_listener(client_handler, Acceptors, ranch_proxy, [{port, Port}], cowboy_protocol, [{env, [{dispatch, Dispatch}]}]) is enough for ranch_proxy to make this scheme working? I have the same case, as TS.

@ferd
Copy link
Contributor

ferd commented Oct 16, 2015

yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants