aws nlb socket.io ssl via copilot - amazon-web-services

Context
I'm trying to create a load balancer with AWS Copilot that runs socket.io instances.
Locally and in an HTTP environment, I can successfully connect to the socket instance via the load balancer (ws://{id}.elb.{region}.amazonaws.com:8080/socket.io/?EIO=4&transport=websocket).
Problem
When I'm in the HTTPS context and try to connect, it fails and I get the error message Error: Websocket error with no real error message or status code (wss://{id}.elb.{region}.amazonaws.com:8080/socket.io/?EIO=4&transport=websocket).
With ws:// everything works and in wss:// it does not work.
Code Snippets
AWS Copilot manifest.yml
name: websocket-service
type: Load Balanced Web Service
http:
path: '/'
healthcheck: '/health'
nlb:
port: 8080/tcp
Server
import {Server} from 'https'; // I use HTTPS here
// ...
this._io = socketIo(server);
// ...
Client
// ...
const client = socketClient(url, {
transports: ['websocket']
});
// ...
AWS Console
EC2 -> Load Balancing -> Load Balancers -> {target} -> Listeners

Related

Strapi AWS Elastic Beanstalk - Deploy success but cannot access URL

I'm trying to deploy Strapi 4 to AWS elastic beanstalk.
After deploying, the app is not accessible by the URL (e.g http://lrd-api.ap-southeast-1.elasticbeanstalk.com).
The instance is running, and docker logs show a successful deployment. The Strapi app is running and connected to the RDS database, but I am unable to access it through the URL.
Are there any additional steps I'm unaware of?
My server.ts file (config/server.ts for Strapi)
import cronTasks from './functions/cron_tasks';
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
app: {
keys: env.array('APP_KEYS'),
},
webhooks: {
populateRelations: env.bool('WEBHOOKS_POPULATE_RELATIONS', false),
},
cron: {
enabled: true,
tasks: cronTasks,
},
});
I have tried changing the EB to a load balanced instance to listen to both ports 80 and 433.
For anyone facing this same issue, this was the problem:
Elastic beanstalk load balance was listening to port 80 for the instance port 80
The app itself was on port 1337
To make it work, what I did was:
Change the port mapping in my docker-compose.yml
Instead of port 1337:1337, I used 80:1337

Istio-ingress behind Google cloud Layer 7 load balancer

Problem I am facing is that my istio-ingressgateway is working perfectly file at network layer load balancer(L4 loadbalancer or TCP load balancer) but when i connect istio-ingressgateway to Layer7 load balancer by attaching nodePort at backend service.after that http to https redirection not working properly its always give Response code 301 even when i request using https protocol.
I successfully configured the same architecture. Here the step to reproduce:
Deploy a GKE cluster. Either with Istio, or with istio installed afterward.
Get the Istio-ingressgateway nodeport for http:
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(#.name=="http2")].port}'
Create a Global Loadbalancer
Create a backend service and select your cluster InstanceGroup.
Set the istio-ingressgateway nodeport as port
Create an health check, on the same nodeport value, in TCP mode
Configure your URL path
Validate and wait 5-10 minutes for letting the time to the health check to validate your configuration and to route the traffic
Now, you can reach your K8S cluster, through the Istio Nodeport with the global load balancer. Deploy a service on Istio, you could reach it through the Global Loadbalancer.
There is an issue on GitHub, Please check: https://github.com/istio/istio/issues/17980

Load balancer AWS configuration

I have some loadbalancer which works fine. It's configured like this.
The app is just running on 80 and redirected by the webserver to 443 and has a route 53 above
Now I tried totally the same but when I set my loadbalancer on the same values + wildcardcert I get:
Updating load balancer named: xx failed Reason: Listeners can't talk to InstancePort 80 with secure and insecure protocols at the same time (Service: AmazonElasticLoadBalancing; Status Code: 409;
What am I missing? Why is it working for the other apps?
Your second listener should have HTTP protocol as instance protocol. Or you should use port 443 for instance protocol.

Meteor on AWS using Mup - SSL with ELB

I'm migrating my Meteor app to AWS, want to use ACM issued SSL cert attached to ELB.
My current setup is:
ELB with ACM SSL cert(verified that load balancing and HTTPS is working on simple HTTP server inside EC ubuntu machine)
Meteor up is deployed on EC2 machine using Mup (Please see my mup.js which works well with SSL cert physically available from file system)
I want to stop using reverse proxy from mup.js config completely and let ELB run all SSL stuff. Problem is that ELB is not able to communicate with Meteor up,
have tried different ROOT_URLs but none are working:
EC2 Elastic IP with HTTP and HTTPS
(i.e. ROOT_URL: 'https://my-ec2-elastic-ip.com', ROOT_URL: 'http://my-ec2-elastic-ip.com')
ELB domain name with HTTP and HTTPS
What should I put for ROOT_URL and is it game changer in accepting requests? i.e. if I have wrong ROOT_URL, will Meteor still be able to accept incoming requests?
Mup version: 1.4.3
Meteor version: 1.6.1
Mup config
module.exports = {
servers: {
one: {
host: 'ec2-111111.compute-1.amazonaws.com',
username: 'ubuntu',
pem: 'path to pem'
}
},
meteor: {
name: 'my-app',
path: 'path',
servers: {
one: {}
},
buildOptions: {
serverOnly: true,
},
env: {
ROOT_URL: 'https://ec2-111111.compute-1.amazonaws.com',
MONGO_URL: 'mongo url',
},
dockerImage: 'abernix/meteord:node-8.9.1-base',
deployCheckWaitTime: 30,
},
proxy: {
domains: 'ec2-111111.compute-1.amazonaws.com,www.ec2-111111.compute-1.amazonaws.com',
ssl: {
crt: './cert.pem',
key: './key.pem'
}
}
};
Resolved, first and general issue was that I was using classic ELB, which doesn't support WebSockets and was preventing DDP connection. Newer Application Load Balancer which comes with WebSocket and Sticky Sessions helped. More on the diff here: https://aws.amazon.com/elasticloadbalancing/details/#details
Another issue more specific to my use case was having no endpoint for ELB health check, I was hiding/securing everything behind basic_auth, health check was getting 403 unauthorized failing and not registering EC2 instance in ELB. Make sure you have endpoint for health check that returns 200 OK, and also revisit your security groups - check out inbound rules and make sure ELB has access to corresponding ports to EC2 instance(80, 443 etc.).

Kubernetes nginx ingress proxy pass to websocket

We are running rails application with unicorn and websocket.
We are using AWS ELB as ingress
SSL terminates on ELB and forwards traffic to application.
Nginx ingress routes traffic to web app running unicorn/puma on port 8080.
App works but our websocket responds with 200 instead of 101. We have enabled CORS and used required annotations in ingress.
This are annotations used for the ingress controller service
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
service.beta.kubernetes.io/aws-load-balancer-ssl-cert::arn:aws:iam::xxx:server-certificate/staging
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
When we use aws loadbalancer protocol as tcp and load balancer ports as 443 it fails on infinite redirect loop.
Following are the annotations used in the ingress:
nginx.ingress.kubernetes.io/service-upstream: true
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"
ingress.kubernetes.io/force-ssl-redirect: "true"
Our sample nginx configuration we used earlier without ingress is here
How to get websockets working with nginx ingress controller with AWS ELB ?
Is it possible to try without CORS?
Part of the handshake is the client must send at least these headers:
Sec-WebSocket-Key
Sec-WebSocket-Version
And maybe something else. Look at https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#The_WebSocket_Handshake