Istio gateway with mtls

This page will introduce how to use mtls with istio gateway.

1. Deploy a nginx application

First, deploy a simple Nginx pod and its Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.23
        ports:
        - containerPort: 80

Save this file to nginx.yaml and apply it to kubernetes cluster.

kubectl apply -f nginx.yaml

2. Create Istio Gateway and VirtualService

Next, we create Istio Gateway and VirtualService to expose the Nginx service, while enabling mTLS.

apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: mtls-sample
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: MUTUAL
      credentialName: nginx-mtls
    hosts:
    - "nginx-sample.amyinfo.com"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: nginx-sample
spec:
  hosts:
  - "nginx-sample.amyinfo.com"
  gateways:
  - mtls-sample
  http:
  - route:
    - destination:
        host: nginx
        port:
          number: 80

Apply this YAML file to cluster.

kubectl apply -f nginx-gateway.yaml

3. Create Kubernetes Secret

To enable mTLS, we need to create a Kubernetes Secret that contains the certificates and keys for both the server and the client. First, generate a self-signed CA, server certificate and key, Client certificate and key using openssl :

openssl req -x509 -newkey rsa:4096 -keyout ca-key.pem -out ca-cert.pem -days 365 -nodes -subj "/CN=amyinfo.com"

# Generate server certificate and key
openssl req -newkey rsa:4096 -keyout server-key.pem -out server-req.pem -nodes -subj "/CN=nginx-sample.amytin.com"
openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem -days 365

# Generate client certificate and key
openssl req -newkey rsa:4096 -keyout client-key.pem -out client-req.pem -nodes -subj "/CN=client"
openssl x509 -req -in client-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem -days 365

Then create the server certificate and key as Kubernetes Secret:

kubectl create -n istio-system secret generic nginx-mtls \
  --from-file=tls.key=server-key.pem \
  --from-file=tls.crt=server-cert.pem \
  --from-file=ca.crt=ca-cert.pem

4. Test with curl

Pass the Client certificate and key to curl to test mTLS:

curl --cacert ca-cert.pem \
    --cert client-cert.pem \
    --key client-key.pem https://nginx-sample.amyinfo.com

5. Q & A

5.1 iptables problem on Fedora

Command error output: xtables parameter problem: iptables-restore: unable to initialize table ‘nat’ Error occurred at line: 1

Try `iptables-restore -h’ or ‘iptables-restore –help’ for more information.

Istio use iptables to intercept traffic by adding nat rules. So all Linux hosts should enable netfilter linux kernel modules by running the below command.

 modprobe br_netfilter; 
 modprobe nf_nat; 
 modprobe xt_REDIRECT; 
 modprobe xt_owner;
 modprobe iptable_nat; 
 modprobe iptable_mangle; 
 modprobe iptable_filter;

Or make it persistent.

cat >> /etc/modules-load.d/istio-iptables.conf <<"EOF"
br_netfilter
nf_nat
xt_REDIRECT
xt_owner
iptable_nat
iptable_mangle
iptable_filter
EOF
Tags: kubernetes
Share: X (Twitter) Facebook LinkedIn