如何理解 Istio 中的 mTLS 流量加密?

标签: 理解 istio mtls | 发表时间:2022-11-21 11:09 | 作者:
出处:https://jimmysong.io/blog/

Istio 服务网格可以帮助云原生应用实现自动 mTLS,完成网格内的流量加密,有助于缩小云原生部署的攻击面,是构建零信任应用网络的关键框架。为了理解 Istio 中的 mTLS 流量加密,本文将包括以下内容:

  • 介绍什么是 TLS、mTLS 和 TLS 终止
  • 介绍 Istio 中如何实现 TLS 加密
  • 如何使用 Istio 为 Kubernetes 中的服务实现 mTLS?
  • 何时需要 mTLS?合适不需要 mTLS?

什么是 TLS?

TLS(Transport Layer Security,传输层安全性)是一种广泛采用的安全协议,用于在联网计算机之间建立经过身份验证和加密的链接,旨在促进互联网通信的私密性和数据安全性。TLS 作为 SSL (Secure Socket Layer,安全套接字层)的继任者,实际上是由 SSL 改名而来,因此人们经常将 TLS/SSL 混用,在本文中我们将统称为 TLS。 TLS 1.0 发布于 1999 年,最新版本为 1.3(发布于 2018 年 8 月),1.0 和 1.1 版本已弃用。

我们在浏览网页时看到的 HTTPS 实际上就使用了 TLS,如下图所示。TLS 是建立在 TCP 之上的,作为 OSI 模型中的会话层。为了保证兼容性,TLS 通常使用 443 端口,但是你也可以使用任意端口。

image HTTP vs HTTPS

当客户端需要验证服务端身份,以防中间人攻击同时保证通信安全的情况下,在和服务端通信时会要求 TLS 加密。下图展示了的是 TLS 加密通信的流程。

image TLS 加密通信流程

  1. 服务器向受信任的 CA(证书管理机构)申请并获得证书(X.509 证书);
  2. 客户端向服务端发起请求,其中包含客户端支持的 TLS 版本和密码组合等信息;
  3. 服务器回应客户端请求并附上数字证书;
  4. 客户端验证证书的状态、有效期和数字签名等信息,确认服务器的身份;
  5. 客户端和服务器使用共享秘钥实现加密通信;

以上仅是对 TLS 通信流程的一个概要描述,实际的 TLS 握手过程比较复杂,请参考 这篇文档

从以上过程中你会发现,证书是代表服务器身份的关键要素,对于互联网公开服务,服务器需要使用权威认证的 CA 颁发的证书,而对于私有环境内部的服务,可以使用 PKI(Private Key Infrastructure,私钥基础设施)来管理证书。

什么是 TLS 终止?

TLS 终止(TLS Termination)指的是在将 TLS 加密流量传递给 Web 服务器之前对其进行解密的过程。将 TLS 流量卸载到入口网关或专用设备上,可以提高 Web 应用的性能,同时确保加密流量的安全性。一般运行在集群入口处,当流量到达入口处时实施 TLS 终止,入口与集群内服务器之间的通信将直接使用 HTTP 明文,这样可以提高服务性能。

image TLS 终止

Istio 默认在入口网关处终止 TLS,然后再为网格内的服务开启 mTLS。你也可以让流量直通(passthrough)到后端服务处理,例如:

   apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: sample-gateway
spec:
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    tls:
      mode: PASSTHROUGH

详见 网关 TLS 配置

什么是 mTLS?

双向 TLS 或相互 TLS(Mutual TLS 或 mTLS)是指在服务端和客户端之间使用双向加密通道,需要双方相互提供证书并验证对方身份。关于如何在 Kubernetes 中使用 mTLS 请参考 这篇文章 。关于 mTLS 的详细介绍请见 这篇文章

Istio 中如何实现自动 mTLS?

下图中展示的是 Istio 安全架构图,从图中可以看到在入口处使用 JWS + TLS 认证和加密,在 Istio 网格内部的所有服务间都开启了 mTLS。

image Istio 安全架构图

Istio 中内置了 CA,使用 xDS 中的 SDS(Secret Discovery Service,秘密发现服务)实现 SVID 证书的签发和轮换。Istio 网格内的 mTLS 流程如下:

  1. Sidecar 代替工作负载向 Istiod 申请证书,Istiod 签发 SVID 证书(该过程比较复杂,我将在今后的博客中说明);
  2. 客户端请求被 Pod 内的 sidecar 拦截;
  3. 客户端 sidecar 与服务端 sidecar 开始 mTLS 握手。在握手的同时,客户端 sidecar 中的 JWT 和认证过滤器将对请求的身份进行认证,认证通过后将身份存储在过滤器元数据中,然后请求经过授权过滤器,判断请求权限。
  4. 若请求通过了认证与授权,则客户端和服务端开始建立连接进行通信。

