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

Istio 服務網格可以幫助雲原生應用實現自動 mTLS,完成網格內的流量加密,有助於縮小云原生部署的攻擊面,是構建零信任應用網絡的關鍵框架。爲了理解 Istio 中的 mTLS 流量加密,本文將包括以下內容:

什麼是 TLS 和 mTLS?

TLS(Transport Layer Security,傳輸層安全性)是一種廣泛採用的安全協議,用於在聯網計算機之間建立經過身份驗證和加密的鏈接,旨在促進互聯網通信的私密性和數據安全性。TLS 作爲 SSL[1] (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 端口,但是你也可以使用任意端口。

當客戶端需要驗證服務端身份,以防中間人攻擊同時保證通信安全的情況下,在和服務端通信時會要求 TLS 加密。下圖展示了的是 TLS 加密通信的流程。

    1. 服務器向受信任的 CA(證書管理機構)申請並獲得證書(X.509 證書);
    1. 客戶端向服務端發起請求,其中包含客戶端支持的 TLS 版本和密碼組合等信息;
    1. 服務器迴應客戶端請求並附上數字證書;
    1. 客戶端驗證證書的狀態、有效期和數字簽名等信息,確認服務器的身份;
    1. 客戶端和服務器使用共享祕鑰實現加密通信;

以上僅是對 TLS 通信流程的一個概要描述,實際的 TLS 握手過程比較複雜,請參考這篇文檔 [2] 。

從以上過程中你會發現,證書是代表服務器身份的關鍵要素,對於互聯網公開服務,服務器需要使用權威認證的 CA 頒發的證書,而對於私有環境內部的服務,可以使用 PKI(Private Key Infrastructure,私鑰基礎設施)來管理證書。

雙向 TLS 或相互 TLS(Mutual TLS 或 mTLS)是指在服務端和客戶端之間使用雙向加密通道,需要雙方相互提供證書並驗證對方身份。關於如何在 Kubernetes 中使用 mTLS 請參考這篇文章 [3] 。關於 mTLS 的詳細介紹請見 這篇文章 [4] 。

什麼是 TLS 終止?

TLS 終止(TLS Termination)指的是在將 TLS 加密流量傳遞給 Web 服務器之前對其進行解密的過程。將 TLS 流量卸載到入口網關或專用設備上,可以提高 Web 應用的性能,同時確保加密流量的安全性。一般運行在集羣入口處,當流量到達入口處時實施 TLS 終止,入口與集羣內服務器之間的通信將直接使用 HTTP 明文,這樣可以提高服務性能。

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 配置 [5] 。

Istio 中如何實現自動 mTLS?

下圖中展示的是 Istio 安全架構圖,從圖中可以看到在入口處使用 JWS + TLS 認證和加密,在 Istio 網格內部的所有服務間都開啓了 mTLS。

Istio 中內置了 CA,使用 xDS 中的 SDS(Secret Discovery Service,祕密發現服務)實現 SVID 證書的簽發和輪換。Istio 網格內的 mTLS 流程如下:

  1. 1. Sidecar 代替工作負載向 Istiod 申請證書,Istiod 簽發 SVID[6] 證書(該過程比較複雜,我將在今後的博客中說明);

    1. 客戶端請求被 Pod 內的 sidecar 攔截;
    1. 客戶端 sidecar 與服務端 sidecar 開始 mTLS 握手。在握手的同時,客戶端 sidecar 中的 JWT 和認證過濾器將對請求的身份進行認證,認證通過後將身份存儲在過濾器元數據中,然後請求經過授權過濾器,判斷請求權限。
    1. 若請求通過了認證與授權,則客戶端和服務端開始建立連接進行通信。

Istio 中有三個資源對象可用於配置服務間的認證與授權:

如何使用 Istio 爲服務開啓自動 mTLS?

你可以在 PeerAuthentication 中指定對目標工作負載實施的 mTLS 模式。對等認證支持以下模式:

Istio 的對等認證默認使用 PERMISSIVE 模式,自動將 mTLS 流量發送到這些工作負載,將純文本流量發送到沒有 sidecar 的工作負載。在將 Kubernetes 服務納入 Istio 網格後,爲了防止服務無法通過 mTLS,我們可以先使用 PERMISSIVE 模式。當我想爲某些服務開啓嚴格的 mTLS 模式時,可以使用以下兩種方式之一:

下面以爲 default 命名空間下的 reviews 服務設置 mTLS 爲例說明。

使用 PeerAuthentication 爲工作負載設置 mTLS

你可以使用 namespace 和 selector 指定某個命名空間下的某個工作負載開啓嚴格的 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 文檔 [7] 。

使用 DestinationRule 爲工作負載設置 mTLS

DestinationRule 用於設置流量路由策略,例如負載均衡、異常點檢測、TLS 設置等。其中 TLS 設置中包含多種模式 [8] ,使用 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 禁用探針重寫 [9] 。

最後當網格中的服務訪問一些外部服務時,也不需要 mTLS。

總結

mTLS 實現了網格內流量的加密,是構建零信任應用網絡的關鍵一步。藉助 Istio 我們可以很方便的爲 Kubernetes 中的服務開啓自動 mTLS,省去管理證書的麻煩。同時,我們也可以針對性的爲網格內的部分服務開啓 mTLS,便於我們將 Kubernetes 中的服務遷移到網格內。關於 Istio 中的證書管理,我們將在今後的博客中再做說明。

參考

引用鏈接

[1] SSL: https://www.ssl.com/faqs/faq-what-is-ssl/
[2] 這篇文檔: https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/
[3] 這篇文章: https://lib.jimmysong.io/blog/mtls-guide/
[4] 這篇文章: https://www.cloudflare.com/zh-cn/learning/access-management/what-is-mutual-tls/
[5] 網關 TLS 配置: https://istio.io/latest/zh/docs/ops/configuration/traffic-management/tls-configuration/#gateways
[6] SVID: https://lib.jimmysong.io/kubernetes-handbook/auth/spiffe/#svid
[7] Istio 文檔: https://istio.io/latest/zh/docs/tasks/security/authentication/mtls-migration/
[8] 多種模式: https://istio.io/latest/docs/reference/config/networking/destination-rule/#ClientTLSSettings-TLSmode
[9] 爲 Pod 禁用探針重寫: https://istio.io/latest/zh/docs/ops/configuration/mesh/app-health-check/#disable-the-http-probe-rewrite-for-a-pod
[10] 什麼是 TLS(傳輸層安全性)?- cloudflare.com: https://www.cloudflare.com/zh-cn/learning/ssl/transport-layer-security-tls/
[11] 什麼是相互 TLS(mTLS)?- cloudflare.com: https://www.cloudflare.com/zh-cn/learning/access-management/what-is-mutual-tls/
[12] What happens in a TLS handshake? | SSL handshake - cloudflare.com: https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/
[13] 寫給 Kubernetes 工程師的 mTLS 指南 - lib.jimmysong.io: https://lib.jimmysong.io/blog/mtls-guide/
[14] 雲原生安全白皮書中文版 - github.com: https://github.com/cncf/tag-security/blob/main/security-whitepaper/v1/cloud-native-security-whitepaper-simplified-chinese.md
[15] Istio 安全 - istio.io: https://istio.io/latest/zh/docs/concepts/security/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/TXg4WXpIj60yXM5RLCLDsg