Mutual Transport Layer Security (mTLS) is an important basic feature of Service Mesh (ASM). You need to only inject sidecar proxies into your application pods to enable mTLS, without the need to modify the code of your applications. However, whether mTLS is enabled is imperceptible to users. You cannot intuitively determine whether traffic is encrypted. This topic demonstrates how to check whether mTLS is enabled in an ASM instance.
Background information
Transport Layer Security (TLS) is a security protocol widely used on the Internet, which aims to provide a secure data transmission channel for both ends of communication. Usually, only one-way authentication is performed for common TLS communication. For example, when you use a browser to visit a website over HTTPS, only the website server needs to provide the certificate of the website to prove to you that the server is the legal owner of the website, and you are not required to provide your certificate to prove your identity.
However, in mTLS, the client must also provide its certificate to the server, and both parties need to verify the identity of each other. This ensures that only authorized clients can access the specified server.
The authorization mechanism in ASM uses mTLS to verify the identities of clients. This mutual authentication mechanism ensures that every service call in ASM comes from a trusted client, thereby providing additional security protection for microservices communication.
In the following example, a sleep application is used to access the HTTPBin application. This example demonstrates how to check whether mTLS is enabled in ASM in a direct manner and in an indirect manner.
Prerequisites
An ASM instance is created. For more information, see Create an ASM instance.
A Container Service for Kubernetes (ACK) managed cluster is created. For more information, see Create an ACK managed cluster.
The cluster is added to the ASM instance. For more information, see Add a cluster to an ASM instance.
Automatic sidecar proxy injection is enabled. For more information, see Enable automatic sidecar proxy injection.
The HTTPBin application is deployed and can be accessed. For more information, see Deploy the HTTPBin application.
Step 1: Deploy a sleep application
Use kubectl to connect to the ACK managed cluster that is added to the ASM instance. Then, create a sleep.yaml file with the following content:
Run the following command to deploy the sleep application, which is the test client:
kubectl apply -f sleep.yaml
Step 2: Check whether mTLS is enabled
Check whether mTLS is enabled in an indirect manner by using the header ID
X-FORWARDED-CLIENT-CERT (XFCC) is a proxy header, which indicates certificate information of part or all of the clients or proxies that a request passes through on its way from the client to the server. For more information, see HTTP header manipulation.
When you use the curl command in the sleep application to access the HTTPBin application, the request received by the HTTPBin application carries an XFCC header, which indicates that the request was sent by the sleep application. This header can be used to indirectly determine that mTLS is enabled in communication between the two ends.
Log on to the ASM console. In the left-side navigation pane, choose .
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose .
On the Global tab, select X-FORWARDED-CLIENT-CERT in the Log Settings section, and then click Submit.

