AWS ElasticBeanstalk + Socket.IO + SSL issue - node.js

I'm having trouble working with AWS ElasticBeanstalk with NodeJS environment + Socket.IO + SSL for our messaging app.
I'm already running in circles trying to fix the issue but I always ends up to a Websocket handshake error (504 GATEWAY_TIMEOUT).
AWS Elastic Beanstalk Load Balancer configuration:
ELB security inbound rule
Instance's security inbound rule
Response error
Front end code
Thanks in advance. Any help is highly appreciated!

Finally!!! Got it!
So after a lot of hours burned, this solution works for me.
The problem is that I have HTTPS in my load balancer pointed to HTTP on my ec2 instance. That causes a problem because websocket runs on TCP and not HTTP/S. The port number also did matter in my case.
Original config (not-working)
New config (working)
I hope this can be of any help in the future. :-)

Related

Problem running Express app over HTTPS on aws

I have an ExpressJS backend and I want to run over https on aws (so I don't get 'mixed type content' error when trying to connect with my frontend which runs over https), it's running great using http but when using https it doesn't work.
I asked this question before and I got answers like 'use nginx', 'use load balancer', unfortunately I don't know much about this stuff as I'm not very experienced with all aws variations and options, are there any tutorials I can follow step by step ? or any easy way to serve my backend over https without complexity?
any easy way to serve my backend over https without complexity?
The easiest way (don't confused with the cheapest way) is to change your EB environment to load-balanced one. You can do this in EB console's configuration settings.
This change will create Application Load Balancer for your app, and place it in-front of your instance. Once ALB is running you can follow this AWS guide:
How can I configure HTTPS for my Elastic Beanstalk environment?
In the above, only section Terminate HTTPS on the load balancer would be relevant.
Depending on the nature of your application, is it fully dynamic, or more on static side, you could also consider using Using Elastic Beanstalk with Amazon CloudFront, instead of using ALB. CloudFront could be also be easily setup to use HTTPS between clients and CloudFront, but the issue is that traffic between CloudFront and your EB instance would go over the internet unencrypted (HTTP). Obviously, you could make it HTTPS, but this requires further changes and configurations which does not fall into category of "easy ways".

AWS Loadbalancer Proxy for Nodejs

I have configured the load balancer to route the request to two of Ec2 Instance running a NodeJs server. I need to direct the request coming from both http (port 80) and https (port 443) to http (port 80) of the EC2 instances in NodeJs. I have uploaded the ssl certificate to AWS and configured the load balancer to use ssl certificate. The problem is the request coming from http port doesn't automatically route to https. It has to be a server side script or snipped which I need to write in server.js which should be routing the http to https, i tried to do it and it run into endless redirection. So questions -
Is there any guide to do this from AWS ?
If not then how one can achieve this, any pointers or suggestions would be greatly appreciated.
On the server side you can check the X-Forwarded-Proto
(original request protocol) and if it's heaving value http you can send redirect (http 302) to a url with https protocol..
though with ALB (application load balancer you may specify a set of rules, maybe it's possible to do that there..)
I couldn't find a guide from AWS, but I will keep searching and update the answer in the case I find it.
Usually, when you write applications in Node.js, you specify which port should your app run at. It means that you will need two different servers listening. And when your app receives a request on port 80 (HTTP), it should redirect to your HTTPS server, like in this answer.
Another point that may be relevant to your question is that, in production environments, you don't usually bind a port to your Node.js server, since it's not production ready. You probably want to use a reverse proxy and load balancer like Nginx or HAProxy.
If you are using the AWS ALB (Application Load Balancer) they announced the http->https redirect today. Take a look: https://exampleloadbalancer.com/redirect_demo.html
Put your ELB behind the Cloudfront and in settings of your distribution select forward HTTP to HTTPS.
The following doc will be helpful
https://docs.aws.amazon.com/waf/latest/developerguide/tutorials-ddos-cross-service-ELB.html
This method has two benefit:
1-Your problem will be solve
2-You can use the benefit of the powerful CDN, for more information about Cloudfront read https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html
Update:
You can forward traffic from HTTP to HTTPS by edit your Listeners setting in your ELB.

504 Gateway Time-out on specific POST request

Since the discussion forums of Amazon gave an error im posting the question here.
We are running a single nodejs (api) instance with Elastic Beanstalk.
After 4 months of usage, suddenly the POST request for creating users failed with a 504 Gateway Time-out. No modification were made to the code or elastic beanstalk config in the meantime whatsoever.
The rest of the requests are working correctly. When testing locally there are no errors.
In the nginx error log the following occurs:
Upstream timed out (110: Connection timed out) while reading response header from upstream.
Tried Apache as a proxy and this gave a similar error.
Environment
64bit Amazon Linux 2016.03 v2.1.0 running Node.js
Nodejs 4.3.0
Nginx 1.8.1
After trying almost everything we are out of options.
Any suggestions?
Thanks in advance,
Mk
If you're using an ELB, try setting the "Idle Timeout" to a higher time value. You can do this using the AWS CLI:
aws elasticbeanstalk update-environment --environment-name your-env-name --option-settings Namespace=aws:elb:policies,OptionName=ConnectionSettingIdleTimeout,Value=300
I'm not sure if you can do this from the UI but I don't think so.

Has anyone used Primus with websockets behind aws Elastic Load Balancer?

I have a node.js application server running on port 80 and I recently added realtime messaging through Primus websockets transformer on port 9001.
It works well in single instance. I deployed the messaging to Beanstalk environment with the following configuration.
AWS Elastic Beanstalk
Platform version v2.0.0
Nodejs version v0.12.6
Primus version v4.0.5
Port 9001 is added to the security group of the instance as shown in the screenshot.
Proxy server is set to "none" in configuration options.
TCP Listener is added in the Elastic Load Balancer configuration.
Proxy-Protocol is enabled as mentioned in the aws documentation.
Added proxywrap to the primus server configuration.
But the client requests doesn't reach the instance and connection timed out. Has anyone used primus with websockets behind AWS ELB?
Please let me know the configuration which enables websockets communication behind Elastic Beanstalk.
I managed to get websockets (https://github.com/websockets/ws) working on both port 80 and 8080 on ELB with the configurations below. And thats without enabling Proxy-Protocol.
Security group:
Load balancer listeners:
Container options:
Load balancer:
You need to do two things
Increase idle timeout on ELB
On EC2 dashboard, reach for Load Balancer settings and open the Description tab for your load balancer. Look for the setting "Idle timeout", type something like "600" (for 10 minutes)
Ping periodically
Implement a WS ping every 5 minutes (or other, but need to be lower than the idle timeout on ELB). If primus doesn't have support on its API, implement yourself sending of a dummy message to client.

node.js autoscaling/load balancing any methods? with socket.io

I am trying to deploy a node.js project so it can auto scale with a loadbalancer.
I have tried AWS ELB elastic beanstalk. After a much time spent, the ELB doesn't like the socket.io connect as much as expected.
From this I have searched many methods to fix this issue:
nginx proxying
changed listeners on the loadbalancer to allow TCP port 3000 (other ports too depending on the forum/question I looked at)
redis server to share socket connection between different nodes.
I can't really put all the sites that I've tried to get this working.
But it hasn't worked at all.
The only thing I probably haven't tried is using route53...
So the question is:
If there is someone that has a proper node.js app with socket.io working with elastic beanstalk (or EC2 instances with a load balancer and auto scaling) working, is there a way to do this, and what would that method be?
If there are links that have a few step by step methods that would be awesome.
Thanks in advance!

Resources