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.yaml
ASMPacketInspector资源部署后,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中查看到证书的明文信息,这是正常现象。
相关文档
您可以通过PeerAuthentication资源来配置服务之间的mTLS策略。请参见对等身份认证(Peer Authentication)。