该文为前期热门文章《eBPF将如何提供服务网格解决方案--告别sidecar》的后续。其介绍了Cilium提供非sidecar模式的服务网格的解决方案。在本篇文章中,我们将目光扩展到mTLS
的主题上,并研究Cilium如何提供基于mTLS非sidecar模式的双向认证,其同时具备出色的安全性和性能优势。
文|Thomas Graf
编辑|zouyee
理解度|适中
随着技术的演进与发展,双向认证逐步成为安全的基石,日常生产、生活中使用的SSH、mTLS或IPsec等协议和技术都基于此。伴随云原生2.0的来临,双向认证将是确保Kubernetes生态和整个云原生基础设施中服务之间的通信安全的理想方案。在该文中,将探究Cilium和Cilium Service Mesh是如何利用eBPF为服务提供一种新的基于身份(IBE)的双向认证方案,其高性能的数据平面可以支持任何网络协议,而无需改变应用程序或注入sidecar。同时我们还将探究如何通过扩展身份概念以涵盖进程、二进制文件和执行环境等来大规模增强安全模型,例如,只允许在非特权环境中运行的某些二进制文件相互认证。
双向认证
双向认证是指两方,即发送方和接收方,相互认证对方的身份,以确保他们都是在与他们期望沟通的一方进行对话,以前称为相互实体认证,因为两个或多个实体在传输任何数据或信息之前会验证对方的合法性。这不能与完整性和保密性相混淆。完整性确保交换的信息没有被篡改。保密性确保信息保持机密性。人们通常认为 "加密 "能保证上述这三者,但它们事实上是可以割裂的。日常中,我们每天都在使用TLS来实现保密性、完整性和服务端认证,但通常不依赖于双向认证,即TLS会话能够确保我们与正确的服务器通信,但我们随后依靠密码或不同形式的认证方式来认证网络服务。
双向认证通常使用公钥和私钥对或单一共享密钥来实现。这两种形式都依赖于使用加密的信息进行握手。下面是一个关于TLS 1.3的握手方式的例子。
在通信两端的身份通过握手建立后,一个加密的通道被建立起来,在TLS会话期间在这两个身份之间传输数据。
如上图所示,双向TLS(mTLS)是指在服务器端和客户端之间使用双向加密通道。而今,mTLS是确保云原生应用程序中微服务之间的通信安全的首选协议,但它不是唯一的方式。IPsec使用IKE(互联网密钥交换)作为握手,对通信两端的节点端点进行认证,然后在它们之间建立一个加密的数据连接。
认证:基于会话vs基于网络
双向认证的一个关键因素是身份的粒度,即发放身份和证书的粒度。例如,针对护照这类身份证明文件,可以为每个人发放单独的护照,也可以为生活在同一家庭的所有人发放一本护照,甚至可以用一本护照来识别生活在同一城镇的所有人。根据你选择的识别粒度,可以进行不同级别的认证。
当前双向认证的两种典型模式:基于会话与基于网络的认证。
根据上述的参照表格,显然基于会话与基于网络的认证都具备一系列的优势,理想状态下,希望最好能把两者相互结合。我们想要更好的身份认证粒度的服务认证,包含TLS握手的特性,并能将其与基于网络的认证方法的透明度、性能和对不同网络协议的广泛支持等特性结合起来。
切割认证和数据传输
一旦将认证握手与有效载荷传输分开,我们可以使用TLS 1.3作为握手协议,同时依靠IPsec或WireGuard作为性能更好、更透明的有效载荷通道。
我们获得了两种模式的好处,包含了许多强大的特性。
- 连接不再需要被终止。而基于sidecar的方法需要将每个TCP连接转换为3段,以注入TLS。非sidecar方案不需要终止或操作连接。
- 无需注入sidecar。不需要运行额外的代理程序。代理服务的认证可以由一个节点来执行。在Cilium的解决方案中中,这个代理已经存在。其简化了管理,改善了资源占用,并提高了可扩展性。
- 支持非TCP和多播。虽然受益于TLS 1.3的强大特性,如低延迟握手,但TLS并没有限制传输能力。支持UDP、ICMP和任何其他可以依托IP传输的协议。
- 支持现有的身份认证和证书管理。任何基于mTLS的认证控制平面或身份管理系统都能够兼容,以提供相应服务。其中包括SPIFFE、Vault、SMI、Istio等。
- 握手缓存和重新认证。握手可以一次完成,并进行缓存,而且经过认证的服务之间可以进行通信,而不会为已经认证的服务带来额外的延迟,并且可以定期认证,以完成对服务进行重新认证。
- 可选的完整性和保密性。即提供可选的完整性和保密性。
上面的图显示了两种模式的对照情况。左边是传统的基于sidecar的mTLS方法,依靠sidecar将TLS注入到每个连接。右边显示的是非sidecar的方案,有效载荷连接保持不变,而TLS认证由Cilium单独执行,同时在eBPF的帮助下控制有效载荷连接。
Cilium服务网格双向认证
Cilium内置的服务认证服务和网络策略功能,是整合SPIFFE、Vault、SMI、cert-manager或Istio等高级身份和证书管理的理想平台,其使现有的身份和证书管理层可以用来管理服务身份并生成证书,然后,这些证书被用来执行如Pods或外部工作负载(如虚拟机、物理机等)的Cilium身份之间的双向认证。
让我们从配置的角度来看看如何实现的。我们将以SPIFFE与Cilium的为例。其允许在创建网络策略时使用SPIFFE身份来选择工作负载。
场景一:允许应用2 =>应用1双向认证的通信
代码语言:javascript复制apiVersion: 'cilium.io/v2'
kind: CiliumNetworkPolicy
metadata:
name: 'auth-rule-spiffe-app1'
spec:
endpointSelector:
- matchLabels:
- spiffe://mycluster/app1: ''
ingress:
- fromEndpoints:
- matchLabels:
- spiffe://mycluster/app2: ''
如上例所示,网络策略通过SPIFFE身份指定允许的endpoints集合。这使得现有基于endpoint选择器的策略变得非常简单,并将其固化为使用基于证书的身份认证。
额外的安全层
值得注意的是,服务层面的双向认证并不是简单地取代网络层的网络策略。它是增加了一个额外的安全层。Cilium仍然像今天一样识别单个endpoint,网络分段仍然适用于这些单个endpoint。如果一个网络策略同时指定了SPIFFE身份和端点选择器,那么恶意的工作负载就无法通过被破坏的服务级证书来冒充该服务。
- 对于pod或服务的所有outbound流量,其目的地必须是pod的出口策略所允许的。假设一个特定的pod窃取了另一个pod身份的证书,这个恶意的pod不能简单地用另一个pod来验证自己,即使证书允许这样做。因为出口策略阻止这种恶意访问。
- 假设出口策略层通过,但目的地还是会被验证。除了验证目的地的证书也被窃取,当然,这个步骤还可以进行额外的验证,因为Cilium处于一个特殊的位置,可以代表服务进行验证。验证目的地的证书是否属于一个实际目的地节点上运行的工作负载?这可以防止身份盗窃,要求攻击者不仅要窃取服务证书和网络身份,还要求攻击者在应该运行服务的节点上运行冒充的工作负载。
- 与第2步相同,但对于接收者来说,要验证发送者的身份。同样,验证发送者使用的证书是来自一个应该运行这个工作负载的节点。
- 最后,入口策略必须允许该流量。如果代表服务的证书被破坏了,攻击者也必须能够冒充一个允许的网络身份。
性能测试
所有这些额外的安全对于性能有何影响?下面是在GKE上运行的Cilium与nighthawk基于不同型号的HTTP基准测试中的测量结果。
- 没有额外的双向认证(基线)
- 启用WireGuard以保证完整性和保密性
- 由Istio提供的Sidecar mTLS模型
注意:下面的基准已经更新,还包括了Istio在禁用协议嗅探特效以使Istio进入纯TCP模式。通过在Service中设置name: tcp可以达到同样的效果。
上图显示了没有任何HTTP处理的基线、配置了HTTP filter的Cilium和默认配置(协议嗅探)的Istio的P95延迟测量值,Istio会在检测到时自动执行HTTP解析。
这些测试数据与Istio文档中的延时基准测试基本一致。
这第二次测量限制了对TCP的参与,并禁用了所有的HTTP处理。Cilium中的HTTP过滤器被移除。对于Istio来说,因为默认启用的协议嗅探可能会导致HTTP处理,即使没有声明要解析HTTP的意图,因此,协议嗅探在本次测试中被禁用。
对于所有的测量,Istio已经通过移除默认的并发量限制以及移除默认的TCP过滤器来进行调整。重现性能基准的脚本可以在这个代码库中找到。
总结
由于Cilium服务网格的1.12版本已经是稳定版,这种双向认证方案是Cilium服务网格的下一个关注点。我们相信,不仅可以与现有的身份管理解决方案(如SPIFFE、cert-manager甚至Istio作为控制平面)进行很好的整合,还可以提供一个更优雅、更高性能、更安全的认证实现,并结合强大的数据路径属性。与NetworkPolicy的紧密结合提供了一个简单易用但高度安全的通信模式,可以防止网络冒充和服务身份窃取。鉴于我们已经实现了所有的前提条件,预计这种双向认证功能将在1.13中实现。
由于笔者时间、视野、认知有限,译文难免出现错误、疏漏等问题,期待各位指正交流。
原文链接
https://isovalent.com/blog/post/2022-05-03-servicemesh-security