mTLS加密通信是服務網(wǎng)格ASM提供的一項重要的基礎能力,您無需對應用進行改造,只需要給應用Pod注入Sidecar代理就會默認啟用mTLS。但由于mTLS是無感啟用的,無法直觀判斷流量是否真正進行了加密,本文將介紹和演示如何確認網(wǎng)格內部是否啟用了mTLS通信。
背景信息
TLS(Transport Layer Security)是一個廣泛應用于互聯(lián)網(wǎng)的安全協(xié)議,旨在為通信兩端提供安全的數(shù)據(jù)傳輸通道。常見的TLS通信通常只執(zhí)行單向的身份認證,比如在瀏覽器中通過HTTPS訪問一個網(wǎng)站時,只需要網(wǎng)站服務器提供網(wǎng)站自身的證書,向客戶證明自己是這個網(wǎng)站的合法所有者,并不需要客戶提供證書證明客戶的身份。
普通的TLS通信僅執(zhí)行單向驗證,服務器需要向客戶端提供證書來建立安全的連接;而在mTLS(Mutual Transport Layer Security)中,客戶端也必須向服務器提供證書,雙方需要相互驗證對方的身份。如此一來就可以保證只有被授權的客戶端才能訪問指定服務端。
服務網(wǎng)格中的授權機制依賴于mTLS協(xié)議來驗證客戶端身份,這種互相認證的機制能夠確保在服務網(wǎng)格中的每個服務調用都來自受信任的客戶端,從而為微服務通信提供了一層額外的安全保護。
以下將以sleep訪問httpbin應用為例,演示通過間接和直接的方式確認網(wǎng)格內部是否已啟用mTLS通信。
前提條件
已創(chuàng)建ASM實例。具體操作,請參見創(chuàng)建ASM實例。
已創(chuàng)建Kubernetes托管版集群。具體操作,請參見創(chuàng)建ACK托管集群。
已添加集群到ASM實例。具體操作,請參見添加集群到ASM實例。
已開啟Sidecar網(wǎng)格代理自動注入。具體操作,請參見啟用自動注入。
已經(jīng)部署了httpbin應用,并且可以正常訪問,請參見部署httpbin應用。
步驟一:部署sleep應用
通過kubectl連接到ASM實例添加的Kubernetes集群,使用以下內容創(chuàng)建sleep.yaml。
apiVersion: v1 kind: ServiceAccount metadata: name: sleep --- apiVersion: v1 kind: Service metadata: name: sleep labels: app: sleep service: sleep spec: ports: - port: 80 name: http selector: app: sleep --- apiVersion: apps/v1 kind: Deployment metadata: name: sleep spec: replicas: 1 selector: matchLabels: app: sleep template: metadata: labels: app: sleep spec: terminationGracePeriodSeconds: 0 serviceAccountName: sleep containers: - name: sleep image: registry.cn-hangzhou.aliyuncs.com/acs/curl:8.1.2 command: ["/bin/sleep", "infinity"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume volumes: - name: secret-volume secret: secretName: sleep-secret optional: true ---
執(zhí)行以下命令,部署測試客戶端應用sleep。
kubectl apply -f sleep.yaml
步驟二:驗證是否已啟用mTLS
通過Header標識間接確認是否啟用mTLS
X-FORWARDED-CLIENT-CERT(XFCC)是一個特殊的Proxy Header,用來標識請求從客戶端到服務端的途中經(jīng)過的部分或全部的客戶端或代理的證書信息。具體信息,請參見HTTP header manipulation。
在sleep應用中使用curl
命令訪問httpbin應用時,httpbin應用收到的請求會攜帶XFCC header,標識這個請求由sleep應用發(fā)出,通過這個Header可以間接確定兩端通信中啟用了mTLS。
登錄ASM控制臺,在左側導航欄,選擇 。
在網(wǎng)格管理頁面,單擊目標實例名稱,然后在左側導航欄,選擇 。
在全局配置中的日志設置中找到X-FORWARDED-CLIENT-CERT,選中后點擊最下方的提交。
通過kubectl連接到ASM實例添加的Kubernetes集群,執(zhí)行以下命令在sleep應用Pod中訪問httpbin服務。
kubectl exec <sleep pod name> -- curl httpbin:8000 -I
執(zhí)行以下命令查看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
本節(jié)在sleep應用Pod中抓取sleep Sidecar發(fā)送給httpbin Sidecar的數(shù)據(jù)包。抓包有兩種方式可以實現(xiàn),您可以根據(jù)實際情況選擇。
抓包前請先刪除已有的httpbin Pod使其重啟,確保Sidecar之間的長連接被強制斷開。
通過ASMPacketInspector實現(xiàn)抓包(ASM實例版本1.21以上)
通過kubectl連接到ASM實例,使用以下內容創(chuàng)建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
執(zhí)行以下命令部署ASMPacketInspector資源。
kubectl apply -f ASMPacketInspector.yaml
ASMPacketInspector資源部署后,ASM會自動在sleep pod中抓取80端口的數(shù)據(jù)包(httpbin pod暴露的服務端口),抓包時長為60s。在此期間,通過kubectl連接到ASM實例添加的Kubernetes集群,執(zhí)行以下命令。
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服務發(fā)送30次請求。
通過kubectl連接到ASM實例,執(zhí)行以下命令查看抓包結果。
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
代表輸出文件的路徑。登錄到指定節(jié)點將文件下載到本地。
直接在sleep應用Pod所在節(jié)點上抓包
通過kubectl連接到ASM實例添加的Kubernetes集群,執(zhí)行以下命令查看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>
登錄到目標節(jié)點。操作步驟詳情,請參見通過密碼或密鑰認證登錄Linux實例。
執(zhí)行以下命令查看sleep應用對應的容器
CONTAINER ID
。sudo crictl ps |grep <Pod名稱關鍵字>
預期輸出:
CONTAINER IMAGE CREATED STATE a1a214d2***** 35d28df4***** 2 days ago Running
使用
CONTAINER ID
參數(shù),執(zhí)行以下命令查看容器PID。sudo crictl inspect a1a214d2***** |grep -i PID
預期輸出:
"pid": 2309838, # 目標容器的PID進程號。 "pid": 1 "type": "pid"
執(zhí)行以下抓包命令。
sudo nsenter -t <容器PID> tcpdump -i any port 80 -w /tmp/test.pcap
將命令執(zhí)行后生成的
test.pcap
文件下載到本地。
確保本地安裝了Wireshark,使用wireshark打開上述下載到本地pcap
格式文件,選擇對應端口協(xié)議為TLS,可以看到如下結果。
通過對應的TLS報文,可以確認Sidecar之間通信使用了mTLS進行了加密。
這里只能看到Client Hello和Server Hello,之后就是Application Data報文了。這里之所以沒有直接看到TLS的證書信息,是因為TLSv1.3中對后續(xù)的證書交換消息都進行了加密,所以無法直接在WireShark中查看到證書的明文信息,這是正常現(xiàn)象。
相關文檔
您可以通過PeerAuthentication資源來配置服務之間的mTLS策略。請參見對等身份認證(Peer Authentication)。