Redirecting AWS ELB HTTP Requests to HTTPS - amazon-web-services

When we use AWS Application Load Balancer to redirect incoming requests to our servers, we created an SSL certificate and set it to the load balancer. It both listens HTTP 80 and HTTPS 443 ports' traffic. In both cases, traffic is redirected to target group instances' HTTP 80 port.
In these instances, there are nginx servers which are configured to listen HTTP 80 ports of the instance they are in. (These instances are Elastic Container Service instances)
When I update the nginx.conf file to redirect incoming HTTP requests to redirect to HTTPS protocol, we are facing a redirect loop. Even if the original request is an HTTPS request, behind the load balancer, EC2 instance is listening HTTP port. So it doesn't matter if the original request is HTTP or HTTPS, nginx infinitely sends redirect.
I saw that Cloudfront is an option, but I'm not interested in using
another service of AWS and paying them extra money just to overcome
this issue.
Other solution might be changing HTTP listener to HTTPS inside the instances registered to target group of the ELB. Since we are using ECS, we have to find a way to secure our SSL certificate keys while creating the docker image. I don't want to put our SSL certificate inside code repository for jenkins to use it. There will be extra work if I choose this solution.
Do you have any simpler ideas to fix this issue?

Nginx will always get requests over HTTP, so obviously you can't tell it to redirect all HTTP requests. The ELB sets a special HTTP header on the requests it sends to your back-end servers, named x-forwarded-proto, that you need configure Nginx to use to check if the connection between the browser and the ELB is over HTTP or HTTPS, and only redirect if that is HTTP. I would check this answer on ServerFault.

As Mark B mentioned, checking the custom header values for the incoming prototol is the simplest way to handle this and eliminate the redirect loop.
However, if you want to ensure end-to-end encryption, you can deploy self-signed certificates in your containers. The load balancer does NOT require a valid, public certificate in order to connect to HTTPS origin.
That way you can forward port 80 on the ALB to port 80 on the target group (and you could even have a separate target group just for redirecting) and force the redirect as you're doing now, and forward port 443 on the ALB to port 443 on the target group.

Related

Redirect http to https on Beanstalk's ALB without support of https on the instance

I have the following beanstalk environment: https(443) -> ALB -> http(80) to instance.
ALB listener accept only HTTPS request and authenticate with SSL certificate and then process to default port 80.
Everything works fine but I wonder if is it also possible to redirect HTTP port 80 requests back to ALB HTTPS listener without the need to support HTTPS on the instance?
When I tried to create redirect process it failed since it tried health-check on port 443 and the instance doesn't support it.
P.S. Is it a security issue if authentication done only in ALB and it communicate instances on port 80? (Instance security group accept requests only from ALB)
The redirection from port HTTP to HTTPS is best set using EC2 console, not EB console. For that you have to go to EC2 console-> Load Balancers.
Then you can modify the existing rule on HTTP:80 listener from Forward to Redirect as shown below:
The above change should not affect any of your health checks.
Is it a security issue if authentication done only in ALB and it communicate instances on port 80?
Yes. This is how it is most commonly done. The HTTP traffic between ALB and your instances traverses only AWS network, not the internet. So its safe from public eyes. But obviously, you can still setup HTTPS between ALB and the instances, but this requires extra work and puts more stress on your instances as they now have to handle SSL encryption and decryption as well.

Gatsby site serving on EC2 with pm2 node with aws classic load balancer needs https

