With TLS passthrough, the ingress gateway forwards encrypted TLS traffic directly to backend services without decrypting it. The backend service handles TLS termination instead of the gateway, which keeps the TLS session intact from client to server.
This differs from TLS termination, where the gateway decrypts traffic before forwarding it:
| Mode | TLS terminated at | Use case |
|---|---|---|
| TLS termination | Ingress gateway | Sidecar proxies are injected; traffic between gateway and sidecar travels through an mTLS tunnel |
| TLS passthrough | Backend service | Sidecar proxies are not injected, or other special circumstances require end-to-end encryption without intermediate decryption |
Note: If sidecar proxies are injected, all traffic between the ingress gateway and sidecar proxies travels through a mutual TLS (mTLS) tunnel. In that case, configure TLS termination on the ingress gateway instead.
TLS passthrough relies on Server Name Indication (SNI) to route traffic. Your clients must support the SNI TLS extension.
Prerequisites
Before you begin, make sure that you have:
An ingress gateway is deployed. For more information, see Create an ingress gateway.
An application is deployed in the cluster that is added to the ASM instance. For more information, see Deploy an application in an ACK cluster that is added to an ASM instance.
A domain name with an Internet Content Provider (ICP) filing (
aliyun.comis used as an example in the following steps)kubectl configured to connect to the cluster that hosts the ingress gateway
Step 1: Prepare a server certificate and private key
If you already have a server certificate and private key for sample.aliyun.com, rename them to sample.aliyun.com.crt and sample.aliyun.com.key, then skip to Step 2.
Otherwise, run the following openssl commands to generate self-signed certificates for testing.
Create a root certificate authority (CA):
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \ -subj '/O=mynginx Inc./CN=aliyun.com' \ -keyout aliyun.root.key -out aliyun.root.crtGenerate a server certificate signed by the root CA:
openssl req -out sample.aliyun.com.csr -newkey rsa:2048 -nodes \ -keyout sample.aliyun.com.key \ -subj "/CN=sample.aliyun.com/O=mynginx sample organization" openssl x509 -req -days 365 \ -CA aliyun.root.crt -CAkey aliyun.root.key -set_serial 0 \ -in sample.aliyun.com.csr -out sample.aliyun.com.crt
These commands produce the following files:
| File | Purpose |
|---|---|
aliyun.root.crt / aliyun.root.key | Root CA certificate and private key |
sample.aliyun.com.crt / sample.aliyun.com.key | Server certificate and private key for sample.aliyun.com |
sample.aliyun.com.csr | Certificate signing request (intermediate file) |
Step 2: Deploy an HTTPS backend service
This step deploys an NGINX-based backend service that terminates TLS on port 443. The ingress gateway passes TLS traffic through to this service without decryption.
Create the NGINX configuration
Create a file named mynginx.conf with the following content:
events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
server {
listen 443 ssl;
server_name www.aliyun.com;
ssl_certificate /etc/nginx-server-certs/tls.crt;
ssl_certificate_key /etc/nginx-server-certs/tls.key;
location / {
return 200 'Welcome to aliyun.com without TLS Termination!';
add_header Content-Type text/plain;
}
}
}Create supporting Kubernetes resources
Create a ConfigMap to store the NGINX configuration:
kubectl create configmap mynginx-configmap --from-file=nginx.conf=./mynginx.confCreate a Secret to store the server certificate and private key:
kubectl create secret tls nginx-server-certs \ --key sample.aliyun.com.key --cert sample.aliyun.com.crtEnable automatic sidecar proxy injection for the
defaultnamespace. For more information, see Enable automatic sidecar proxy injection.
Deploy the NGINX service
Create a file named mynginxapp.yaml with the following content, then run kubectl apply -f mynginxapp.yaml:
Verify the backend service
Run the following command to send a test request from the sidecar proxy to the NGINX server:
kubectl exec -it $(kubectl get pod -l app=mynginxapp -o jsonpath={.items..metadata.name}) \
-c istio-proxy -- curl -v -k --resolve sample.aliyun.com:443:127.0.0.1 https://sample.aliyun.comIf the NGINX server is running correctly, the response body contains:
Welcome to aliyun.com without TLS Termination!Step 3: Create an Istio gateway with TLS passthrough
Define a Gateway resource that listens on port 443 and forwards TLS traffic to the backend without termination.
Log on to the ASM console.
In the left-side navigation pane, choose Service Mesh > Mesh Management.
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
In the left-side navigation pane, choose ASM Gateways > Gateway. On the page that appears, click Create from YAML.
Select the default namespace and paste the following YAML:
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: istio-mynginx-customingressgateway spec: selector: istio: ingressgateway # binds to the default ingress gateway servers: - hosts: - 'sample.aliyun.com' port: name: https number: 443 protocol: HTTPS tls: mode: PASSTHROUGH # forward encrypted traffic without terminationClick Create.
The new Gateway appears on the Gateway page.
Step 4: Create a virtual service for TLS routing
Define a VirtualService that routes TLS traffic matching the SNI host sample.aliyun.com to the backend service.
Log on to the ASM console.
In the left-side navigation pane, choose Service Mesh > Mesh Management.
On the Mesh Management page, find the ASM instance that you want to configure. Click the name of the ASM instance or click Manage in the Actions column.
In the left-side navigation pane, choose Traffic Management Center > VirtualService. On the page that appears, click Create from YAML.
Select the default namespace and paste the following YAML:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: istio-mynginx-customvirtualservice spec: hosts: - "sample.aliyun.com" gateways: - istio-mynginx-customingressgateway # reference the Gateway from Step 3 tls: - match: - port: 443 sniHosts: - sample.aliyun.com # route traffic by SNI hostname route: - destination: host: mynginxapp.default.svc.cluster.local # backend service FQDN port: number: 443Click Create.
The new VirtualService appears on the VirtualService page.
Verify the result
Get the IP address of the ingress gateway using one of the following methods:
ASM console: See Substep 1 of Step 3 in Use Istio resources to route traffic to different versions of a service.
kubectl:
kubectl get svc -n istio-system -l istio=ingressgatewayThe
EXTERNAL-IPcolumn shows the gateway IP address.
Send an HTTPS request through the ingress gateway. Replace
<ingress-gateway-ip>with the IP address from the previous step:curl -v --cacert aliyun.root.crt \ --resolve sample.aliyun.com:443:<ingress-gateway-ip> \ https://sample.aliyun.comExpected output:
Welcome to aliyun.com without TLS Termination!This confirms that TLS traffic passes through the ingress gateway to the NGINX backend, which terminates TLS and returns the response.
Clean up
To remove the resources created in this tutorial, run the following commands:
kubectl delete gateway istio-mynginx-customingressgateway
kubectl delete virtualservice istio-mynginx-customvirtualservice
kubectl delete service mynginxapp
kubectl delete deployment mynginxapp
kubectl delete secret nginx-server-certs
kubectl delete configmap mynginx-configmap