Kubernetes的网络架构及其安全风险

本博客地址:https://security.blog.csdn.net/article/details/129137821

一、常见的Kubernetes网络架构

如图所示:

在这里插入图片描述

说明:

1、集群由多个节点组成。
2、每个节点上运行若干个Pod。
3、每个节点上会创建一个CNI网桥(默认设备名称为cni0)。
4、每个Pod存在于自己的网络命名空间中,通过虚拟网卡对Veth Pair设备与外界通信。
5、Veth Pair设备将创建两张虚拟网卡,分别位于Pod所在的网络命名空间中(对应图中 Pod内部的eth0)和节点根网络命名空间中(对应图中每个节点上方根网络命名空间内的各个veth,如veth1056db9f),互为对端(Veth Peer),对于Veth Pair设备的两张虚拟网卡来说,从其中一张网卡发出的数据包,将直接出现在另一张网卡上。
6、每个Pod的eth0网卡的对端veth网卡“插”在cni0网桥上。
7、同一节点上的各Pod可以借助cni0网桥互相通信,不同节点之间需要借助额外的网络插件进行通信,如Flannel。
8、CoreDNS是整个Kubernetes集群的DNS服务器。

二、Kubernetes下pod间的网络通信

如果一个pod想要发送ARP包,需要具有CAP_NET_RAW权限,在容器中,对于一个具有root权限的用户来说,默认是具有该权限的,查看方式如下:

在这里插入图片描述

Kubernetes以服务资源kube-dns的形式提供集群级别的DNS服务,所有pod的DNS服务器IP地址正是kube-dns服务的地址:

在这里插入图片描述

当这个Pod向kube-dns服务发起DNS查询请求时,查询请求会经过Kubernetes配置的iptables规则,最终被发送到服务后端的CoreDNS Pod中:

# 执行命令
iptables -t nat -L

在这里插入图片描述

而Pod的IP地址则是:

在这里插入图片描述

Pod内的eth0网卡的对端被连接到cni0网桥上。此时该对端就成为了cni0网桥的一个接口。当Pod向外发出ARP请求时,该请求会被网桥转发给其他接口,这样一来其他Pod就能够收到ARP请求,其中网卡MAC地址与ARP请求相符的Pod就会发送ARP响应,该响应同样会被网桥转发给最初发出ARP请求的Pod。这就是Kubernetes内部同一个节点上的ARP请求响应流程。

假设一个Pod需要访问example.com,那么它首先必须知道该域名对应的IP,因此它需要发出一个DNS查询请求。默认情况下,Pod的DNS策略为ClusterFirst,也就是说,这个Pod会向集群DNS服务kube-dns发起请求。

DNS请求实际上是一个UDP报文,从我们上面的截图可知,kube-dns服务的IP为10.2.0.10,而该Pod的IP为10.244.2.11,两者不在同一子网。因此该UDP报文会被Pod发送给默认网关,也就是cni0。之后,节点iptables对该报文进行DNAT处理,将目的地改为10.244.0.7, 也就是CoreDNS Pod的IP地址。

之后,cni0通过查询自己维护的MAC地址表,找到10.244.0.7对应的MAC地址,然后将报文发到网桥的对应端口上。CoreDNS Pod收到报文后,向上级DNS服务器查询example.com的IP,收到结果后向该Pod发出DNS响应。

至此,这个Pod知道了example.com对应的IP。该Pod就可以向example.com对应的IP发出基于TCP的HTTP请求了

三、容器编排平台(Kubernetes)面临的风险

容器技术和编排管理系统是云原生生态的两大核心部分,前者负责执行,后者负责控制和管理,共同构成云原生技术有机体。

Kubernetes架构图如下:

在这里插入图片描述

上图是一个常见的Kubernetes集群,由一个Master节点和三个Worker节点组成,Pod之间借助CNI插件Flannel实现通信。Kubernetes自身的系统Pod(kube-system命名空间内的Pod)主要运行在Master节点上,除此之外,每个Worker节点上也分别有一个Flannel Pod和kube-proxy Pod;所有业务Pod分布在三个Worker节点上。另外,每个节点上还有一个Kubelet服务,负责管理容器。

1、在Kubernetes环境中,容器基础设施存在的风险

镜像面临的风险:主要是不安全的第三方组件、恶意镜像、敏感信息泄露(例如将敏感配置信息打包进镜像的情况)等;
活动容器面临的风险:主要是不安全的容器应用、不受限制的资源共享、不安全的配置与挂载等;
网络存在的风险:主要是由于集群通常由多个节点组成,因此集群网络风险的影响范围要比单宿主机运行容器的网络风险更大;
其他风险:除此外,还有容器管理程序接口、宿主机操作系统、容器软件漏洞等安全风险;

2、Kubernetes组件接口存在的风险

Kubernetes中组件众多,绝大多数组件以基于HTTP或HTTPS的API形式提供服务。其中,我们日常接触比较多的服务及其端口如下所示:

组件 默认端口 说明
API Server 6443 基于HTTP的安全端口
API Server 8080 不安全的HTTP端口
Kubelet 10248 用于检查Kubelet健康状态的HTTP端口
Kubelet 10250 面向API Server提供服务的HTTPS端口
Dashboard 8001 提供HTTP服务的端口
etcd 2379 客户端与服务端之间通信的端口
etcd 2380 不同服务端实例之间通信的端口

