25

This doesn't seem to be working right now. I'm using Faye with NodeJS behind an Amazon ELB. When I switch on HTTPS the connections can no longer be brokered. I found a question here unanswered: https://forums.aws.amazon.com/message.jspa?messageID=283293 . Anyone able to get this working? Are there any work around outside of running my own instance of HAProxy?

Art
  • 5,864
  • 3
  • 30
  • 32

4 Answers4

42

I confirm, based on our own tests, that configuring ELB on TCP/SSL, instead oh HTTP/HTTPS, makes the trick with WebSockets. The drawbacks are two:

1) As already pointed by arturnt, you cannot get stickyness.

2) You will lose the ability to retrieve the identity of the clients. The originating IP seen by your WebSocket server will be always the ELB one and, differently from the HTTP/HTTPS configuration, no X-Forwarded-For header will be added to the requests.

UPDATE July 2013: Amazon has just added support for Proxy Protocol, which solves drawback number 2 above. With the Proxy Protocol, a header containing the client's originating IP is added even when ELB works at TCP level, rather than HTTP. Full details: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html

UPDATE August 2016: Amazon has just announced new AWS Application Load Balancer, which supports WebSocket at Layer 7 (as well as HTTP/2.0 and content-based routing). See https://aws.amazon.com/it/blogs/aws/new-aws-application-load-balancer/

Alessandro Alinone
  • 4,934
  • 2
  • 18
  • 22
  • Can WSS be used with the second option? – whadar Jan 15 '13 at 15:44
  • 1
    ...and there's [a module to deal with the PROXY protocol](http://stackoverflow.com/q/17981943/201952). – josh3736 Jul 31 '13 at 22:30
  • ...or a currently active [fork](https://github.com/findhit/proxywrap) of the above module. – jamix Apr 21 '15 at 12:32
  • The inability to use sticky sessions makes it impossible to effectively use ELB with websockets sine it needs to connect to the same instance each time which there is no way to guarantee. – Loourr Aug 16 '15 at 21:27
  • @loourr correct, I would like to see this actually working as we have been trying it out from some time now ... – Amit Kriplani Dec 14 '15 at 13:28
10

It won't work, the ELB's HTTP(S) proxy does not understand websocket requests, for now at least, and I don't know when/if it's planned.

I'm not sure HAProxy is completely necessary though. It should be possible to put an SSL terminator, e.g. stud/stunnel, on the same instance as your nodejs servers and pass through that way. You can then keep the ELB, but put it in TCP mode.

Obviously there's the SSL overhead on each instance, but in the long run that probably scales better than offloading the SSL to ELB (particularly based on users' comments on ELB's SSL performance).

James Little
  • 1,964
  • 13
  • 12
  • 1
    It is often more desirable to terminate SSL at the AWS ELB, if only so that renewing the certificate is easily performed in one place. It also means that potentially-vulnerable application code does not have access to the certificate. The downside, of course, is that communication between ELB and the application is unencrypted, but this can be mitigated with VPCs and hardened network security. – jokeyrhyme Aug 26 '14 at 22:24
4

After James' answer I did a little bit more research and ended up going to the TCP route, not sure there are any disadvantages of that over using the HTTP tunneling of ELB (considering I don't need stickiness). The good thing is that you don't need to do stud/stunnel since ELB provides that for you. So final ELB setup where NodeJS/Faye are listening on port 8000:

Secure TCP Forward (443) -> Local (8000)
TCP Forward 80 -> Local(8000)
Art
  • 5,864
  • 3
  • 30
  • 32
  • The downside is stickyness and the ability of the ELB to forward on a request to a different server if the current one it choose returns an error. – Zac Bowling Jun 05 '12 at 01:19
1

You could use Application LB to support websocket well. I just implemented this idea on our latest project after implemented some tricks on ALB:

  1. open 80 port on all related SGs
  2. make NodeJS running on 80
  3. enable NodeJS responding http-80 request (NodeJS will upgrade http request to websocket in the backend)
  4. make ALB target group check http-80 & correct ping path
  5. create listeners on ALB: http80->http80, https443->http80
  6. create listener rules on ALB: http80->target group, https443->target group
  7. Enable http stickiness in
Freman Zhang
  • 491
  • 6
  • 6
  • 1
    How did you configure the health check / ping path for this to work? – BrokenGlass Sep 16 '16 at 03:05
  • I ended up creating a separate, HTTP, endpoint just for health checks. According to the [docs](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html), "...health checks do not support WebSockets". – dskrvk Nov 26 '16 at 17:35
  • @dskrvk Where and how did you setup an endpoint for your health check? Are you running nginx for you ALB? I am in the same situation not running nginx and now sure what file I should serve for health check and what it should respond with? – jdog Feb 16 '18 at 04:22
  • I simply created another listener in my application (a Node.js HTTP server) that responded with a status 200 and a string "OK" (though the body can be empty). It can be anything really - either an endpoint you define in your application or a configuration block for your Apache or nginx webserver. – dskrvk Feb 18 '18 at 04:43