TLS passthrough¶
Available since MKE 3.7.0
TLS passthrough is the action of passing data through a load balancer to a server without decrypting it. Usually, the decryption or TLS termination happens at the load balancer and data is passed along to a web server as plain HTTP. TLS passthrough, however, keeps the data encrypted as it travels through the load balancer, with the web server performing the decryption upon receipt. With TLS passthrough enabled in NGINX Ingress Controller, the request will be forwarded to the backend service without being decrypted.
Note
Prior to setting up TLS termination, verify that you have correctly configured kubectl.
Enable TLS passthrough using either the MKE web UI or the MKE configuration file.
Note
You must have MKE admin access to enable TLS passthrough.
To enable TLS passthrough with the MKE web UI, navigate to <username> > Admin Settings > Ingress, scroll down to Advanced Settings and toggle the Enable TLS-Passthrough control on.
To enable TLS passthrough using the MKE configuration file, set the
ingress_extra_args.enable_ssl_passthrough
file parameter under thecluster_config.ingress_controller
option totrue
.[cluster_config.ingress_controller.ingress_extra_args] http_port = 80 https_port = 443 enable_ssl_passthrough = true default_ssl_certificate = ""
Generate a self-signed certificate and a private key for the TLS connection.
Note
The Common Name (CN) in the certificate must match the host name of the server.
mkdir -p example_certs openssl req \ -new \ -newkey rsa:2048 \ -x509 \ -sha256 \ -days 365 \ -nodes \ -subj "/O=Example Inc./CN=nginx.example.com" \ -keyout example_certs/nginx.example.com.key \ -out example_certs/nginx.example.com.crt
Create Kubernetes Secrets for the generated certificate:
kubectl create secret tls nginx-server-certs \ --key example_certs/nginx.example.com.key \ --cert example_certs/nginx.example.com.crt
Deploy a web server.
Create a Kubernetes ConfigMap to retain the configuration of the NGINX server:
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ConfigMap metadata: name: nginx-conf data: nginx.conf: | events { } http { server { listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name nginx.example.com; ssl_certificate /etc/nginx-server-certs/tls.crt; ssl_certificate_key /etc/nginx-server-certs/tls.key; } } EOF
Deploy the NGINX server:
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: my-nginx labels: app: my-nginx spec: ports: - port: 443 protocol: TCP selector: app: my-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: my-nginx spec: selector: matchLabels: app: my-nginx replicas: 1 template: metadata: labels: app: my-nginx spec: containers: - name: my-nginx image: nginx ports: - containerPort: 443 volumeMounts: - name: nginx-config mountPath: /etc/nginx readOnly: true - name: nginx-server-certs mountPath: /etc/nginx-server-certs readOnly: true volumes: - name: nginx-config configMap: name: nginx-configmap > nginx-conf - name: nginx-server-certs secret: secretName: nginx-server-certs EOF
Configure Ingress.
Create a Kubernetes Ingress with the annotation:
nginx.ingress.kubernetes.io/ssl-passthrough: "true"
:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/ssl-passthrough: "true" name: nginx-test spec: ingressClassName: nginx-default rules: - host: nginx.example.com http: paths: - path: / pathType: Prefix backend: service: name: my-nginx port: number: 443 EOF
Test the TLS passthrough by connecting to the application using HTTPS.
In the example below, the TLS connection is being negotiated using the certficate provided for host nginx.example.com. Thus, theTLS connection was passed to the deployed NGINX server.
export MKE_HOST=<mke host> export NODE_PORT=33001 curl -k -v \ --resolve "nginx.example.com:$NODE_PORT:$MKE_HOST" \ "https://nginx.example.com:$NODE_PORT"
Example output:
* Added nginx.example.com:33001:54.218.145.62 to DNS cache * Hostname nginx.example.com was found in DNS cache * Trying 54.218.145.62:33001... * Connected to nginx.example.com (54.218.145.62) port 33001 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/cert.pem * CApath: none * (304) (OUT), TLS handshake, Client hello (1): * (304) (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: O=Example Inc.; CN=nginx.example.com * start date: Nov 29 18:52:39 2022 GMT * expire date: Nov 26 18:52:39 2032 GMT * issuer: O=Example Inc.; CN=nginx.example.com * SSL certificate verify result: self signed certificate (18), continuing anyway. ...
The output shows that the TLS connection is being negotiated with the certificate provided for host
nginx.example.com
, thus confirming that the TLS connection has passed to the deployed NGINX server.Clean up Kubernetes resources that are no longer needed:
kubectl delete deploy my-nginx kubectl delete service my-nginx kubectl delete ingress nginx-test kubectl delete configmap nginx-conf kubectl delete secrets nginx-server-certs