AWS ELB redirect behind SSH tunnel doesn't work - amazon-web-services

We have an HTTP server listening on port X, and an AWS Classic HTTP Load Balancer, listening on the same port X and forwarding to the host port X.
The ELB is not routable to the internet, so to connect to it, we create an SSH tunnel from a local port Y to the ELB port X over a bastion host.
Simple HTTP requests work ok, however when the service return an HTTP redirect response (303), the ELB translates it to port Y.
So it looks like:
http://localhost:Y --> (303 redirected) http://localhost:X/login
When skipping the ELB and tunnelling directly to the service host, redirects work fine.
Any way to configure the ELB to translate the redirections to the originating port, as specified in the HTTP Host header?

Related

is it possible to access a ec2 instance where inbound rule is only allowed for ssh with the help of apache http

I need to access an ec2 instance using http but inbound rule is only allowed for ssh.So is it possible to access the ec2 through http if i connected the ec2 using ssh and installed apache http.
It can be resolved using changing the inbound rule but is it possible by apache http without changing the inbound rule
Yes. You can activate Port Forwarding across your SSH connection, which will allow traffic to go across the SSH connection to the web server on the destination EC2 instance, and it will all happen via port 22 (SSH).
For example, this command will forward local port 8000 to the remote port 80:
ssh -i key.pem ec2-user#IP-ADDRESS -L 8000:localhost:80
You can then access the remote web server from your own computer by pointing your web browser to http://localhost:8000. The traffic will be sent across the SSH connection to the EC2 instance, where it will be sent to localhost:80 (which is the web server on the EC2 instance).
For details, see: How to Use SSH Port Forwarding {Ultimate Guide}

Kubernetes nginx ingress path-based routing of HTTPS in AWS

Question: Within Kubernetes, how do I configure the nginx ingress to treat traffic from an elastic load balancer as HTTPS, when it is defined as TCP?
I am working with a Kubernetes cluster in an AWS environment. I want to use an nginx ingress to do path-based routing of the HTTPS traffic; however, I do not want to do SSL termination or reencryption on the AWS elastic load balancer.
The desired setup is:
client -> elastic load balancer -> nginx ingress -> pod
Requirements:
1. The traffic be end-to-end encrypted.
2. An AWS ELB must be used (the traffic cannot go directly into Kubernetes from the outside world).
The problem that I have is that to do SSL passthrough on the ELB, I must configure the ELB as TCP traffic. However, when the ELB is defined as TCP, all traffic bypasses nginx.
As far as I can tell, I can set up a TCP passthrough via a ConfigMap, but that is merely another passthrough; it does not allow me to do path-based routing within nginx.
I am looking for a way to define the ELB as TCP (for passthrough) while still having the ingress treat the traffic as HTTPS.
I can define the ELB as HTTPS, but then there is a second, unnecessary negotiate/break/reencrypt step in the process that I want to avoid if at all possible.
To make it more clear I'll start from OSI model, which tells us that TCP is level 4 protocol and HTTP/HTTPS is level 7 protocol. So, frankly speaking HTTP/HTTP data is encapsulated to TCP data before doing rest levels encapsulations to transfer packet to another network device.
If you setup Classic (TCP) LoadBalancer it stops reading packet data after reading TCP part, which is enough to decide (according to LB configuration) to which IP address and to which IP port this data packet should be delivered. After that LB takes the TCP payload data and wrap it around with another TCP layer data and send it to the destination point (which in turn cause all other OSI layers applied).
To make your configuration works as expected, it's required to expose nginx-ingress-controller Pod using NodePort service. Then Classic ELB can be configured to deliver traffic to any cluster node to port selected for that NodePort service. Usually it is in between 30000 and 32767. Sou your LB pool will look like the following:
Let's imagine cluster nodes have IP addresses 10.132.10.1...10 and NodePort port is 30276.
ELB Endpoint 1: 10.132.10.1:30276
ELB Endpoint 2: 10.132.10.2:30276
...
ELB Endpoint 10: 10.132.10.10:30276
Note: In case of AWS ELB, I guess, nodes DNS names should be used instead of IP addresses.
So it should cause the following sequence of traffic distribution from a client to Kubernetes application Pod:
Client sends TCP packet with HTTP/HTTPS request in payload to ELB_IP:ELB_port (a.b.c.d:80).
ELB receives IP packet, analyze its TCP data, finds the appropriate endpoint from backend pool (whole list of Kubernetes cluster nodes), and creates another TCP packet with the same HTTP/HTTPS data inside, and also replaces destination IP and destination TCP port to cluster node IP and Service NodePort TCP port (l.m.n.k:30xxx) and then send it to the selected destination.
Kubernetes node receives TCP packet and using the iptables rules changes the destination IP and destination port of the TCP packet again, and forward the packet (according to the Nodeport Service configuration) to destination pod. In this case it would be nginx-ingress-controller pod.
Nginx-ingress-controller pod receives the TCP packet, and because according to TCP data it have to be delivered locally, extracts HTTP/HTTP data out of it and send the data (HTTP/HTTPS request) to Nginx process inside the Nginx container in the Pod,
Nginx process in the container receives HTTP/HTTPS request, decrypt it (in case of HTTPS) and analyze all HTTP headers.
According to nginx.conf settings, Nginx process change HTTP request and deliver it to the cluster service, specified for the configured host and URL path.
Nginx process sends changed HTTP request to the backend application.
Then TCP header is added to the HTTP request and send it to the backend service IP_address:TCP_port.
iptables rules defined for the backend service, deliver packet to one of the service endpoints (application Pods).
Note: To terminate SSL on ingress controller you have to create SSL certificates that includes ELB IP and ELB FQDN in the SAN section.
Note: If you want to terminate SSL on the application Pod to have end to end SSL encryption, you may want to configure nginx to bypass SSL traffic.
Bottom line: ELB configured for delivering TCP traffic to Kubernetes cluster works perfectly with nginx-ingress controller if you configure it in the correct way.
In GKE (Google Kubernetes Engine) if you create a Service with type:LoadBalancer it creates you exactly TCP LB which forward traffic to a Service NodePort and then Kubernetes is responsible to deliver it to the Pod. EKS (Elastic Kubernetes Service) from AWS works in pretty much similar way.

