Ingress Gateway without TLS Termination

The Securing Gateways with HTTPS task describes how to configure HTTPS ingress access to an HTTP service. This example describes how to configure HTTPS ingress access to an HTTPS service, i.e., configure an ingress gateway to perform SNI passthrough, instead of TLS termination on incoming requests.

The example HTTPS service used for this task is a simple NGINX server. In the following steps you first deploy the NGINX service in your Kubernetes cluster. Then you configure a gateway to provide ingress access to the service via host nginx.example.com.

Generate client and server certificates and keys

For this task you can use your favorite tool to generate certificates and keys. The commands below use openssl

  1. Create a root certificate and private key to sign the certificate for your services:

    1. $ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
  2. Create a certificate and a private key for nginx.example.com:

    1. $ openssl req -out nginx.example.com.csr -newkey rsa:2048 -nodes -keyout nginx.example.com.key -subj "/CN=nginx.example.com/O=some organization"
    2. $ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in nginx.example.com.csr -out nginx.example.com.crt

Deploy an NGINX server

  1. Create a Kubernetes Secret to hold the server’s certificate.

    1. $ kubectl create secret tls nginx-server-certs --key nginx.example.com.key --cert nginx.example.com.crt
  2. Create a configuration file for the NGINX server:

    1. $ cat <<\EOF > ./nginx.conf
    2. events {
    3. }
    4. http {
    5. log_format main '$remote_addr - $remote_user [$time_local] $status '
    6. '"$request" $body_bytes_sent "$http_referer" '
    7. '"$http_user_agent" "$http_x_forwarded_for"';
    8. access_log /var/log/nginx/access.log main;
    9. error_log /var/log/nginx/error.log;
    10. server {
    11. listen 443 ssl;
    12. root /usr/share/nginx/html;
    13. index index.html;
    14. server_name nginx.example.com;
    15. ssl_certificate /etc/nginx-server-certs/tls.crt;
    16. ssl_certificate_key /etc/nginx-server-certs/tls.key;
    17. }
    18. }
    19. EOF
  3. Create a Kubernetes ConfigMap to hold the configuration of the NGINX server:

    1. $ kubectl create configmap nginx-configmap --from-file=nginx.conf=./nginx.conf
  4. Deploy the NGINX server:

    1. $ cat <<EOF | istioctl kube-inject -f - | kubectl apply -f -
    2. apiVersion: v1
    3. kind: Service
    4. metadata:
    5. name: my-nginx
    6. labels:
    7. run: my-nginx
    8. spec:
    9. ports:
    10. - port: 443
    11. protocol: TCP
    12. selector:
    13. run: my-nginx
    14. ---
    15. apiVersion: apps/v1
    16. kind: Deployment
    17. metadata:
    18. name: my-nginx
    19. spec:
    20. selector:
    21. matchLabels:
    22. run: my-nginx
    23. replicas: 1
    24. template:
    25. metadata:
    26. labels:
    27. run: my-nginx
    28. spec:
    29. containers:
    30. - name: my-nginx
    31. image: nginx
    32. ports:
    33. - containerPort: 443
    34. volumeMounts:
    35. - name: nginx-config
    36. mountPath: /etc/nginx
    37. readOnly: true
    38. - name: nginx-server-certs
    39. mountPath: /etc/nginx-server-certs
    40. readOnly: true
    41. volumes:
    42. - name: nginx-config
    43. configMap:
    44. name: nginx-configmap
    45. - name: nginx-server-certs
    46. secret:
    47. secretName: nginx-server-certs
    48. EOF
  5. To test that the NGINX server was deployed successfully, send a request to the server from its sidecar proxy without checking the server’s certificate (use the -k option of curl). Ensure that the server’s certificate is printed correctly, i.e., common name (CN) is equal to nginx.example.com.

    1. $ kubectl exec "$(kubectl get pod -l run=my-nginx -o jsonpath={.items..metadata.name})" -c istio-proxy -- curl -sS -v -k --resolve nginx.example.com:443:127.0.0.1 https://nginx.example.com
    2. ...
    3. SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
    4. ALPN, server accepted to use http/1.1
    5. Server certificate:
    6. subject: CN=nginx.example.com; O=some organization
    7. start date: May 27 14:18:47 2020 GMT
    8. expire date: May 27 14:18:47 2021 GMT
    9. issuer: O=example Inc.; CN=example.com
    10. SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    11. > GET / HTTP/1.1
    12. > User-Agent: curl/7.58.0
    13. > Host: nginx.example.com
    14. ...
    15. < HTTP/1.1 200 OK
    16. < Server: nginx/1.17.10
    17. ...
    18. <!DOCTYPE html>
    19. <html>
    20. <head>
    21. <title>Welcome to nginx!</title>
    22. ...

