云计算时代容器安全综述-容器的网络安全(上)

互联网应用已经深深的渗透到我们日常生活的方方面面,比如很多同学应该有很长时间都没有使用过现金了。不过任何事情都具有两面性,科技发展给我们造成便利的同事,不容忽视的一个事实是,大部分在线交付系统每天都会遭受各种各样的网络攻击,因此无论你的系统部署在哪里,我们都需要有基本的网络知识来保护系统的正常运行以及核心数据不会被窃取。

读者看到这里可能会说讲网络原理的书和文章太多了,这个东西还有什么好说的。笔者认可这个说法,因此也没有打算对网络原理进行深入的探讨,而是会着重介绍网络安全相关的部分,以期帮助那些对这些概念不很熟悉的同学能够消化我们介绍的核心知识:安全。

容器化部署方案总是伴随着微服务架构一起出现在技术方案,最近给几个头部客户做技术方案和部署方案的时候,深刻的体会到其中的缘由。微服务架构本身解决的是如何将模块化失控的单体应用拉回到可运维,可管理,可扩展应用的范围,因此我们会将大块的功能进行拆分,结果就是可独立部署的一个个“微”服务。

很明显这里拆分是关键,因为也没有什么放之四海而皆准的标准规则,大部分讲微服务拆分的文章都提供了供参考的拆分维度,比如从业务的角度,从变化频率,从访问量,从技术栈等等。当软件被拆分为粒度“合适”的服务后,整个部署方案也需要适配,我们需要考虑这么多服务以及服务的多个实例如何进行部署和管理的问题。

虽然说解决这个问题有过很多不同方向的尝试,目前看容器化部署应该是这些方案里最被广泛接受的,特别是从安全的角度看,大的单体应用的安全边界远比细粒度服务的安全边界大,因此“微”服务更加容易来进行安全防护。当然背后的逻辑不难理解,由于微服务承载的功能比起单体应用来说小了不少,因此微服务需要和其他容器通信的场景少很多,甚至都可能不需要和公网上的服务通信。

咱们来举个例子,比如说我们开发电商平台,核心功能会被拆分到不同的能力中心,典型的能力中心有产品,库存和支付等。对于电商来说,用户需要通过商品详情页面来帮助客户更好的了解商品信息,因此我们需要提供商品检索接口,因此对于上平中心的微服务来说,除了访问数据库之外,根本不需要访问比如说支付微服务的权限,理论上我们应该禁止这样的访问链路,确保当商品微服务被攻破后,不会影响支付微服务。如下图所示:

《图1.1 容器间访问场景下防火墙策略》

容器防火墙可以用来限制进出容器实例的访问流量,不过熟悉Kubernetes的同学应该会觉得“容器防火墙”这个术语很奇怪,因为在K8S中,我们用的术语是网络策略(Network policy)。不过无论是叫啥名字,本质都是为了让进出容器的网络流量符合预期。另外容器防火墙也会记录和报告预期之外的网络访问情况,这些数据可以用来进行安全审计以及网络攻击预防工作。

容器防火墙一般情况下会和多个网络工具配合使用,来达到纵深防御的效果,常见的工具罗列如下:

- 和VPC结合起来,来让部署在VPC中的应用和外部系统的相互访问受规则管控

- 和WAF等工具配合使用,来约束7层的访问流量

如笔者在前边所述,这些工具的组合使用会加深安全纵深,我们应该在自己的系统设计中,特别是安全体系中考虑这种纵深防御的思路。接下里我们聊聊如何实现容器防火墙,不过在这之前,为了内容的完整性,咱先简单的介绍一下网络基础知识。

说到网络模型,不得不提OSI(Open Systems Interconnection)网络模型,这个模型在40年后的今天(1984年发布)仍然具有参考价值。OSI模型和网络的事实规范TCP/IP模型之间并不能1:1映射,如下图所示,

《图1.2 OSI模型和TCPIP模型的关系》

关于OSI模型的各层简要说明如下:

- Layer 7一般被称作是应用程序层。应用程序层可以理解为我们通过应用来访问某个服务接口,这里的应用所处的就是Layer 7,或者说访问接口这个动作发生在Layer 7。7层的请求一般访问某个具体的URL,为了将请求路由到目标机器,URL中的域名会被翻译成IP地址,翻译的过程需要DNS服务的支持。

- Layer 4被称作是传输层,这一层有两个大名鼎鼎的协议TCP和UDP,端口号工作在4层