Amazon EC2 HTTP connection refused, but HTTP port is open

I created a new Ubuntu T2 Micro instance on EC2.
Created a new Elastic IP and selected "EIP used in: VPC"
Associated the address to my new EC2 Ubuntu instance.
I now have a Private IP and a Public/Elastic IP. No Public DNS.
My security group has SSH port 22 and HTTP port 80 open.
I can connect to the instance just fine through SSH using the Public IP, but when I try to browse to the Public IP through the browser it says connection refused. I can't ping it either.
I'm out of ideas.
Amazon EC2 HTTP connection refused, but HTTP port is open
That's already proven by the fact that you got 'connection refused'. If the port wasn't open it would have been 'connect timeout'.
'Connection refused' means that the service you tried to connect to wasn't listening at that port. Possibly it isn't started at all, or even installed.
You need to install a web server on your machine, such as Apache or Nginx. This is not provided by default in EC2.
go to security groups --> edit inbound rules --> add rule (add a custom TCP port 8888 with 0.0.0.0/0 ).
There are two major things that can happen to your web server.
Connection refused :- Which means there is no service running (http/JBOSS/nginx) on your server which is available to accept connections on port specified (which is 80 in this case)
Connection timed out :- Would mean server is not able to process any incoming connection hitting it at port 80. Once you fix the security group and your NACL (if you don't have a default one), then you need to re-check to see if it's service which is giving out the error, not to forget that the error response will change.

How to get the port number of client request with AWS ELB using TCP and Nginx on server

While using HTTP/HTTPS as load balancer protocol we get the requested origin protocol (i.e. it is HTTP or HTTPS) from x-forwarded-protocol header.
Now, using this header in nginx configuration it can be determined that whether the originating call was from HTTP or HTTPS and action could be performed accordingly.
But if the ELB listeners configuration is as shown in the below image, then how to determine that the request has come via port 80 or port 443?
You have a couple of options, at least:
Option 1 is not to send both types of traffic to the same port on the instances. Instead, configure the application to listen on an additional port, such as 81 or 8080, and send the SSL-originating traffic there. Then use the port where the traffic arrives at the instance, to differentiate between the two types of traffic.
Option 2 is to enable the PROXY protocol on the ELB, after modifying the application to understand it. This has the advantage of also giving you the client IP address.
http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html
http://www.haproxy.org/download/1.5/doc/proxy-protocol.txt

EC2 Load Balancer Instance Protocol and Port

I have an elastic load balancer that works properly when configured like so:
Load Balancer Protocol: HTTPS
Load Balancer Port: 443
Instance Protocol: HTTP
Instance Port: 80
However, if I attempt to change the instance protocol to HTTPS and instance port to 443, my server stops responding.
What do I have to do in order for my instance port to be 443?
The reason I want my instance port to be 443 is that my Rails app must verify that the incoming connection uses SSL, but this way, this check fails.
You need to change the way your application detects whether or not the client is using SSL.
The port on the server won't give you that information. You may want to look at the ELB documentation and see if you can use X-Forwarded-Proto or X-Forwarded-Port.
Your instance server has to be able to respond on port 443, with a valid HTTPS response.
That generally means you have to install a signed SSL cert and configure your web server to use it.
Without knowing what web server you are using, I can't give specific instructions.
For instance, if you are using Apache, you need to install something like mod_ssl.