How do you find the original protocol (or port) of requests where Kubernetes is terminating SSL?

11/7/2019

I am wanting to achieve the follow redirections and ensure that they all happen in one step:

I have a Kubernetes (1.15.5) cluster on Digital Ocean using stable/nginx-ingress (installed via helm) and also using cert-manager to handle SSLs.

In my Ingress config I have disabled ssl redirection as I want to handle this in the services themselves:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: proxy
  namespace: default
  annotations:
    kubernetes.io/tls-acme: "true"
    kubernetes.io/ingress.class: "nginx"
    certmanager.k8s.io/issuer: "letsencrypt-prod"
    certmanager.k8s.io/acme-challenge-type: http01
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  tls:
  - hosts:
    - example.com
    - www.example.com
    secretName: tls-example-com
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: nginx-service
          servicePort: 80
  - host: www.example.com
    http:
      paths:
      - backend:
          serviceName: nginx-service
          servicePort: 80

One of my services is a nginx server:

server {
    server_name  example.com;
    return 301 https://wwww.$host$request_uri;
}

server {
    server_name  www.example.com;

    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    }

    # app
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

However, $scheme here, is always '"http"', which makes sense as my service only receives requests on port 80. But just as the original address (host information) is forwarded to my service, how can I find out what the original port was?

-- Thomas Nadin
kubernetes
nginx
nginx-ingress
nginx-reverse-proxy
ssl

1 Answer

11/7/2019

The nginx set up by the ingress controller acts as a reverse proxy and inserts X-Forwarded-* headers for the services behind it to read. Your service has to use those to get the correct client ip, port or scheme.

For nginx you can use $http_x_forwarded_proto:

  if ($http_x_forwarded_proto != "https") {
    return 301 https://$host$request_uri;
  }
-- koe
Source: StackOverflow