daguej / node-proxywrap

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

TLS/HTTPS Support #4

Closed ach closed 11 years ago

ach commented 11 years ago

We are using SSL for internal encryption behind ELB with ProxyProtocol. I have tested both tls and https but this module isn't working for either.

I have made some progress in setting up a tls-server and parse the socket with https://github.com/racker/node-proxy-protocol. Using this method, I get one raw-socket for each request but I have not been able to complete the chain and bind it to node.js http-module.

Has anyone tried to implement support for HTTPS/TLS backend with this or any other libraries?

daguej commented 11 years ago

This should work just fine with a HTTPS server -- in fact, that's exactly how I use it. The only thing this module really does is process the first ~50 bytes (up to the first CRLF) and then hands off the incoming data to whatever was originally listening. It is completely agnostic as to what protocol is used after that.

Are you sure your ELB is configured correctly? It should be TCP 443 -> TCP. It should not be in HTTPS mode -- you should not have uploaded any certificates/keys to the ELB.

Finally, make sure you've properly enabled PROXY on your ELB. If the first five bytes are not PROXY, the connection will be dropped.

ach commented 11 years ago

I confirm that it is working if you use TCP as internal protocol. However, my question is if someone has succeeded if SSL is used. My configuration is SSL 443 -> SSL (internal port), the reason for using SSL internally is for high security as sensitive data is tunnelled.

A guess is that the appended header is encrypted by ELB and cannot be read at the stage this library hook up the socket. But as both SSL and HTTP are at Application Layer, this might not be a correct assumption.

daguej commented 11 years ago

Your configuration doesn't make sense. You're terminating SSL at the load balancer, then re-encrypting your connection to the EC2 instance (I think). This actually costs you performance, and the ELB could just insert X-Forwarded-For headers anyway.

Instead, you should just do a full passthrough of the SSL stream. (TCP -> TCP) Data will be encrypted all the way to your server. Your sever will handle decryption and the PROXY headers will be sent correctly by the ELB.

Alternatively, if you want to do SSL decryption (termination) at the ELB, there's really no reason to encrypt the connection between the ELB and the EC2 instance. Amazon has certified that your traffic inside AWS cannot be intercepted by third parties. For this configuration, you'd do HTTPS -> HTTP, and then there's no need for this library since the ELB will insert the X-Forwarded-For header.

ach commented 11 years ago

Your assumption regarding the setup of SSL termination and internal SSL to the EC2-instance is correct. The main reason for investigating this setup is for PCI-DSS Certification telling a requirement of all traffic between machines MUST be encrypted. I don't know if the standard take in consideration hosting supplier telling "Traffic between ELB and EC2 instances are safe from third parties", but that is worth looking up.

The reason for using TCP and not HTTP ELB is for WebSocket support which is not supported using HTTP(S) ELB.

daguej commented 11 years ago

I've had to deal with PCI compliance before, so I've researched this exact issue. PCI DSS § 4.1 only requires encryption when data is transmitted over "open, public networks." Traffic between machines on a private network does not fall under this requirement. Traffic inside AWS qualifies as a private network (AWS is PCI Level 1 certified), so it's not required to encrypt between an ELB and EC2 instance.

Regardless, none of that solves your technical problem of WebSockets not working when the ELB is in HTTP mode. For this to work correctly, you must configure your ELB for TCP -> TCP.

It's important to realize that the ELB's protocol configuration has less to do with the protocols you're actually using and more to do with the protocol you want the ELB itself to speak.

We want the last option. The ELB should not touch the bytes coming though; it should just pass them to your EC2 instance (after adding PROXY headers). This allows the proxywrap library to properly parse the PROXY headers, then allows you to do SSL decryption in node and handle WebSockets correctly.

ach commented 11 years ago

If SSL between ELB and EC2 instance isnt nesseccary for PCI-compliance as you write, I would say that SSL->TCP LoadBalancer is the best solution for performace as EC2-instances will not drain in slow SSL-termination (Especially nodejs-applications). This is described in a blog post: http://blog.cloudparty.com/2013/09/30/efficient-load-balancing-and-ssl-termination-for-websockets-and-node-js/

I have tested SSL->TCP ELB with Proxy protocol enabled and can confirm the setup to work just fine. Thanks for the imput regarding PCI-Compliance and private networks.