Mutual TLS and Istio

Before Start

You should have NO virtualservice, destinationrule, gateway or policy (in tutorial namespace) kubectl get virtualservice kubectl get destinationrule kubectl get gateway kubectl get policy if so run:

./scripts/clean.sh

In this chapter, we are going to see how to secure the communication between all services by enabling mutual TLS in Istio.

Testing mTLS

Depending on how you install Istio, you have mTLS enabled or not. If you have followed this guide and installed the demo profile (Setup), then mTLS is not enabled.

To check if mTLS is enabled or not just run the next command:

istioctl authn tls-check $(kubectl get pods -n tutorial|grep customer|awk '{ print $1 }'|head -1) customer.tutorial.svc.cluster.local
HOST:PORT                                    STATUS     SERVER         CLIENT     AUTHN POLICY     DESTINATION RULE
customer.tutorial.svc.cluster.local:8080     OK         PERMISSIVE     -          /default         -

If CLIENT is with - means that mTLS is not enabled.

To enable mTLS:

kubectl create -f istiofiles/authentication-enable-tls.yml -n tutorial
kubectl create -f istiofiles/destination-rule-tls.yml -n tutorial

To check that mTLS is enabled run the next command:

istioctl authn tls-check $(kubectl get pods -n tutorial|grep customer|awk '{ print $1 }'|head -1) customer.tutorial.svc.cluster.local
HOST:PORT                                    STATUS     SERVER     CLIENT           AUTHN POLICY         DESTINATION RULE
customer.tutorial.svc.cluster.local:8080     OK         STRICT     ISTIO_MUTUAL     tutorial/default     tutorial/default

Check the mTLS by sniffing traffic between services, which is a bit more tedious, open a new terminal tab and run next command:

CUSTOMER_POD=$(kubectl get pod | grep cust | awk '{ print $1}' ) (1)
kubectl exec -it $CUSTOMER_POD -c istio-proxy /bin/bash (2)
1 Get customer pod name
2 Open a shell inside pod

Inside pod shell

ifconfig (1)
sudo tcpdump -vvvv -A -i eth0 'dst port 8080) and (net 172.17.0.10' (2)
1 Get IP of current pod (probably the IP represented at eth0 interface)
2 Capture traffic from eth0 (or your interface) of port 8080 and network 172.17.0.10 (your IP from ifconfig)

Now all communication that happens between customer service and preference service is dumped in the console.

So now go to a terminal and execute:

customer => preference => recommendation v1 from 'b87789c58-mfrhr': 2

Obviously, the response is exactly the same, but if you go to the terminal where you are executing tcpdump, you should see something like:

Z.!.X/K.............w$.?....&T...=..=..y..[.k..g..0..5.f%..vz|..t.....%..|...B..%r0.^k.y.....y.@l$O.....?...J..qc&...
.n$X.....l.#...... ..Q..u..jBI.Z.Eb$9.$.._...!.........~"Xx<....);........Z.
.y/E]......K......... .@s.3.\.

Notice that you cannot see any detail about the communication since it happened through TLS.

Now, let’s disable TLS:

kubectl replace -f istiofiles/disable-mtls.yml

And execute again:

customer => preference => recommendation v1 from 'b87789c58-mfrhr': 2

And again check tcpdump output:

host: 0192.168.64.70:31380
user-agent: curl/7.54.0
accept: */*
x-forwarded-for: 172.17.0.1
x-forwarded-proto: http
x-envoy-internal: true
x-request-id: e5c0b90f-341b-9edc-ac3e-7dd8b33f0e8b
x-envoy-decorator-operation: customer.tutorial.svc.cluster.local:8080/
x-b3-traceid: ce289e960a639d11
x-b3-spanid: ce289e960a639d11
x-b3-sampled: 1

Now, you can see that since there is no TLS enabled, the information is not shadowed but in clear.

Clean Up

kubectl delete -f istiofiles/disable-mtls.yml
kubectl delete -f istiofiles/destination-rule-tls.yml

or you can run:

./scripts/clean.sh