Istio 中有三个资源对象可用于配置服务间的认证与授权:

  • RequestAuthentication:用于定义服务支持的请求级认证方式,目前只支持 JWT;
  • PeerAuthentication:配置服务间的传输认证模式,如 STRICTPERMISSIVEDISABLE 等,以开启 mTLS 或明文请求;
  • AuthorizationPolicy:用于授权服务间的流量,定义谁可以做什么?例如主体 A 允许( ALLOW)或拒绝( DENY)来自主体 B 的流量;

如何使用 Istio 为服务开启自动 mTLS?

你可以在 PeerAuthentication 中指定对目标工作负载实施的 mTLS 模式。对等认证支持以下模式:

  • PERMISSIVE:默认值,工作负载可接受双向 TLS 或纯文本流量;
  • STRICT:工作负载仅接受 mTLS 流量;
  • DISABLE:禁用 mTLS。从安全角度来看,除非你有自己的安全解决方案,否则不应禁用 mTLS;
  • UNSET:从父级继承,优先级为服务特定 > 命名空间范围 > 网格范围的设置;

Istio 的对等认证默认使用 PERMISSIVE 模式,自动将 mTLS 流量发送到这些工作负载,将纯文本流量发送到没有 sidecar 的工作负载。在将 Kubernetes 服务纳入 Istio 网格后,为了防止服务无法通过 mTLS,我们可以先使用 PERMISSIVE 模式。当我想为某些服务开启严格的 mTLS 模式时,可以使用以下两种方式之一:

  • 使用 PeerAuthentication 定义流量如何在 sidecar 之间传输;
  • 使用 DestinationRule 定义流量路由策略中的 TLS 设置;

下面以为 default 命名空间下的 reviews 服务设置 mTLS 为例说明。

使用 PeerAuthentication 为工作负载设置 mTLS

你可以使用 namespaceselector 指定某个命名空间下的某个工作负载开启严格的 mTLS。例如下面的配置:

   apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: foo-peer-policy
  namespace: default
spec:
  selector:
    matchLabels:
      app: reviews
  mtls:
    mode: STRICT

你也可以给安装 Istio 的命名空间 istio-system 设置严格的 mTLS,那样会为网格中的所有服务开启严格的 mTLS,详细步骤请参考 Istio 文档

使用 DestinationRule 为工作负载设置 mTLS

DestinationRule 用于设置流量路由策略,例如负载均衡、异常点检测、TLS 设置等。其中 TLS 设置中包含 多种模式 ,使用 ISTIO_MUTUAL 模式可以为工作负载开启 Istio 的自动 TLS,如下所示。

   apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
  namespace: default
spec:
  host: reviews
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

什么时候用 mTLS?

互联网客户端对 Web 服务的访问,一般使用单向 TLS,即只需要服务端提供身份证明,而不关心客户端的身份。当你需要验证客户端身份时,使用单向 TLS可以使用密码、token、双因子认证等方式。不过这样的认证方式需要应用程序内部支持,而双向 TLS 是运行在应用程序之外的,不需要多应用逻辑进行修改。

当你需要正如你在上文中看到的,实施 mTLS 的服务间需要交换证书,当服务数量变大时,就需要管理大量的证书,这需要消耗大量的精力,使用服务网格可以帮助你实现自动 mTLS,彻底解决证书管理的难题。

什么时候不用 mTLS?

虽然 mTLS 是确保云原生应用程序服务间通信安全的首选协议,但是应用 mTLS 需要完成复杂的对称加密、解密过程,这将非常耗时且消耗大量的 CPU 资源。对于某些安全级别不高的流量,如果我们在流量入口处终止 TLS,并网格内部仅对针对性的服务开启 mTLS,就可以加快请求响应和减少计算资源消耗。

另外当有的服务无法获取证书,例如 Kubelet 上使用 HTTP 的健康检查,无法通过 TLS 访问服务内的健康检查端点,这时候就需要 为 Pod 禁用探针重写

最后当网格中的服务访问一些外部服务时,也不需要 mTLS。

总结

mTLS 实现了网格内流量的加密,是构建零信任应用网络的关键一步。借助 Istio 我们可以很方便的为 Kubernetes 中的服务开启自动 mTLS,省去管理证书的麻烦。同时,我们也可以针对性的为网格内的部分服务开启 mTLS,便于我们将 Kubernetes 中的服务迁移到网格内。关于 Istio 中的证书管理,我们将在今后的博客中再做说明。

参考

相关 [理解 istio mtls] 推荐:

如何理解 Istio 中的 mTLS 流量加密?

