AWS Application load balancer throwing 502 - node.js

I am currently learning about AWS and I have a single EC2 instance running with a nodejs server on port 3000, an Application load balancer with SSL setup that listen on port 80 and 443 (http & https). When I make requests to the http route it returns back the successful health check message. But when I try to access my api via the https method, I get a 502 Error. I googled around and read some articles and they pointed out that the nodejs server keepAliveTimeout and headersTimeout should be higher than the timeout option of the ALB. I tried that and it didn't work. I also tried to set the max-http-header-value to 16384, I also tried to check the access logs for the load balancer on my S3 bucket and the logs just showed that I am getting a 502 error and nothing more. What could be the issue? Because I have tried all solutions that presented but they don't seem to work.

The 443 listener needs to be pointed to port 80 on the ec2 instance

The first thing to check is that your server is responding to requests. Try connecting to port 3000 on the server, either from the server itself (eg curl localhost:3000) or from outside the server (which will require the Security Group to permit access to port 3000).
Once you have confirm that the server is responding, configure Security Groups as:
A Security Group on the Application Load Balancer (ALB-SG) that permits Inbound access on ports 80 and 443
A Security Group on the Amazon EC2 instance (App-SG) that permits inbound access on port 3000 from ALB-SG
That is, App-SG should specifically refer to ALB-SG in its Inbound rules.
Then, configure the Load Balancer to have a Target Group that points at port 3000 on the app server and provide it a URL for the Health Check (that could simply be /).
Then, connect to the Application Load Balancer and see whether you can access your app.

Related

Using HTTPListener with Azure Web apps

I'm trying to get a simple HTTP console app running as an Azure Service App. All it does is return OK when you connect. It works fine on my laptop and I can publish to Azure ok using VS2019. The issue is the prefixes that are used for listening.
On my laptop I can use http://+:80/;https://+:443/, but in Azure I get an error: [EXCEPTION] Access is denied.
This article https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox#network-endpoint-listening implies the app will listen on 80 and 443
"The only way an application can be accessed via the internet is through the already-exposed HTTP (80) and HTTPS (443) TCP ports; applications may not listen on other ports for packets arriving from the internet.
However, applications may create a socket which can listen for connections from within the sandbox. For example, two processes within the same app may communicate with one another via TCP sockets; connection attempts incoming from outside the sandbox, albeit they be on the same machine, will fail. See the next topic for additional detail."
but my code always fails when I try and register the prefix. I can't use localhost as the same article says that's not allowed. I've tried using the app URL but that doesn't work either.
I've seen other articles that imply the HTTPListener needs admin permissions which I can't give it in Azure.
Does anyone know what the correct prefixes are or if it's ever going to work?
Netstat not working in KUDU so ASE (App Service Environment) is used to view the port details in portal App Service Environment -> General -> IP Addresses (check here ).
App Service applications only serve HTTP (port 80) and HTTPS (port 443) traffic. Each App Service application has default built-in HTTPS support for the azurewebsites.net domain name.
Your app may be already listening to the port 80 & 443. Please check here for more info for similar issue see here

Building a secure HTTPs web server with Fargate + ACM + ALB

I am trying for the simplest deploy to get an https web server up and running in Fargate.
I have used Amazon Certificate Manager to create a public certificate.
I have an Application Load Balancer that is talking to the Fargate container on two ports:
80 for http and
443 for https
This is the problem: when I run my webserver on port 80 (http) and connect via the ALB, it works fine (not secure, but it serves up the html).
When I run my webserver on port 443 with TLS enabled, it does not connect via the ALB.
Another point is that when running my webserver with TLS enabled on port 443, I do not have the certificate or certificate key, and so am confused how to get that from Amazon.
Another question I have is: does it make sense for me to say that the ELB will communicate with the client over HTTPS but that the ELB can communicate with the container via HTTP? Is this secure?
My networking knowledge is very rusty.
does it make sense for me to say that the ELB will communicate with the client over HTTPS but that the ELB can communicate with the container via HTTP?
Yes. You should make sure your web server is accepting traffic from the ALB on port 80. This is done at the application level, on the web server, and with your target group, which is what the ALB will use to determine how it routes traffic to your web server. This is way it typically works:
client --(443)--> ALB --(80)--> web server
Some things to check:
Target group is configured to send traffic to your FG web server on port 80
Target group health check is configured to check port 80
FG task security group has ingress from ALB on port 80
Web server is configured to listen on port 80
Sidenote: You can configure your target group to send traffic to the target (web server in Fargate) on 443, but as you said, without the proper certificate setup in the container, you won't be able to properly terminate SSL and it just wouldn't work. You would need to upload your own cert to ACM for this to work, which sends you down a security rabbit hole, namely how to avoid baking your private key into your Docker image.

