How NGINX Ingress controller back-end protocol annotation works in path based routing?

11/2/2020

I'm currently playing with NGINX ingress controller in my k8s cluster. I was trying to make end-to-end encryption work and I was able to make the connection secure all the way to the pod.

In order to achieve HTTPS all the way till pod, I had to use annotation

nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"

Sample Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo-api-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  tls:
  - hosts:
    - foo.example.com
    secretName: foo-cert
  rules:
  - host: foo.example.com
    http:
      paths:
      - path: /path1
        backend:
          serviceName: foo-api-path1-service
          servicePort: 443
      - path: /path2
        backend:
          serviceName: foo-api-path2-service
          servicePort: 443

I'm confused in terms of how exactly this happens because when we encrypt the connection path also get encrypted then how NGINX does path-based routing? does it decrypt the connection at ingress and re-encrypt it? also, does performance get affected by using this method?

-- Sam
kubernetes
kubernetes-ingress
nginx
nginx-ingress
ssl

1 Answer

11/3/2020

TL;DR

does it decrypt the connection at ingress and re-encrypt it?

In short, yes. Please see the explanation below.


Explanation

The path that a request is travelling to get to a Pod can be seen as:

REQUEST-PATH

Assuming that we have an Ingress controller (nginx-ingress) in place of an Ingress you can have several ways to connect your client with a Pod (simplified):

  • Unencrypted:
    • client -- (HTTP) --> Ingress controller -- (HTTP) --> Service ----> Pod

  • Encrypted at the Ingress controller (with nginx.ingress.kubernetes.io/backend-protocol: "HTTPS")
    • client -- (HTTP) --> Ingress controller -- (HTTPS) --> Service ----> Pod

  • Encrypted and decrypted at the Ingress controller where TLS Termination happens:
    • client -- (HTTPS) --> Ingress controller (TLS Termination) -- (HTTP) --> Service ----> Pod

Your setup:

  • Encrypted and decrypted at the Ingress controller where TLS Termination happens and encrypted once again when connecting with a HTTPS backend by nginx.ingress.kubernetes.io/backend-protocol: "HTTPS":
    • client -- (HTTPS) --> Ingress controller (TLS Termination) -- (HTTPS) --> Service ----> Pod

  • Encrypted and decrypted at the Pod where Ingress controller is configured with SSL Passthrough:
    • client -- (HTTPS) --> Ingress controller -- (HTTPS) --> Service ----> Pod

Disclaimer!

This is only a simplified explanation. For more reference you can look at this comment:

there is a missing detail here, the SSL Passthrough traffic never reaches NGINX in the ingress controller. There is a go listener for TLS connections that just pipes the traffic to the service defined in the ingress.



For more reference you can look on the similar question (with an answer):

You can also check this article with example setup similar to yours:


Additional resources:

-- Dawid Kruk
Source: StackOverflow