Use kubectl to connect to the ACK managed cluster that is added to the ASM instance. Then, run the following command to access the HTTPBin application from the sleep pod:
kubectl exec <sleep pod name> -- curl httpbin:8000 -IRun the following command to view the logs of the HTTPBin pod:
kubectl logs <httpbin pod> -c istio-proxy | tail -1Expected output:
{"bytes_received":"0","bytes_sent":"0","downstream_local_address":"192.168.34.76:80","downstream_remote_address":"192.168.34.74:45042","duration":"2","istio_policy_status":"-","method":"HEAD","path":"/","protocol":"HTTP/1.1","request_id":"7bd9862b-69d8-4d14-bc62-4520b2b45370","requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local","response_code":"200","response_flags":"-","route_name":"default","start_time":"2024-06-11T11:24:04.163Z","trace_id":"-","upstream_cluster":"inbound|80||","upstream_host":"192.168.34.76:80","upstream_local_address":"127.0.0.6:54963","upstream_service_time":"2","upstream_response_time":"2","upstream_transport_failure_reason":"-","user_agent":"curl/8.1.2","x_forwarded_for":"-","authority_for":"httpbin:8000","x_forwarded_client_cert":"By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=583116d4dfd7b548400031f5c8685ee4f8ca99f217aca2af8634022362988114;Subject="";URI=spiffe://cluster.local/ns/default/sa/sleep"}The XFCC header in the preceding output indicates that the client is the sleep application.
Check whether mTLS is enabled in a direct manner by running the tcpdump command to capture packets
In this section, the packets that are sent from the sidecar proxy of the sleep application to the sidecar proxy of the HTTPBin application are captured in the sleep pod. Two ways can be used to capture packets. You can choose one based on the actual situation.
Before you capture packets, delete the existing HTTPBin pod to restart it and ensure that the persistent connection between sidecar proxies is forcibly disconnected.
Use ASMPacketInspector to capture packets (ASMPacketInspector is available in ASM instances of V1.21 and later)
Use kubectl to connect to the ASM instance and create an ASMPacketInspector.yaml file that contains the following content:
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMPacketInspector metadata: name: test spec: pod: clusterId: ${ACK Cluster ID} namespace: default name: ${sleep pod name} tcpDumpParams: '-i any port 80' duration: 60s fileName: sleep.pcapRun the following command to deploy ASMPacketInspector resources:
kubectl apply -f ASMPacketInspector.yamlAfter the ASMPacketInspector resources are deployed, ASM automatically captures packets whose destination port is port 80 in the sleep pod. Port 80 is the service port exposed by the HTTPBin application. The packet capture duration is 60s. During this period, use kubectl to connect to the ACK managed cluster that is added to the ASM instance and run the following command:
kubectl exec -it <sleep pod name> -c sleep -- sh -c 'for i in $(seq 1 30); do curl httpbin:8000 -I ; echo "request $i done"; done'This command automatically sends 30 requests from the sleep pod to the HTTPBin application.
Use kubectl to connect to the ASM instance and run the following command to view the packet capture results:
kubectl get ASMPacketInspector test -o yamlExpected results:
apiVersion: istio.alibabacloud.com/v1beta1 kind: ASMPacketInspector metadata: ****** spec: ****** status: completedAt: null conditions: - time: "2024-06-12T08:15:33Z" type: Inspecting - message: 'inspecting job status: Running' time: "2024-06-12T08:15:43Z" type: Inspecting - message: 'inspecting job status: Running' time: "2024-06-12T08:15:53Z" type: Inspecting - message: 'inspecting job status: Running' time: "2024-06-12T08:16:03Z" type: Inspecting - message: 'inspecting job status: Running' time: "2024-06-12T08:16:13Z" type: Inspecting - message: 'inspecting job status: Running' time: "2024-06-12T08:16:23Z" type: Inspecting filePath: /tmp/sleep.pcap phase: Inspecting runningOnNode: ******* startAt: "2024-06-12T08:15:43Z" taskId: inspector-zumnmwdcrunningOnNodein thestatussection indicates the node where the packets are captured.filePathindicates the path of the output file. Log on to the specified node to download the file to your local computer.
Capture packets on the node where the sleep pod resides
Use kubectl to connect to the ACK managed cluster that is added to the ASM instance. Then, run the following command to check the node where the sleep application runs:
kubectl get pod -o wideExpected output:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpbin-6c8f47d9b9-stq72 2/2 Running 0 33m 172.16.*.* cn-***.172.16.*.* <none> <none> sleep-84f9785988-ft9rm 2/2 Running 0 3h56m 172.16.*.* cn-***.172.16.*.* <none> <none>Log on to the node where the sleep application runs. For more information, see Use Workbench to connect to a Linux instance over SSH.
Run the following command to view the
CONTAINER IDof the container where the sleep application resides:sudo crictl ps | grep <Pod name>Expected output:
CONTAINER IMAGE CREATED STATE a1a214d2***** 35d28df4***** 2 days ago RunningRun the following command with
CONTAINER IDset to the one obtained in the preceding step to view the PID of the container:sudo crictl inspect a1a214d2***** |grep -i PIDExpected output:
"pid": 2309838, # The PID of the container. "pid": 1 "type": "pid"Run the following command to capture packets:
sudo nsenter -t <Container PID> tcpdump -i any port 80 -w /tmp/test.pcapDownload the
test.pcapfile generated after the command is executed to your local computer.
Make sure that Wireshark is installed on your computer. Use Wireshark to open the pcap file that you downloaded to your computer and set the protocol of the corresponding port to TLS. The following result is displayed.

The TLS packets indicate that the communication between sidecar proxies is encrypted by using mTLS.
You can view only Client Hello and Server Hello packets, followed by Application Data packets. TLS certificate information is not displayed because TLSv1.3 encrypts subsequent certificate exchange messages. Therefore, the plaintext information of certificates cannot be directly viewed in WireShark, which is normal.