<p>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.</p>
<p>In order to achieve HTTPS all the way till pod, I had to use annotation</p>
<pre><code>nginx.ingress.kubernetes.io/backend-protocol: &quot;HTTPS&quot;
</code></pre>
<p>Sample Ingress:</p>
<pre><code>apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: foo-api-ingress
  annotations:
    kubernetes.io/ingress.class: &quot;nginx&quot;
    nginx.ingress.kubernetes.io/backend-protocol: &quot;HTTPS&quot;
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
</code></pre>
<p>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?</p>

<p><strong>TL;DR</strong></p>
<blockquote>
<p>does it decrypt the connection at ingress and re-encrypt it?</p>
</blockquote>
<p>In short, yes. Please see the explanation below.</p>
<hr />
<h3>Explanation</h3>
<p>The path that a request is travelling to get to a <code>Pod</code> can be seen as:</p>
<p><a href="https://i.stack.imgur.com/RiUnf.png" rel="noreferrer"><img src="https://i.stack.imgur.com/RiUnf.png" alt="REQUEST-PATH" /></a></p>
<ul>
<li><em><a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" rel="noreferrer">Kubernetes.io: Docs: Concepts: Services networking: Ingress</a></em></li>
</ul>
<p>Assuming that we have an <code>Ingress controller</code> (<code>nginx-ingress</code>) in place of an <code>Ingress</code> you can have several ways to connect your client with a <code>Pod</code> (simplified):</p>
<ul>
<li>Unencrypted:
<ul>
<li><code>client</code> -- (HTTP) --&gt; <code>Ingress controller</code> -- (HTTP) --&gt; <code>Service</code> ----&gt; <code>Pod</code></li>
</ul>
</li>
</ul>
<hr />
<ul>
<li>Encrypted at the <code>Ingress controller</code> (with <code>nginx.ingress.kubernetes.io/backend-protocol: &quot;HTTPS&quot;</code>)
<ul>
<li><code>client</code> -- (HTTP) --&gt; <code>Ingress controller</code> -- (HTTP<strong>S</strong>) --&gt; <code>Service</code> ----&gt; <code>Pod</code></li>
</ul>
</li>
</ul>
<hr />
<ul>
<li>Encrypted and decrypted at the <code>Ingress controller</code> where <a href="https://kubernetes.github.io/ingress-nginx/examples/tls-termination/#tls-termination" rel="noreferrer">TLS Termination</a> happens:
<ul>
<li><code>client</code> -- (HTTP<strong>S</strong>) --&gt; <code>Ingress controller</code> (TLS Termination) -- (HTTP) --&gt; <code>Service</code> ----&gt; <code>Pod</code></li>
</ul>
</li>
</ul>
<hr />
<p><strong>Your setup:</strong></p>
<ul>
<li>Encrypted and decrypted at the <code>Ingress</code> controller where <a href="https://kubernetes.github.io/ingress-nginx/examples/tls-termination/#tls-termination" rel="noreferrer">TLS Termination</a> happens and <strong>encrypted once again</strong> when connecting with a HTTPS backend by <code>nginx.ingress.kubernetes.io/backend-protocol: &quot;HTTPS&quot;</code>:
<ul>
<li><code>client</code> -- (HTTP<strong>S</strong>) --&gt; <code>Ingress controller</code> (TLS Termination) -- (HTTP<strong>S</strong>) --&gt; <code>Service</code> ----&gt; <code>Pod</code></li>
</ul>
</li>
</ul>
<hr />
<ul>
<li>Encrypted and decrypted at the <code>Pod</code> where <code>Ingress controller</code> is configured with <a href="https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#ssl-passthrough" rel="noreferrer">SSL Passthrough</a>:
<ul>
<li><code>client</code> -- (HTTP<strong>S</strong>) --&gt; <code>Ingress controller</code> -- (HTTP<strong>S</strong>) --&gt; <code>Service</code> ----&gt; <code>Pod</code></li>
</ul>
</li>
</ul>
<blockquote>
<p><strong>Disclaimer!</strong></p>
<p>This is only a simplified explanation. For more reference you can look at this comment:</p>
<blockquote>
<p>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.</p>
<ul>
<li><em><a href="https://github.com/kubernetes/ingress-nginx/issues/5618" rel="noreferrer">Github.com: Kubernetes: Ingress nginx: Issues: 5618</a></em></li>
</ul>
</blockquote>
</blockquote>
<hr />
<hr />
<p>For more reference you can look on the similar question (with an answer):</p>
<ul>
<li><em><a href="https://stackoverflow.com/a/54459898/12257134">Stackoverflow.com: Answer: How to configure ingress to direct traffic to an https backend using https</a></em></li>
</ul>
<p>You can also check this article with example setup similar to yours:</p>
<ul>
<li><em><a href="https://code.oursky.com/how-to-enable-tls-https-between-your-kubernetes-ingress-and-back-end-deployments/" rel="noreferrer">Code.oursky.com: How to enable tls https between your kubernetes ingress and back end deployments</a></em></li>
</ul>
<hr />
<p>Additional resources:</p>
<ul>
<li><em><a href="https://github.com/kubernetes/ingress-nginx/issues/6142" rel="noreferrer">Github.com: Kubernetes: Ingress nginx: Is it possible to have secure backend connections from the nginx controller?</a></em></li>
<li><em><a href="https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/nginx-configuration/annotations.md#backend-certificate-authentication" rel="noreferrer">Github.com: Kubernetes: Ingress nginx: Nginx configuration: Annotations: Backend certificate authentication</a></em></li>
</ul>
