mTLS加密通訊是服務網格ASM提供的一項重要的基礎能力,您無需對應用進行改造,只需要給應用Pod注入Sidecar代理就會預設啟用mTLS。但由於mTLS是無感啟用的,無法直觀判斷流量是否真正進行了加密,本文將介紹和示範如何確認網格內部是否啟用了mTLS通訊。
背景資訊
TLS(Transport Layer Security)是一個廣泛應用於互連網的安全性通訊協定,旨在為通訊兩端提供安全的資料轉送通道。常見的TLS通訊通常只執行單向的身份認證,比如在瀏覽器中通過HTTPS訪問一個網站時,只需要網站伺服器提供網站自身的認證,向客戶證明自己是這個網站的合法所有者,並不需要客戶提供認證證明客戶的身份。
普通的TLS通訊僅執行單向驗證,伺服器需要向用戶端提供認證來建立安全的串連;而在mTLS(Mutual Transport Layer Security)中,用戶端也必須向伺服器提供認證,雙方需要相互驗證對方的身份。如此一來就可以保證只有被授權的用戶端才能訪問指定服務端。
服務網格中的授權機制依賴於mTLS協議來驗證用戶端身份,這種互相認證的機制能夠確保在服務網格中的每個服務調用都來自受信任的用戶端,從而為微服務通訊提供了一層額外的安全保護。
以下將以sleep訪問httpbin應用為例,示範通過間接和直接的方式確認網格內部是否已啟用mTLS通訊。
前提條件
已建立ASM執行個體。具體操作,請參見建立ASM執行個體。
已建立Kubernetes託管版叢集。具體操作,請參見建立ACK託管叢集。
已添加叢集到ASM執行個體。具體操作,請參見添加叢集到ASM執行個體。
已開啟Sidecar網格代理自動注入。具體操作,請參見啟用自動注入。
已經部署了httpbin應用,並且可以正常訪問,請參見部署httpbin應用。
步驟一:部署sleep應用
通過kubectl串連到ASM執行個體添加的Kubernetes叢集,使用以下內容建立sleep.yaml。
執行以下命令,部署測試用戶端應用sleep。
kubectl apply -f sleep.yaml
步驟二:驗證是否已啟用mTLS
通過Header標識間接確認是否啟用mTLS
X-FORWARDED-CLIENT-CERT(XFCC)是一個特殊的Proxy Header,用來標識請求從用戶端到服務端的途中經過的部分或全部的用戶端或代理的認證資訊。具體資訊,請參見HTTP header manipulation。
在sleep應用中使用curl命令訪問httpbin應用時,httpbin應用收到的請求會攜帶XFCC header,標識這個請求由sleep應用發出,通過這個Header可以間接確定兩端通訊中啟用了mTLS。
登入ASM控制台,在左側導覽列,選擇。
在網格管理頁面,單擊目標執行個體名稱,然後在左側導覽列,選擇。
在全域配置中的日誌設定中找到X-FORWARDED-CLIENT-CERT,選中後點擊最下方的提交。

通過kubectl串連到ASM執行個體添加的Kubernetes叢集,執行以下命令在sleep應用Pod中訪問httpbin服務。
kubectl exec <sleep pod name> -- curl httpbin:8000 -I執行以下命令查看httpbin應用Pod的日誌。
kubectl logs <httpbin pod> -c istio-proxy | tail -1預期輸出:
{"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"}從上述輸出中的XFCC header資訊可以看到用戶端身份標識是sleep應用。
通過tcpdump抓包直接確認是否啟用mTLS
本節在sleep應用Pod中抓取sleep Sidecar發送給httpbin Sidecar的資料包。抓包有兩種方式可以實現,您可以根據實際情況選擇。
抓包前請先刪除已有的httpbin Pod使其重啟,確保Sidecar之間的長串連被強制斷開。
通過ASMPacketInspector實現抓包(ASM執行個體版本1.21以上)
通過kubectl串連到ASM執行個體,使用以下內容建立ASMPacketInspector.yaml。
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.pcap執行以下命令部署ASMPacketInspector資源。
kubectl apply -f ASMPacketInspector.yamlASMPacketInspector資源部署後,ASM會自動在sleep pod中抓取80連接埠的資料包(httpbin pod暴露的服務連接埠),抓包時間長度為60s。在此期間,通過kubectl串連到ASM執行個體添加的Kubernetes叢集,執行以下命令。
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'此命令會自動從sleep pod向httpbin服務發送30次請求。
通過kubectl串連到ASM執行個體,執行以下命令查看抓包結果。
kubectl get ASMPacketInspector test -o yaml預期結果:
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-zumnmwdc從
status部分的runningOnNode可以看到抓包啟動並執行node,filePath代表輸出檔案的路徑。登入到指定節點將檔案下載到本地。
直接在sleep應用Pod所在節點上抓包
通過kubectl串連到ASM執行個體添加的Kubernetes叢集,執行以下命令查看sleep應用運行在哪個Node上。
kubectl get pod -o wide預期輸出:
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>登入到目標節點。操作步驟詳情,請參見通過密碼或密鑰認證登入Linux執行個體。
執行以下命令查看sleep應用對應的容器
CONTAINER ID。sudo crictl ps |grep <Pod名稱關鍵字>預期輸出:
CONTAINER IMAGE CREATED STATE a1a214d2***** 35d28df4***** 2 days ago Running使用
CONTAINER ID參數,執行以下命令查看容器PID。sudo crictl inspect a1a214d2***** |grep -i PID預期輸出:
"pid": 2309838, # 目標容器的PID進程號。 "pid": 1 "type": "pid"執行以下抓包命令。
sudo nsenter -t <容器PID> tcpdump -i any port 80 -w /tmp/test.pcap將命令執行後產生的
test.pcap檔案下載到本地。
確保本地安裝了Wireshark,使用wireshark開啟上述下載到本地pcap格式檔案,選擇對應連接埠協議為TLS,可以看到如下結果。

通過對應的TLS報文,可以確認Sidecar之間通訊使用了mTLS進行了加密。
這裡只能看到Client Hello和Server Hello,之後就是Application Data報文了。這裡之所以沒有直接看到TLS的認證資訊,是因為TLSv1.3中對後續的認證交換訊息都進行了加密,所以無法直接在WireShark中查看到認證的明文資訊,這是正常現象。