daguej / node-proxywrap

Wrap node's Server interfaces to be compatible with the PROXY protocol
48 stars 36 forks source link

Source Protocol #7

Closed mateusz- closed 10 years ago

mateusz- commented 10 years ago

Hi, I need to be able to determine the originating protocol. There is no way to currently do this with proxywrap, correct?

daguej commented 10 years ago

Please clarify what you mean by "determine the originating protocol" -- I'm not quite sure what you mean.

mateusz- commented 10 years ago

Thanks for the quick response.

I mean, the protocol used between the client and the load balancer.

On AWS, I have a load balancer listening on 443/SSL, the instance is 80/TCP. Trying to determine the protocol with req.protocol produces "http" in both scenarios. Is there any way to get around that?

mateusz- commented 10 years ago

To clarify what I meant further, by "both scenarios" I mean, 80 / TCP on the load balancer => 80 / TCP on the instance and 443 / SSL on the load balancer => 80 / TCP on the instance. The load balancer is configured to serve the SSL certificate. As far as the application is concerned, requests coming through 443 and 80 on the load balancer are "http", which may be problematic.

daguej commented 10 years ago

OK, I see. If you're doing SSL termination at the ELB, the bytes that node gets are identical for TCP and SSL; there's no way to determine whether they were originally encrypted. Thus, all node will ever see are plain bytes, and the http module will set req.protocol to http.

However, it is possible for you to override this behavior based on port information.

There are two approaches:

  1. Listen on two ports in node and from ELB forward connections that were originally plain TCP to one port and those that were SSL to the other port. Then write some logic in your app to overwrite req.protocol based on which node port the request was routed to.
  2. proxywrap currently ignores the PROXY protocol's destination (in this case, the ELB's public) IP and port information. I could add additional properties to the socket with the destination information, and you could use that information to overwrite req.protocol.

I'm going to do the latter at some point soon (it's actually a long outstanding feature request), but you can do the former immediately as a quick workaround.

mateusz- commented 10 years ago

Thanks. Yes, number one should work. Haven't thought about that.

What about X-forwarded-proto header? Could that be used, or is it not available?

daguej commented 10 years ago

By design, the PROXY protocol is unaware of the application protocol that it wraps. That means we can't touch HTTP headers.

If you use the ELB in HTTP/HTTPS mode (rather than TCP/SSL), it is aware of the application protocol and inserts X-Forwarded-For and X-Forwarded-Proto headers for you. When you're dealing with HTTP in AWS, there's really only two reasons to run in TCP mode and use this module instead of running the ELB in HTTP mode:

mateusz- commented 10 years ago

Thanks for your explanation.

I'd like to use websockets with ELB which is why I am looking into this.

I will proceed with using @sadasant pull request as it's cleaner than listening on multiple ports.

Thanks again!

daguej commented 10 years ago

Warning: I'm not going to use that PR. It overwrites information that might actually be useful.

I'm going to add new properties with the PROXY destination information.