How to link a url as a default like localhost in Nodejs

I have a url which is now https and is ready to be use. But the problem is, I do not know how to use that url as Nodejs backend localhost.
By default, We are using
http://localhost:3000/api/thisRoute
And I want to use that url and it looks like this
https://api.domainName.com/api/thisRoute
Current Status:
My backend is deployed in AWS EC2 and already link to that url and I am still using the default in the backend.
Is this possible?
You can setup an ALB (Application Load Balancer) in AWS and terminate the https connection at the Load Balancer by setting up a HTTPS listener. Then have it send the request via http to your EC2 Instance on port 3000 via a target group.
OR
You could setup a second listener on port 443 in your node.js server (see https.createServer) and point the DNS directly to your EC2 Instance IP address. This would require more work but you don't have to pay for a Load Balancer.

Mutliple http routes on Elastic Beanstalk load balancer for node app with multiple servers

Having difficulty phrasing my question, so I could not find much info on it so I will explain:
I have a node.js app that hosts a restify/express api on port 8081.
This same api hosts a websocket server on port 8083.
All this works wonderfully on localhost by specifying the ports, but in a hosted environment it needs to run on port 80 http. (omitting 443 for simplicity).
I am using AWS Elastic Beanstalk (nginx server). When I deployed my app, it creates an EC2 and ELB (load balancer) instance. The ELB then has a public dns which I use to access the api on port 80. There is no special listeners configured (only 80 and 443). So I am not sure how it gets to the api on port 8081. The EC2 instance also only allows 80 and 443.
The api works fine using it with the ELB public dns on port 80.
Now I have added the websocket server in there.
My problem is - I need another public dns on port 80 to go to the socket server on port 8083 of the same Beanstalk app. How would I approach this?
I would appreciate any thoughts and ideas.
It appears that..
Elastic Beanstalk creates a Classic load balancer which does not support websockets.
Default nginx setup on AWS does not allow Upgrade headers.
However, I got it working in the following manner:
Default EB setup (with classic ELB) serves the API as it normally did.
Then I created an ALB (Application load balancer) from the EC2 dashboard.
I added a target that routes to my EC2 instance (that EB created) on port 8083 (my websocket listener). My API runs on port 8081. Then add the target to the new ALB on on the Listeners tab.
This will allow traffic that hits the new ALB on port 80 to route to port 8083 of the server where my application is hosted.
In my .ebextensions file in the project, I added the following that will update nginx settings to allow the Upgrade header that is needed for websockets:
Add to .ebextensions
container_commands:
enable_websockets:
command: |
sed -i '/\s*proxy_set_header\s*Connection/c \
proxy_set_header Upgrade $http_upgrade;\
proxy_set_header Connection "upgrade";\
' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf
So basically I have two load balancers. The default one that routes 80 to 8081, and another (ALB) that routes 80 to 8083.
This is by no means perfect. Auto scaling/load balancing would probably not work. But for now is serves the API and websocket server from the same application.

Hosting web application on Amazon AWS EC2

I am developing a web application locally. However, I would like to host the final product on an Amazon EC2 instance. I have moved my web application to the EC2 instance and am able to run the application; it's now listening on port 8081.
What I don't understand is how to allow users on the internet to access the web application running on port 8081 of the EC2 instance. I have tried redirecting the domain name to the IP address of the EC2 instance on the NameCheap DNS (where we bought the domain) to no avail. I suspect one of the things I need to do is set the permissions of the EC2 permission group but what should I set it to?
Help is greatly appreciated!
Thanks!
You can setup a nginx server to proxy all request to the port 8081.
Read more information here: https://doesnotscale.com/deploying-node-js-with-pm2-and-nginx/
Generally speaking, for a public web application you will want to run on a standard port (e.g. 80 or 443). You could do that by just running your node app as a privileged user (required by most OS's to expose 80 or 443), but generally it's better to have a web server in front pass the traffic, treating your node app as an upstream server (even if it's on localhost). NGinX is a good choice for this.
Regardless of what port you want to run it on, you'll need to update your EC2 security policy for that instance to allow traffic on that port (80, 443, 8081, whatever). You'll also need to make sure it's exposing a public IP address. It's not a bad idea to assign it an Elastic IP, since you'll wnat it to have the same address across instance reboots.
Finally, depending on what AMI you're running from, there may be a host firewall configured that you'll need to check on and configure to allow the traffic.

Resources