4.5.1 背景知识
1.中间人攻击
中间人攻击(Man-in-the-middle Attack)是一类经典的攻击方式。它包括许多种具体的类型,如ARP欺骗、DNS劫持和SMB会话劫持等。
许多读者对中间人攻击的概念可能都不陌生。通常情况下,在不受干扰时,逻辑上看两台计算机设备之间的通信应该如图4-13所示(高度抽象,略去了复杂的协议栈)。
图4-13 正常情况下两个设备间的通信
此时,如果有一个攻击者劫持了张三和李四的通信,分别在张三面前冒充李四,在李四面前冒充张三,那么通信场景就变成了如图4-14所示。
图4-14 中间人攻击场景
在此过程中,张三和李四可能对攻击者浑然不觉。然而,作为“通信的中间人”,攻击者却能够读取甚至修改双方交互的信息。欲了解更多关于中间人攻击的内容,可以参考维基百科[1]。
理论上,几乎所有的通信交互都可能存在中间人攻击的风险。其中,针对ARP和DNS协议的攻击尤为经典。但是,结合Linux系统Capabilities知识可知,如果想要发送ARP包,需要具有CAP_NET_RAW权限。那么,容器内部的root用户是否具有此权限呢?
首先,在Pod内执行命令查看Capabilities的值:
root@k8s:~# kubectl exec -it attacker -- grep CapEff /proc/self/status CapEff: 00000000a80425fb
然后,在宿主机上使用capsh命令解析上一步获取的值:
root@k8s:~# capsh --decode=00000000a80425fb 0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_ kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_ raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap
可以看到,解析结果包含cap_net_raw,这意味着在Pod中攻击者具有足够权限来发送恶意的ARP包。
2.Kubernetes与DNS
我们首先介绍一下Kubernetes中的DNS服务。首先,Kubernetes以服务资源kube-dns的形式提供集群级别的DNS服务:
root@k8s:~# kubectl get svc -n kube-system NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP 202d
kube-dns服务依赖的是集群中kube-system命名空间下的CoreDNS Pod:
root@k8s:~# kubectl describe svc kube-dns -n kube-system Name: kube-dns Namespace: kube-system Labels: k8s-app=kube-dns kubernetes.io/cluster-service=true kubernetes.io/name=KubeDNS Annotations: prometheus.io/scrape: true Selector: k8s-app=kube-dns Type: ClusterIP IP: 10.96.0.10 Port: dns 53/UDP TargetPort: 53/UDP Endpoints: 10.244.0.134:53,10.244.0.187:53 Port: dns-tcp 53/TCP TargetPort: 53/TCP Endpoints: 10.244.0.134:53,10.244.0.187:53 Session Affinity: None Events: <none>
如果新建一个Pod,我们会发现,它的内部resolv.conf文件中记录的DNS服务器IP地址正是kube-dns服务的地址:
root@test:/# cat /etc/resolv.conf nameserver 10.96.0.10
当这个Pod向kube-dns服务发起DNS查询请求时,查询请求会经过Kubernetes配置的iptables规则,最终被发送到服务后端的CoreDNS Pod中:
root@k8s:~# iptables -t nat -L Chain PREROUTING (policy ACCEPT) target prot opt source destination KUBE-SERVICES all -- anywhere anywhere /* kubernetes service portals */ Chain KUBE-MARK-MASQ (8 references) target prot opt source destination MARK all -- anywhere anywhere MARK or 0x4000 Chain KUBE-SEP-SFEHAAPK7JVDTVUX (1 references) target prot opt source destination KUBE-MARK-MASQ all -- 10.244.0.134 anywhere /* kube-system/kube-dns:dns */ DNAT udp -- anywhere anywhere /* kube-system/kube-dns:dns */ udp to:10.244.0.134:53 Chain KUBE-SERVICES (2 references) target prot opt source destination KUBE-MARK-MASQ udp -- !10.244.0.0/16 10.96.0.10 /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain KUBE-SVC-TCOU7JCQXEZGVUNU udp -- anywhere 10.96.0.10 /* kube-system/kube-dns:dns cluster IP */ udp dpt:domain Chain KUBE-SVC-TCOU7JCQXEZGVUNU (1 references) target prot opt source destination KUBE-SEP-SFEHAAPK7JVDTVUX all -- anywhere anywhere /* kube-system/kube-dns:dns */ statistic mode random probability 0.50000000000
欲了解更多关于CoreDNS的内容,可以参考官方文档[2]。
3.Kubernetes与ARP
图4-12给出了一般性的Kubernetes网络架构。可以发现,Pod内的eth0网卡的对端被连接到cni0网桥上。此时,该对端就成为了cni0网桥的一个接口。当Pod向外发出ARP请求时,该请求会被网桥转发给其他接口,这样一来,其他Pod就能够收到ARP请求,其中网卡MAC地址与ARP请求相符的Pod就会发送ARP响应,该响应同样会被网桥转发给最初发出ARP请求的Pod。这就是Kubernetes内部同一个节点上的ARP请求响应流程。
[1] https://en.wikipedia.org/wiki/Man-in-the-middle_attack。
[2] https://kubernetes.io/docs/tasks/administer-cluster/coredns/。