- - Jimmy Song - 专注于探索后 Kubernetes 时代的云原生新范式 – 博客
Istio 服务网格可以帮助云原生应用实现自动 mTLS,完成网格内的流量加密,有助于缩小云原生部署的攻击面,是构建零信任应用网络的关键框架. 为了理解 Istio 中的 mTLS 流量加密,本文将包括以下内容:. 介绍什么是 TLS、mTLS 和 TLS 终止. 介绍 Istio 中如何实现 TLS 加密.

如何理解 Istio 中的 VirtualService 和 DestinationRule?

- - Jimmy Song - 专注于探索后 Kubernetes 时代的云原生新范式 – 博客
Istio 在刚开源的时候就定义了几十个 CRD,其中用于流量治理的有 RouteRule、 DestinationPolicy、 EgressRule 等,后来推出了 v1alpha3 API 使用 VirtualService 和 DestinationRule 等取代了之前的 API.

如何理解 Istio Ingress, 它与 API Gateway 有什么区别?

- - Jimmy Song - 云原生|开源|社区 – 博客
API 网关作为客户端访问后端的入口,已经存在很长时间了,它主要是用来管理”南北向“的流量;近几年服务网格开始流行,它主要是管理系统内部,即“东西向”流量,而像 Istio 这样的服务网格还内置了网关,从而将系统内外部的流量纳入了统一管控. 这经常给初次接触 Istio 的人带来困惑——服务网格与 API 网关之间是什么关系.

istio 原理简介

- - 掘金 架构
由于 istio 自 1.5 版本以后架构上有了较大变化,控制面从多组件变成了单体的 istiod 组件,所以下文会先介绍 1.5 之前的架构,再介绍 1.5 之后的,是一个由繁到简的过程. istio 1.5 之前架构. Istio 的架构分为控制平面和数据平面. 数据平面:由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信.

Istio 常见的 10 个异常分析

- - DockOne.io
本文总结了使用 Istio 常见的 10 个异常. Istio 支持多平台,不过 Istio 和 Kubernetes 的兼容性是最优的,不管是设计理念,核心团队还是社区, 都有一脉相承的意思. 但 Istio 和 Kubernetes 的适配并非完全没有冲突,一个典型问题就是 Istio 需要 Kubernetes Service 按照协议进行端口命名(Port Naming).

Istio究竟是干嘛的? - 知乎

- -
当微服务架构体系越来越复杂的时候,需要将“业务服务”和“基础设施”解耦,将一个微服务进程一分为二:. 一个进程实现业务逻辑,biz,即上图白色方块. 一个进程实现底层技术体系,proxy,即上图蓝色方块,负载均衡、监控告警、服务发现与治理、调用链…等诸多基础设施,都放到这一层实现. biz不管是调用服务,还是提供服务,都只与本地的proxy进行本地通信.

使用 Istio 进行金丝雀部署

- -
本篇博客最后更新时间 2018 年 5 月 16 号,采用了最新版本的流量管理模型. Istio项目的一大好处就是为服务金丝雀方式部署提供了控制便利. 金丝雀部署(或上线)背后的想法是通过让一小部分用户流量引入的新版本进行测试,如果一切顺利,则可以增加(可能逐渐增加)百分比,逐步替换旧版本. 如在过程中出现任何问题,则可以中止并回滚到旧版本.

实践k8s istio熔断 - fat_girl_spring - 博客园

- -
熔断主要是无感的处理服务异常并保证不会发生级联甚至雪崩的服务异常. 在微服务方面体现是对异常的服务情况进行快速失败,它对已经调用失败的服务不再会继续调用,如果仍需要调用此异常服务,它将立刻返回失败. 与此同时,它一直监控服务的健康状况,一旦服务恢复正常,则立刻恢复对此服务的正常访问. 这样的快速失败策略可以降低服务负载压力,很好地保护服务免受高负载的影响.

知乎落地的 Service Mesh Istio

- -
在知乎,我们很早就进行了非常彻底的容器化部署. 全站在线运行的微服务数量高达两千多个. 这些微服务通过我们自己维护的 RPC 框架和 Kodor 体系来实现服务互联的能力. 在这其中,我们也存在一系列的问题:. 各种基础组件维护成本比较高,单点风险存在. 各语言客户端特性难以统一,熔断、重试等特性实现颇有不同,且不能做到动态线上进行调整.

Istio 中的服务和流量的抽象模型

- - IT瘾-dev
本文介绍了 Istio 和 Kubernetes 中的一些服务和流量的抽象模型. 虽然 Istio 一开始确定的抽象模型与对接的底层平台无关,但目前来看基本绑定 Kubernetes,本文仅以 Kubernetes 说明. 另外在 ServiceMesher 社区中最近有很多关于 Istio、Envoy、Kubernetes 之中的服务模型关系的讨论,本文作为一个开篇说明,Kubernetes 和 Isito 之间有哪些共有的服务模型,Istio 在 Kubernetes 的服务模型之上又增加了什么,为什么说 Kubernetes service 存在的意义仅剩下做服务发现.