API Server:默认情况下,API Server在8080和6443两个端口上提供服务。其中,8080端口提供的是没有TLS加密的HTTP服务。保留该端口主要是为了方便测试以及集群初启动。然而在生产环境开放8080端口,即使绑定本地环回地址(localhost)也是很危险的。如果将该端口暴露在互联网上,那么任何网络可达的攻击者都能够通过该端口直接与API Server交互,继而控制整个集群。

Kubelet:默认配置下,Kubelet在10250端口开放上述API服务,另外还监听10248端口,以供其他组件检查Kubelet的运行状态。这里10248端口的服务相对简单,不存在特别的风险,但10250端口在默认情况下,API Server在访问Kubelet的API时需要使用客户端证书,相对来说是比较安全的。但是如果出现以下任一情况:

1)攻击者通过某种方式窃取了API Server访问Kubelet的客户端证书。
2)用户为了方便起见,将Kubelet的--anonymous-auth参数设置为true,且authorization.mode设置为AlwaysAllow。

则网络可达的攻击者都能够直接与Kubelet进行交互,从而实现对其所在节点的控制。

Dashboard:默认情况下,我们需要先执行kubectl proxy,然后才能通过本地8001端口访问Dashboard。但是,如果直接将Dashboard端口映射在宿主机节点上,或者在执行kubectl proxy时指定了额外地址参数,那么所有能够访问到宿主机的用户,包括攻击者,都将能够直接访问Dashboard。

另外,默认情况下Dashboard需要登录认证,但是,如果用户在Dashboard的启动参数中添加了--enable-skip-login选项,那么攻击者就能够直接点击Dashboard界面的“跳过”按钮,无须登录便可直接进入Dashboard。

etcd:etcd启动后监听2379和2380两个端口,前者用于客户端连接,后者用于多个etcd实例之间的对端通信。在多节点集群中,为了实现高可用,etcd往往在节点IP上(非本地IP)监听,以实现多节点之间的互通,这可能允许外部攻击者访问etcd。

默认情况下,两个端口提供的服务都需要相应证书才能访问(禁止匿名访问),这为etcd的安全性提供了保障。如果攻击者窃取了证书,或者用户将etcd设置为允许匿名访问,那么攻击者就可能直接访问etcd并窃取数据

3、集群网络存在的风险

为了实现集群Pod间相互通信,在安装部署Kubernetes后,我们往往还要额外安装一个网络插件,常见的网络插件有Flannel、Calico和Cilium等。

在没有其他网络隔离策略和Pod安全策略的默认情况下,由于Pod与Pod之间彼此可连通,且Pod内的root用户具有CAP_NET_RAW权限,集群内部可能发生网络探测、嗅探、拒绝服务和中间人攻击等网络攻击。

4、访问控制机制存在的风险

如果访问控制过于宽松,高权限账户可能会被滥用,从而对Kubernetes自身及正在运行的容器产生威胁;除此之外,如果允许针对Kubernetes的未授权访问,攻击者可能借此直接获得集群管理员权限。另外,即使认证和授权机制在容器环境创建初期遵循了最小权限等安全原则,随着时间的推移和环境的更新变动,角色与权限可能会变得混乱,从而为攻击者提供可乘之机。

5、其他风险

其他风险主要是Kubernetes软件安全漏洞

四、Kubernetes下Pod通信的中间人攻击

对于Pod通信的中间人攻击,我们的前提是其中一个Pod已被攻击者攻入且具有root权限。

具体的网络示意如图所示,攻击者的Pod为节点1左下方的Web APP Pod(我们将其命名为attacker Pod),受害者Pod为节点1右下方的Backend Pod(我们将其命名为victim Pod)

在这里插入图片描述

攻击流程:

1、首先获得各种网络参数,包括attacker Pod自身的MAC和IP地址、Kubernetes集群DNS服务的IP地址、同节点上CoreDNS Pod的MAC和IP地址、CNI网桥的MAC和IP地址。

2、在attacker Pod中启动一个HTTP服务器,监听80端口,对于任何HTTP请求均回复一行字符串“F4ke Website”,作为攻击成功的标志。

3、攻击者在attacker Pod中启动一个ARP欺骗程序,持续向cni0网桥发送ARP响应帧,不断声明CoreDNS Pod的IP对应的MAC地址应该是attacker Pod的MAC地址。

4、在attacker Pod中启动一个DNS劫持程序,等待接收DNS请求。

5、根据设定,victim Pod向example.com发起HTTP请求,为了获得example.com的IP地址,victim Pod需要向DNS服务器发起请求,为了找到DNS服务器的MAC地址,victim Pod需要先向cni0网桥发送ARP请求,然而由于attacker Pod在第3步不断地向cni0网桥发送ARP响应帧,因此victim Pod会收到响应,被告知CoreDNS Pod的IP对应attacker Pod的MAC地址。

6、一旦第3步生效,victim Pod向attacker Pod发来DNS请求,则DNS劫持程序首先判断该请求针对的域名是否为目标域名example.com。如否,则将请求转发给真正的CoreDNS Pod,接收CoreDNS Pod的响应包,并转发给victim Pod;如是,则伪造DNS响应包,声明example.com对应的IP地址是attacker Pod自己的IP,将这个响应包发送给victim Pod。

7、顺利的话,victim Pod接下来将向attacker Pod发送http://example.com的HTTP请求,因此第2步中attacker Pod中设置的HTTP服务器将向victim回复预设字符串“F4ke Website”,victim Pod以为“F4ke Website”正是自己需要的内容。

防御措施:

禁用CAP_NET_RAW权限即可

猜你喜欢

转载自blog.csdn.net/wutianxu123/article/details/129137821