- Layer 3被称作是IP层或者网络层。这一层和核心工作是IP数据包的路由。当容器实例初始化的时候,会加入到宿主机上的虚拟网络,因此也会有自己的IP地址

- Layer 2被称作为数据链路层,工作在这一层的协议有WIFI,以太网等,年长的同学可能还听过什么Token Ring网络的,也属于链路层。不过WIFI放在这层稍微有点争议,因为WIFI覆盖了2层和1层(物理层),咱们所有的文章只会设计以太网,这是容器化部署网络使用最广泛的协议

- Layer 1被称作是物理层,什么同轴电缆,光纤等都属于这一层。对于容器网络来说,笔者想要特别强调的是,物理层可以虚拟。如果大家对笔者前边的文章有印象,我们说VMM(Virtual Machine Monitor)提供了对系统资源的虚拟化,让guest kernel通过虚拟设备来最终访问物理设备。

接下来我们通过一个具体的场景来看看这些曾是如何工作在一起支持网络连接的两台机器相互通信。假设我们有个客户端应用程序需要发送请求给某个目标URL,由于这个客户端属于我们所说的应用程序,因此我们可以理解为“发送”请求这个动作发生在Layer 7。

发出请求后第一步是DNS查询,来把URL中的主机名映射成IP地址,当然我们也可以不用访问外部的DNS服务,直接在etc/hosts文件中静态的将域名映射到对应的IP地址,这在我们很多测试场景非常实用。

当要访问的IP地址通过DNS解析或者本地hosts文件确认后,接下来就是3层的路由选择,路由选择主要包含两部分:

- 为了访问目标机器,可能需要跨越多个IP网,因此首先需要确定下一跳地址

- 确定了系一条地址,由于要具体发送数据,因此需要确定发送数据的网络接口(网卡)

接着请求会被封装成以太网帧,下一跳IP地址需要被翻译成MAC地址,翻译的过程需要依赖于ARP协议,当然如果之前访问过这个服务地址,并且ARP缓存中数据未过期,那么直接可以从ARP缓存取到IP地址对应的MAC地址,如果缓存中没有,那么就要依赖于ARP协议来确定下一跳机器的MAC地址。

确定了下一跳机器的MAC地址,消息就会通过选择的网络接口发送出去。不过这里基于具体的网络实现,网络接口可能是点到点连接,或者连接到外部的网桥。

网桥这个概念在容器网络中非常关键,因此我们需要花费一些笔墨来详细介绍一下。大家可以把网桥理解为有多个网线连接的设备,网线的另外一端连到电脑网卡上。每张网卡在出场的时候都会被分配并固化一个唯一的MAC地址,网桥bridge可以通过连接学习到每台机器的MAC地址。所有连接到网桥的设备都可以通过连接的网线来相互发送数据进行通信。

在容器网络模型中,网桥是通过软件来实现,而不是硬件,并且物理网线被虚拟以太网接口替换。因此数据发送到网桥后,会基于下一跳MAC地址来决定具体发送到哪个虚拟以太网接口上。

当数据出现在另外一头,也就是目标机器端,IP数据包被从以太网帧中抽取出来发送给Layer3。大家需要注意的是在数据在协议栈中发送的过程中,每一层都会增加header,以及在数据链路层会给尾部增加数据效验。如下图所示:

注:大家可以考虑一下为什么不在IP层增加checksum?主要还是效率的考虑,因为NAT的存在,如果我们在IP层做了checksum,那么无论是修改源地址还是目标地址,都会造成checksum的重新计算,会造成性能损耗,从这一点可以看出网络机制设计的核心域一定包含传输效率。

《图1.3 协议栈数据发送过程中会添加Header》

在网络层还会判断数据的目标机器是不是本机,如果是数据会被继续往上递交,如果不是,网络层会继续进行路由选择,来讲数据往下传递。上边的描述略微简略,但是大概把数据从应用层如何发送到目标机器描述了一遍,如果读者对这部分内容还有疑问,建议直接看TCP/IP Illustrated这本书,你绝对会喜欢上W Richard Steven的文字风格,特别是如何将复杂的技术细节通过简单的文字表达清楚。

好了,这篇文章就这么多了,咱们下篇文章继续讨论容器的IP地址分配,网络隔离,负载均衡,以及网络防火墙的具体落地实施方案,敬请期待!

你可能感兴趣的:(云计算时代容器安全综述-容器的网络安全(上))