Subscriptions-transport-ws: Secure Websocket connection establishment failing -- AWS ALB + Docker

Created on 21 Mar 2018  Â·  3Comments  Â·  Source: apollographql/subscriptions-transport-ws

I'm trying to get a simple Meteor project working with SSL but having trouble with wss connections using subscriptions-transport-ws. I'm wondering if anyone in this community has experience working with ssl through a AWS application load balancer in front of a Docker container running a Meteor app on EC2. All works fine without ssl and the ALB so I assume I'm doing something wrong when defining the rule for forwarding wss requests to the correct port on the instance OR there is an issue with this package and secure websockets?

The websocket port we've defined is 5000. The error I'm seeing is

Websocket connection to .... failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED

Specifically we are deploying a Meteor app with Meteor-Up to a Docker on EC2. We are using _subscriptions-transport-ws_ for the websocket server wrapping Node's http server. The GraphQL URL defined on the client is "wss://foobar.com:5000/graphql". Everything else is the same as it was in the working project without ssl at the code level.

Any help would be much appreciated. Thank you!

help wanted help-wanted

Most helpful comment

Hello @leshane. Good chance is, you already solved your problem, but in case you didn't, i'll throw couple of aws specific points since i'm successfully running wss powered by node behind ALB.

Since you mentioned it worked before ssl + alb, i am guessing you previously ran meteor bound to port 5000 on a host and had domain direct to host's IP.

It's quite a different with ALB:

  1. You run server on a host, binding to host's IP, eg 5000
  2. You add a http/instance target group 'METEOR' (standard TG port 80 here). You register your instance in this TG, and when adding instance, change port to 5000. This way, TG points to whatever your server is exposing on 5000
  3. You have Application load balancer with a https listener and serve certificate here. Typically you would have https listener under port 443. You add rule to your listener, eg when path is /graphql, redirect to 'METEOR' TG.
  4. You alias your domain to point to ALB host

In this scenario, you would connect to wss://foobar.com/graphql. If you want your server to be responding with ssl under port 5000, you need to add port 5000 listener in step 3, instead of regular 443.

There is another complexity layer with server in docker being able to listen to one port, but that port being bound to different one in host, but since you successfully ran that inside docker, i don't think this would matter here.

All 3 comments

Are you using classic ELB? It doesn't have WebSocket support, try using newer Application Load Balancer instead, which comes with WebSocket support and Session Stickiness.

https://aws.amazon.com/elasticloadbalancing/details/#details

Application Load Balancer Network Load Balancer Classic Load Balancer
WebSockets ✔ ✔ x

Hello @leshane. Good chance is, you already solved your problem, but in case you didn't, i'll throw couple of aws specific points since i'm successfully running wss powered by node behind ALB.

Since you mentioned it worked before ssl + alb, i am guessing you previously ran meteor bound to port 5000 on a host and had domain direct to host's IP.

It's quite a different with ALB:

  1. You run server on a host, binding to host's IP, eg 5000
  2. You add a http/instance target group 'METEOR' (standard TG port 80 here). You register your instance in this TG, and when adding instance, change port to 5000. This way, TG points to whatever your server is exposing on 5000
  3. You have Application load balancer with a https listener and serve certificate here. Typically you would have https listener under port 443. You add rule to your listener, eg when path is /graphql, redirect to 'METEOR' TG.
  4. You alias your domain to point to ALB host

In this scenario, you would connect to wss://foobar.com/graphql. If you want your server to be responding with ssl under port 5000, you need to add port 5000 listener in step 3, instead of regular 443.

There is another complexity layer with server in docker being able to listen to one port, but that port being bound to different one in host, but since you successfully ran that inside docker, i don't think this would matter here.

@leriel : Thank you for the detail explanation. I am facing similar issue.

I am using aws-alb-ingress-controller and ingress service something like this

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ template "pd.frontend.fullname" . }}
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: {{ .Values.ingressScheme }}
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
    alb.ingress.kubernetes.io/certificate-arn: {{ .Values.external.acmCertificateARN }}
    alb.ingress.kubernetes.io/inbound-cidrs: {{ .Values.ipWhiteList }}
spec:
  rules:
    - host: app.{{ .Values.domainName }}
      http:
        paths:
          - path: /*
            backend:
              serviceName: {{ template "pd.frontend.fullname" . }}
              servicePort: 80

it is working fine but now we are adding websocket(subscriptions-transport-ws) to our application.

Could you help me with any document or sample how can I implement the changes. Thanks again

Was this page helpful?
0 / 5 - 0 ratings