-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Http -> https redirect on TCP ELB terminating ssl, results in a 308 redirect loop. #2724
Comments
Hi folks, still experiencing this issue in 0.17.1 it seems |
I am seeing this issue as well. Could the destination port provided via the PROXY protocol not be used to determine if the incoming connection was made over HTTP or HTTPS? When using the L7/HTTP ELB the |
After thinking about this over the weekend I got it to work this morning. So... Make sure the ELB is set to load balance the HTTP and HTTPS protocols, not SSL or TCP, etc... Double check that both HTTP and HTTPS balance to the same internal port. in your nginx configmap: proxy proto : false Example below: "apiVersion": "v1", |
thank you @boxofnotgoodery this works for us! |
Let me share my settings that finally work. In ConfigMap:
Also in Service:
|
I think the suggestion above misses the point a bit (at least for my use case) as it will mean you cannot use web sockets and gRPC when the ELB runs in HTTP mode. It will have to run in TCP/SSL mode (ideally with the proxy protocol) in order for those features to be supported. |
I agree with Tenzer, I am also trying to enable force ssl redirect while using websockets and get a 308 redirect loop when enabled. Currently I cannot enable ssl redirect until there is a fix for this. If anyone has a suggestion please let me know. |
Same problem. I have to use WebSocket, so I'm not able to use HTTP and HTTPS in ELB ports, only TCP. |
This also happens to me on |
I've fixed it using this answer: Looks like a crutch, but it works :) |
Same issue for me |
Same issue is happening |
I gave the workaround in the Stack Overflow post a try and got it working as well. I'll try and point out the differences you have to make for the workaround to make it a bit more clear and why it works. I'll start with the configuration of the service/load balancer/ELB: ---
kind: Service
apiVersion: v1
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
# Enable PROXY protocol
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
# Specify SSL certificate to use
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:[...]
# Use SSL on the HTTPS port
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: https
spec:
type: LoadBalancer
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
ports:
- name: http
port: 80
# We are using a target port of 8080 here instead of 80, this is to work around
# https://github.com/kubernetes/ingress-nginx/issues/2724
# This goes together with the `http-snippet` in the ConfigMap.
targetPort: 8080
- name: https
port: 443
targetPort: http Three things to point out here:
In the ---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
data:
use-proxy-protocol: "true"
# Work around for HTTP->HTTPS redirect not working when using the PROXY protocol:
# https://github.com/kubernetes/ingress-nginx/issues/2724
# It works by getting Nginx to listen on port 8080 on top of the standard 80 and 443,
# and making any requests sent to port 8080 be reponded do by this code, rather than
# the normal port 80 handling.
ssl-redirect: "false"
http-snippet: |
map true $pass_access_scheme {
default "https";
}
map true $pass_port {
default 443;
}
server {
listen 8080 proxy_protocol;
return 308 https://$host$request_uri;
} This does the following:
An extra thing I changed which wasn't mentioned on Stack Overflow, was that I changed the ports:
- name: http
containerPort: 80
- name: https
containerPort: 443 to this: ports:
- name: http
containerPort: 80
- name: http-workaround
containerPort: 8080 This is in order to make the ports the Kubernetes pod accepts connections on to match what we need. I hope this is useful for other people. I don't know if it would be worth adding to the documentation somewhere or if it could inspire a more slick workaround. |
@Tenzer Thank you so much. Been stuck in this for a couple days, your solution works like a charm. |
I have just updated my previous comment and added the following to the
I found this to be necessary in order for Jenkins to not complain about the port number it received in the |
Thanks a ton @Tenzer. This is a great solution for anyone using a TCP/SSL load balancer that still wants HTTP redirects. Our data scientists will be very happy to have Jupyterhub, which requires web sockets, up and running in the k8s cluster. |
@trueinviso Thank you! I have a similar setup (terminating TLS at the load balancer) and reverting from |
@trueinviso If you aren't using the PROXY protocol (with |
@Tenzer I'll move it to the other issue referencing the 308 redirect. |
@Tenzer 's workaround worked like magic for us, till we've tried to upgrade nginx image to version 0.22.0 |
@assafShapira could you please provide some more information on what behaviour you are seeing with version 0.22.0? I'm using the workaround with an Nginx ingress controller on version 0.22.0 and I'm not aware of any problems with it. |
sorry, worng version number. |
Okay, but the question of how it breaks is still left. |
I'm getting into 308 loop |
I've tried to upgrade an Nginx ingress controller to both version 0.24.0, 0.24.1 and 0.25.0 and from what I can see the problem is the http-snippet: |
map true $pass_access_scheme {
default "https";
}
map true $pass_port {
default 443;
} This work around doesn't work any more as the two maps aren't used further down in the generated config file. Each ingress-nginx/rootfs/etc/nginx/template/nginx.tmpl Lines 816 to 820 in 28cc3bb
These are then used inside the location / {} block to set the headers sent to the backend:ingress-nginx/rootfs/etc/nginx/template/nginx.tmpl Lines 1205 to 1206 in 28cc3bb
I've tried various ways to attempt to change the value of these headers so the port number instead if 443 and protocol is "https" but to no avail:
I have both tried to In a test Nginx instance I tried to create a minimal configuration to create a test case for this, but I haven't been able to reproduce it: events {}
http {
server {
listen 8081;
set $pass_access_scheme $scheme;
# Position 1
location / {
# Position 2
set $pass_access_scheme https;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
proxy_pass http://127.0.0.1:8080;
# Position 3
}
# Position 4
}
} Regardless of which of the four positions noted by comments I can put in As long as we haven't got a way to overrule the I'd be very interested to hear if anybody else can come up with a work around for changing the values of those headers. |
@KongZ Right, I am using an NLB. However, the NGINX controller is still a L7 reverse proxy that forwards its own
And because we are serving HTTPS over port 8000, it is forwarding the port as 8000 instead of 443. |
@ssh2n every deployment you do with helm should have the annotation. |
Thanks @dardanos, that was a bit confusing, so I switched back to the classic L7 setup :) |
@walkafwalka, ran into the same issue as you with apps which depend on X-Forwarded-Port. Solution below sets proxy_port instead of server_port which comes by default. In my case Jenkins with Keycloak redirection had port 8000. This solved it:
|
I came across this although I am NOT using The issue was closed without recommending what workaround to apply in which context. For my specific case, I assume that because I am NOT using The nginx.com website documents an annotation that I haven't seen mentioned elsewhere, namely Also having So in total I have two issues:
My configuration looks like this using Helm charts:
and the ingress object itself:
Appreciate kindly your advise. |
@abjrcode It is on my answer. It is the complete solution. Just configure |
Thank you @KongZ for your suggestion. I will provide some more guidance for people coming across this and more options as I had a chance to take a thorough look at the code. There are two choices for load balancers, at least when it comes to AWS. ELBELB (although Classis and will be completely deprecated at some point), probably for historical reasons, actually forwards the The NGINX controller actually supports and can do redirection based on those headers. Here's how your configuration would look like with Helm:
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
name: <RELEASE_NAME>
namespace: <NAMESPACE>
spec:
chart:
repository: https://kubernetes.github.io/ingress-nginx/
name: ingress-nginx
version: 2.11.1
values:
config:
ssl-redirect: "false" # We don't need this as NGINX isn't using any TLS certificates itself
use-forwarded-headers: "true" # NGINX will now decide whether it will do redirection based on these headers
controller:
service:
targetPorts:
https: http # NGINX will never get HTTPS traffic, TLS is handled by load balancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "<CERTIFICATE_ARN>"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-type: "elb"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
name: <INGRESS_NAME>
namespace: <NAMESPACE>
spec:
rules:
- host: <CUSTOM_HOST>
http:
paths:
- path: /
backend:
serviceName: <WHATEVER>
servicePort: <SOME_PORT> NLBThere are two choices when it comes to NLBs. Unfortunately, at least from my point of view, the preferred option isn't available at the time of this writing because of this open issue My preferred option (Not possible until this is resolved)
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
name: <RELEASE_NAME>
namespace: <NAMESPACE>
spec:
chart:
repository: https://kubernetes.github.io/ingress-nginx/
name: ingress-nginx
version: 2.11.1
values:
config:
ssl-redirect: "false" # We don't need this as NGINX isn't using any TLS certificates itself
use-proxy-protocol: "true" # NGINX will now decide whether it will do redirection based on these headers
controller:
service:
targetPorts:
https: http # NGINX will never get HTTPS traffic, TLS is handled by load balancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "<CERTIFICATE_ARN>"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
name: <INGRESS_NAME>
namespace: <NAMESPACE>
spec:
rules:
- host: <CUSTOM_HOST>
http:
paths:
- path: /
backend:
serviceName: <WHATEVER>
servicePort: <SOME_PORT> Workaround by manipulating portsPlease check @KongZ comment on this issue. |
Thanks @KongZ it works fine with NLB
Complete configmap as a reference:
Add the following lines in
More lines from deployments.
When you save&exit deployments, it will create new ingress-nginx pod. finally, add the following annotations lines into your app ingress
Complete app ingress yml
then update it And let's test it
|
I ran into the same problem, it works for most of services except Keycloak, tried adding
to the ingress-nginx configmap as you suggested but still not work, any advice? |
Following this solution: kubernetes/ingress-nginx#2724 (comment) Tested it with both no https and with https. ALL SERVICES WILL REDIRECT PUBLIC TRAFFIC HTTP TO HTTPS IF SSL IS PRESENT, NO EXCEPTION
Following this solution: kubernetes/ingress-nginx#2724 (comment) Tested it with both no https and with https. ALL SERVICES WILL REDIRECT PUBLIC TRAFFIC HTTP TO HTTPS IF SSL IS PRESENT, NO EXCEPTION
|
@ngocketit got anything? |
@samrakshak As I mentioned, putting the server snippet in Helm didn't work for me so I had to put it in every ingress (with |
@ngocketit now I am getting the following error: error:1408F10B:SSL routines:ssl3_get_record:wrong version number I have used a AWS NLB and the certificate is being issued by certmanager/let's encrypt . I want TLS termination but I think as TLS is not termination I am facing this issue. |
Using helm ingress-nginx chart on EKS Edit service/ingress-nginx-controller by adding Setup your port in the ingress controller to look like what I have below:
Now Edit ingress controller deployment containerPort
|
@Ariseaz - I applied the suggested workaround and its working. Thank you @Ariseaz But , Today I installed pgadmin service in my EKS cluster and its redirection to special port 8000. Could you please suggest where I am doing mistake. Below are the yamls deployment.yaml
service.yaml
resource ingress yaml
|
Followed @Ariseaz suggestion and I was able to redirect to https but it did not work when I enable Proxy protocol v2 on the NLB for forwarding the client real ip. I was able to get it it fixed both https redirct and client ip by following this page Change this in service `spec:
and this in deployment `ports:
Hope this helps for anyone looking for similar solution |
@KongZ
why we even need 8000 port ? also why we need this
instead of
|
@StepanKuksenko I'm no longer using nginx controllers for years. Hope this description is still valid.
Because we need 80 to handle HTTP and response 308.
Because it is a spec. It accepts only "ssl" or "tcp" |
* adding instrumentation to docker compose * updating notes * enabling instrumentation, adding logging + k8s con * switching to debug level logging in flask * adding nginx.conf in image buil * updating conf to include proxy_pass to flask * updating expected envvars for RUM init * enabling rum + calling envvars * adding base path /api k8s deploy for axios call * removing hashbang from base url of served vue app * adding k8s-config deployment files * adding dockerfile for mongodb container * removing carryover unused components * updating notes * dynamicallu assigning api call routes * updating backend routes to include /api * adding dynamic app build env var for vue * updating styles and correcting logo click behavior * removing unused component from router * calling api routes dynamically * updating notes * updating nginx server conf in case of page refresh * adding notes for finding custom theming * shell script for applying all yaml files in dir * always pull image + adding envvars to vue * adding ingress resource * updating api version for ingress resource * updating namspace to default * adding helm values * updating clustername * updating clustername * updating target type for ingress * updating ingress annotations * updating namespace * updating namespace * updating namespace for ingress to default * adding elb * adding ingress controller * updating type of vue service to LoadBalancer * updating yaml files * adding kubeadm init config * updating init-config * updating init-config * updating init file * enable apm in values.yaml * updating for dev * updating notes * adding recapchta server validation * updating flask reqs for recaptcha * adding recaptcha and datadog-ci * hide recaptcha badge * adding recaptcha and email validation * adding favicon * adding sh script for building/pushing imgs * adding debounce for window resize event listener * adding link to faviconn * adding debounce dep * removing unused dependency * adding docker updates * update flask to read from config * add config.py to container deploy * add dev containerized build for vue * update host for dev build to 0.0.0.0 * update vales for dd-helm to pull latest agent * adding default nginx config /etc/nginx * updateing vuenotes * move docker_push * adding nginx w/apm dockerfile * adding trace propogation to nginx * update main nginx.conf- /etc/nginx * adding apm specific docker entrypoint * adding shell script to generate the ddtrace config * update values to include commented config * adding envvars to flask deploy + logs source * adding ust + apm to vue deploy * adding source annotations to mongo deploy * removing unnecessary NodePort type from svcs * adding more notes * adding headless option to flask config * adding hl ss and svc * updating to prevent conflict * adding tls encryption * adding host to rule * udating targetPort for https to nlb to 80 * updating app protocol to http * updating ingress service to use ssl * adding ssl redirect annotations * removing ssl redirect at ingress level * removing tls at ingress resource * removing tls updates * adding default ssl cert to controller deployment * adding tls options back to ingress * adding ingressclassname * kubernetes/ingress-nginx#2724 (comment) * small updates * removing unnecessary tls at Ingress * cleaning up ingress * removing default ssl opt * cleaning up nginx-elb * updating notes * updating mongo deploy to always pull image * statefulset image config for mongo * adding updates to ingress for aws deploy on dev * removing duplicate init files * adding notes * adding multiConnect config to flask config file * adding working statefulset image * adding authorization to mongo statefulset * adding updated mongo init file and script for RS * adding dd annotations to mongodb * improve css styling * improve hamburger animation * add playfair font as default * update year in bottombar * update .ignore to add DS_STORE * update values for kubeadm * add ingress controller tracing * update service name of ingress * adding clusterconf * update bind addr for contollermgr and scheduler * update ing contr servicename for tracing * add pv for mongo ss * updating mongo init for envvar ref * udpating notes * update log format for trace id injection * update rum init config in vue app * add testing values.yaml for helm deployment * update img of vue deploy to latest * delete unused conf file * fix merge conflict * update flask image to latest * add env to nginx ingress tracing config * add modsecurity configmap * update nginx ingr controller to enable modsecurity * add to-do in notes * fixing vuenotes * upgrading datadog-ci * update ns for modsec configmap * add dd-env to nginx-elb * enable logging for debugging modsec * update flask * enable rule processing * update notes * clean up logging in flask * update dockerpush to accept alt dockerfile path * update aboutme description * fix docker push * update ps-vue version
What keywords did you search in NGINX Ingress controller issues before filing this one? (If you have found any duplicates, you should instead reply there.):
Issues #2000 an #1957 touch on this, with #1957 suggesting its was fixed. Searched 308, redirect, TCP, aws, elb, proxy etc.
NGINX Ingress controller version:
v0.16.2
Kubernetes version (use
kubectl version
):v1.9.6
Environment:
AWS
What happened:
With this ingress that creates an ELB handling TLS termination.
And these nginx settings asking for
force-ssl-redirect
requesting
http://example.com
will result in a 308 redirect loop. withforce-ssl-redirect: false
it works fine, but no http -> https redirect.What you expected to happen:
I expect http://example.com to be redirected to https://example.com by the ingress controller.
How to reproduce it (as minimally and precisely as possible):
Spin up an example with the settings above, default backend, ACM cert and dummy Ingress for it to attach to. then attempt to request the
http://
emdpoint.The text was updated successfully, but these errors were encountered: