This topic describes how to use an Istio gateway to enable Transport Layer Security (TLS) pass-through. You can enable TLS pass-through to ensure secure access to HTTPS services in a cluster.

Prerequisites

Step 1: Prepare a server certificate and private key pair

If you have an available server certificate and private key pair for the sample.aliyun.com domain name, rename the private key to sample.aliyun.com.key and the server certificate to sample.aliyun.com.crt. Alternatively, run the following openssl commands to create a server certificate and private key pair for sample.aliyun.com.

  1. Run the following command to create a root certificate and a private key:
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=mynginx Inc./CN=aliyun.com' -keyout aliyun.root.key -out aliyun.root.crt 
  2. Run the following commands to generate a server certificate and private key pair for the server of sample.aliyun.com:
    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

Step 2: Define an internal service

The internal services in this example are implemented based on NGINX. You must create a configuration file for the NGINX server first. Take an internal service of the aliyun.com domain name as an example. Define the requested root path to directly return the sentence Welcome to aliyun.com without TLS Termination!and status code 200. The following code shows the content of the mynginx.conf file:

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;
    location / {
        return 200 'Welcome to aliyun.com without TLS Termination!';
        add_header Content-Type text/plain;
    }
    server_name www.aliyun.com;
    ssl_certificate /etc/nginx-server-certs/tls.crt;
    ssl_certificate_key /etc/nginx-server-certs/tls.key;
  }
}
  1. In the cluster to which the ingress gateway pod belongs, run the following command to create a ConfigMap for storing the configuration of the NGINX server:
    ​kubectl create configmap mynginx-configmap --from-file=nginx.conf=./mynginx.conf​
  2. In the cluster to which the ingress gateway pod belongs, run the following command to create a secret that contains the server certificate and private key pair in the default namespace:
    ​kubectl create secret tls nginx-server-certs --key sample.aliyun.com.key --cert sample.aliyun.com.crt​
  3. In the cluster to which the ingress gateway pod belongs, run the following command to enable automatic sidecar injection for the default namespace:
    kubectl label namespace default istio-injection=enabled
  4. Create a mynginxapp.yaml file that contains the following content. Then, run the kubectl apply -f mynginxapp.yaml command to create an internal service for the aliyun.com domain name.
    apiVersion: v1
    kind: Service
    metadata:
      name: mynginxapp
      labels:
        app: mynginxapp
    spec:
      ports:
      - port: 443
        protocol: TCP
      selector:
        app: mynginxapp
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: mynginxapp
    spec:
      selector:
        matchLabels:
          app: mynginxapp
      replicas: 1
      template:
        metadata:
          labels:
            app: mynginxapp
        spec:
          containers:
          - name: 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: mynginx-configmap
          - name: nginx-server-certs
            secret:
              secretName: nginx-server-certs    
  5. Run the following command to send a request from the sidecar to the NGINX server to check whether the NGINX server is deployed:
    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.com

Step 3: Define an Istio gateway

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. 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 of the ASM instance.
  4. On the details page of the ASM instance, choose Traffic Management > Gateway in the left-side navigation pane. On the Gateway page, click Create.
  5. In the Create panel, perform the following steps to define a virtual service. Then, click OK.
    1. Select a namespace as required. In this example, the default namespace is used.
    2. In the code editor, define an Istio gateway. The following code shows a sample YAML file:
      apiVersion: networking.istio.io/v1alpha3
      kind: Gateway
      metadata:
        name: istio-mynginx-customingressgateway
      spec:
        selector:
          istio: ingressgateway
        servers:
        - hosts:
          - 'sample.aliyun.com'
          port:
            name: https
            number: 443
            protocol: HTTPS
          tls:
            mode: PASSTHROUGH
    On the Gateway page, you can view the created Istio gateway.

Step 4: Define a virtual service

  1. Log on to the ASM console.
  2. In the left-side navigation pane, choose Service Mesh > Mesh Management.
  3. 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 of the ASM instance.
  4. On the details page of the ASM instance, choose Traffic Management > VirtualService in the left-side navigation pane. On the VirtualService page, click Create.
  5. In the Create panel, perform the following steps to define a virtual service. Then, click OK.
    1. Select a namespace as required. In this example, the default namespace is used.
    2. In the code editor, define a virtual service. The following code shows a sample YAML file:
      apiVersion: networking.istio.io/v1alpha3
      kind: VirtualService
      metadata:
        name: istio-mynginx-customvirtualservice
      spec:
        hosts:
        - "sample.aliyun.com"
        gateways:
        - istio-mynginx-customingressgateway
        tls:
        - match:
          - port: 443
            sniHosts:
            - sample.aliyun.com
          route:
          - destination:
              host: mynginxapp.default.svc.cluster.local
              port:
                number: 443
    On the VirtualService page, you can view the created virtual service.

Execution result

Use one of the following methods to query the IP address of the ingress gateway:

  • View the IP address of the ingress gateway in the ASM console. For more information, see Deploy an ingress gateway service.
  • Run the following command on the cluster to which the ingress gateway pod belongs to query the IP address of the ingress gateway:
    kubectl get svc -n istio-system -l istio=ingressgateway
  • Run the following command to access the aliyun.com domain name by using HTTPS:
    curl -v --cacert aliyun.root.crt --resolve sample.aliyun.com:443:xx.xx.xx.xx   https://sample.aliyun.com
    Welcome to aliyun.com without TLS Termination!%