Configure an ingress gateway

  1. Define a Gateway with a server section for port 443. Note the PASSTHROUGH TLS mode which instructs the gateway to pass the ingress traffic AS IS, without terminating TLS.

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: Gateway
    4. metadata:
    5. name: mygateway
    6. spec:
    7. selector:
    8. istio: ingressgateway # use istio default ingress gateway
    9. servers:
    10. - port:
    11. number: 443
    12. name: https
    13. protocol: HTTPS
    14. tls:
    15. mode: PASSTHROUGH
    16. hosts:
    17. - nginx.example.com
    18. EOF
  2. Configure routes for traffic entering via the Gateway:

    1. $ kubectl apply -f - <<EOF
    2. apiVersion: networking.istio.io/v1alpha3
    3. kind: VirtualService
    4. metadata:
    5. name: nginx
    6. spec:
    7. hosts:
    8. - nginx.example.com
    9. gateways:
    10. - mygateway
    11. tls:
    12. - match:
    13. - port: 443
    14. sniHosts:
    15. - nginx.example.com
    16. route:
    17. - destination:
    18. host: my-nginx
    19. port:
    20. number: 443
    21. EOF
  3. Follow the instructions in Determining the ingress IP and ports to define the SECURE_INGRESS_PORT and INGRESS_HOST environment variables.

  4. Access the NGINX service from outside the cluster. Note that the correct certificate is returned by the server and it is successfully verified (SSL certificate verify ok is printed).

    1. $ curl -v --resolve "nginx.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" --cacert example.com.crt "https://nginx.example.com:$SECURE_INGRESS_PORT"
    2. Server certificate:
    3. subject: CN=nginx.example.com; O=some organization
    4. start date: Wed, 15 Aug 2018 07:29:07 GMT
    5. expire date: Sun, 25 Aug 2019 07:29:07 GMT
    6. issuer: O=example Inc.; CN=example.com
    7. SSL certificate verify ok.
    8. < HTTP/1.1 200 OK
    9. < Server: nginx/1.15.2
    10. ...
    11. <html>
    12. <head>
    13. <title>Welcome to nginx!</title>

Cleanup

  1. Remove created Kubernetes resources:

    1. $ kubectl delete secret nginx-server-certs
    2. $ kubectl delete configmap nginx-configmap
    3. $ kubectl delete service my-nginx
    4. $ kubectl delete deployment my-nginx
    5. $ kubectl delete gateway mygateway
    6. $ kubectl delete virtualservice nginx
  2. Delete the certificates and keys:

    1. $ rm example.com.crt example.com.key nginx.example.com.crt nginx.example.com.key nginx.example.com.csr
  3. Delete the generated configuration files used in this example:

    1. $ rm ./nginx.conf

See also

Istio as a Proxy for External Services

Configure Istio ingress gateway to act as a proxy for external services.

Direct encrypted traffic from IBM Cloud Kubernetes Service Ingress to Istio Ingress Gateway

Configure the IBM Cloud Kubernetes Service Application Load Balancer to direct traffic to the Istio Ingress gateway with mutual TLS.

Deploy a Custom Ingress Gateway Using Cert-Manager

Describes how to deploy a custom ingress gateway using cert-manager manually.

Configuring Istio Ingress with AWS NLB

Describes how to configure Istio ingress with a network load balancer on AWS.

Consuming External Web Services

Describes a simple scenario based on Istio’s Bookinfo example.

Configuring Gateway Network Topology [Experimental]

How to configure gateway network topology (experimental).