I am running a Gatsby site in development mode as a dev server on EC2 with a loadbalancer pointing from port 80 to 8000. I have setup a cname on my domain dns to point to the load balancer this works fine. However I need to display this page as an iframe in sanity.io as a web preview and it requires https.
I've read through this https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html and most of it is pretty straight forward for the most part.
What I have done so far is created a listener for 443 https on the loadbalancer and added https 443 to the security group. i have succsufully issued a certificate to the subdomain I am using with aws and attached it to the loadbalancer listener.
Gatsby has a article about custom certs for development mode here https://www.gatsbyjs.org/docs/local-https/#custom-key-and-certificate-files What I am looking for is the cert file, the authority file and the key file in order to pass this command below
Where in the aws certificate manager do I find these files. I think that is the last piece I need to get https working, correct me if I am wrong.
thanks ahead of time.
gatsby develop --https --key-file ../relative/path/to/key.key --cert-file ../relative/path/to/cert.crt --ca-file ../relative/path/to/ca.crt
This is the process I used to request my certficate and it says it's issued
https://docs.aws.amazon.com/acm/latest/userguide/gs-acm-request-public.html
But how do I use it with the custom https command with gatsby?
There is a export option but it says only for private keys. Do I need to create a private key and then I can export these files I need?
Do I even need to run https on gatsby's side. I watched a video using apache and no change was made to the apache server to get https working with the loadbalancer.
Here is a screenshot of my loadbalancer listenr
Here is a image of my security groups
If I run the --https for gatsby develop it breaks my site I can no longer visit it via the loadbalancer or port 8000. So not sure what to do here.
I would suggest not to encrypt the connection between your ELB and the EC2 instances. If your EC2 instances are not publicly reachable, but only through the load balancer instead, it is best practice to terminate the SSL connection on the load balancer. No need to encrypt HTTP requests inside an AWS VPC (i.e. between ELB and target instances).
You can create a load balancer that listens on both the HTTP (80) and HTTPS (443) ports. If you specify that the HTTPS listener sends requests to the instances on port 80, the load balancer terminates the requests and communication from the load balancer to the instances is not encrypted. [1]
There is some discussion (e.g. on the blog of Kevin Burke) whether it is necessary to encrypt traffic inside a VPC. [2] However, most people are probably not doing it.
What it means for you: Use the same instance protocol for your targets as before: HTTP via port 8000 for both listeners. Do not set up SSL for your Gatsby service. Use a plain HTTP server config instead. No changes are necessary to ELB targets when using SSL termination on the load balancer.
References
[1] https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-create-https-ssl-load-balancer.html
[2] https://acloud.guru/forums/aws-certified-security-specialty/discussion/-Ld2pfsORD6ns5dDK5Y7/tlsssl-termination?answer=-LecNy4QX6fviP_ryd7x

added SSL does not work for AWS Load Balancer using ACM

I have a AWS LoadBalancer which created using Kube, Kops and AWS.
protocl type for the ELB is tcp. this work fine for http requests, means I can access my site with http://testing.example.com. Now I tried to add SSL for this ELB using ACM (Certificate manager). I added my Domain details example.com and *.example.com by requesting a public Certificate. it created successfully and domain validation is also success.
Then I tried to add this ssl to my ELB like below.
went to my ELB and selected the ELB.
Then went to Listeners tab and Added SSL to it like below.
and ELB description is like below.
I cannot access the https://testing.example.com, it hangs for few minutes and nothing happens. what is going on here. hope your help with this.
In the Listener configuration, you are forwarding the default HTTP port 80 to port 30987 on the back-end server. So this tells me that the back-end server is listening for HTTP requests on port 30987.
You then added an SSL listener on the default port 443 but you are forwarding that to port 443 on the back-end server. Do you have something on your back-end listening on port 443 in addition to 30987?
The most likely fix for this is to change the SSL listener on the load balancer to forward to port 30987 on the back-end by setting that as the "Instance Port" setting.
If your backend application (that sits behind the ELB) only listens on HTTP port 30987 then you need some layer of TLS termination before your app server.
More food for thought on this approach:
https://security.stackexchange.com/questions/30403/should-ssl-be-terminated-at-a-load-balancer
Or you need to tweak your backend app server to also listen on an HTTPS / TLS context, in a different port (which you must map in your ELB configuration).
BTW, I would also suggest to switch to and ALB or an NLB.
More info: https://medium.com/cognitoiq/how-cognitoiq-are-using-application-load-balancers-to-cut-elastic-load-balancing-cost-by-90-78d4e980624b
Once you finish the setup of whatever suggestion you picked, run curl -k -I https://testing.example.com/ to check whether of not you are getting blocked by the ELB.

How can i redirect port 80 to https in aws ALB

I am using Amazon ALB with TargetGroups
I have ALB Listener on HTTPS which goes to TargetGroup1.
TargetGroup1 goes to ECS Service
Now i want if someone come from port 80 then should get redirected to HTTPS listener on ALB. Is there any easy way for this?
Assuming your performing ssl termination on the ALB you need your ecs to conditionally redirect based on the value of the header x-forwarded-proto added by the ALB (its value is either http or https). This variable desribes the request sent to the ALB and allows you to act accordingly.
Since there's no answer and this is a relatively recent question, the answer is that this is now supported out of the box by ELB. Add a listener on port 80 with an action of Redirect and HTTPS is now an option.

Http to https redirection is not working

I am trying to configure the redirection for all http traffic to https only. My configuration as follows
We are using ELB and EC2 instances
Configured application Load Balancer in this case.
Backend server is working on port 443, using Nginx
Configured Nginx redirection rule for http to https redirection
Configured ELB listener for both port 80 and 443
Installed SSL Certificate in both backed servers and ELB
My Issue is when a client accesses this application over https URL is working fine in https. But when the clients try to connect this application over http, it is working in http and not redirect it into https.
I need to work this application only in https. How can we force all client communication into https?
Are you checking the right values in the redirect settings? The ALB should set x-forwarded-port and x-forwarded-proto.
Another option would be to use cloudfront in front of your ALB, and set it to force everything to https.