十二張圖:從0開始理解對稱/非對稱加密、CA認證、以及K8S各元件頒發證書原由

2022-06-13 09:00:25

一、對稱加密

對稱加密的過程類似下圖中,通訊的雙方約定好使用統一的加密解密演演算法,以及一個salt鹽作為唯一標識,傳送資料前先試用加密演演算法和salt經過加密函數處理得到密文,接受方收到密文後使用解密演演算法+salt對密文解密得到明文再處理。

二、對稱加密-不安全

對稱加密的缺陷如駭客可能會列舉出對稱加密演演算法,而且salt是唯一的,不會為不同的服務建立不同的salt。

一旦出現資訊洩漏,很可能出現如下情況:使用者端和伺服器端之間的資料被駭客竊取並篡改,再將篡改後的資料發給伺服器端,因為駭客知道完整的加解密方法和salt,所以他能瞞天過海。

三、非對稱加密

非對稱加密涉及到了:公鑰和私鑰

特點是:

  • 特性1:使用公鑰加密的資料只有私鑰才能解密,公鑰自己是解密不了的。
  • 特性2:使用私鑰加密的資料只有公鑰才能解密,私鑰自己是解密不了的。
  • 伺服器端同時持有公鑰和私鑰(不會給任何人)。
  • 伺服器端要跟誰通訊就把自己的公鑰給它。

使用非對稱加密的互動的過程如下:使用者端先拿到伺服器端的公鑰,然後使用這個公鑰加密資料,再把加密後的資料傳送給伺服器端,由於上面說的特性1、2,這時只有伺服器端才能正確的解密出資料。

四、非對稱加密-不安全

如下紅色部分,伺服器端傳送給使用者端的資料如果使用公鑰加密,那麼使用者端肯定解密不了,看起來它只能使用私鑰加密,這時使用者端可以使用之前獲取到的公鑰解密。

但是問題是所有人都能獲取到伺服器端的公鑰,包括駭客。所以駭客也能解密出伺服器端傳送過來的資料。

五、對稱加密和非對稱加密結合

兩者結合的方式如下,使用者端先獲取到伺服器端的公鑰,然後自己生成一個唯一的隨機金鑰A,使用公鑰加密隨機金鑰A,這時只有伺服器端的私鑰才能解密出隨機金鑰A,所以即便被加密的隨機金鑰A被駭客截獲它也解密不出啥。

伺服器端拿到隨機金鑰A之後,伺服器端和使用者端雙方約定從此之後雙方的互動使用隨機金鑰A做對車加密的salt,全球只有他倆知道,所以很安全。

六、對稱加密和非對稱加密結合-不安全

如下圖這樣,假設駭客很厲害他有自己的公鑰和私鑰,而且從一開始就擷取了使用者端的請求,然後自己冒充伺服器端,在使用者端和伺服器端的互動過程中全程充當一個代理的存在,這樣駭客依然能獲取到雙方互動的所有資料。

簡而言之這個問題就出在:使用者端太信任他拿到的公鑰了

七、Https的做法-引入CA機構

為了解決上面說到的:使用者端太信任他拿到的公鑰問題,引入了第三方的CA機構。

CA機構出現之後,所有人就約定:我們只相信被CA機構信任的公鑰(也就是下面說到的證書)

可以直接看上圖,CA機構有自己的公鑰和私鑰,大家絕對信任CA認證機構,讓他做安全方面的背書。

這時駭客再想插進入比如偷偷替換伺服器端的公鑰,那不好意思,使用者端只相信權威機構的公鑰能解析的證書。即便駭客自己也有CA機構頒發給他自己的證書,使用者端也不會認,因為證書是和域名系結的,而域名是唯一的。

八、乘勝追擊理解K8S的中的證書

為了大家更好的理解,我特意化了下面這張圖。

相信很多小夥伴自己安裝K8S叢集的時候,莫名其妙的就得為各個元件安裝一大堆不知所然

這個問題不是很複雜,那我們隨便嘮叨幾句。

你看上圖:ApiServer、Controller Manager、Scheduler有一對自己的公鑰(CA給簽發的證書/自簽證書)和私鑰,而像kubelet這種只要有CA認證機構的公鑰匙證書就行。

原因是kubelet作為一個使用者端、ApiServer作為伺服器端,他們之間的關係和校權差不多可以按下面這張圖理解(看圖是不是很好理解??)

然後我們實踐一下這個過程,首先是證書是有CA認證機構簽發的,是要花錢買的,為了不破費,一般我們自己玩K8S都是使用cfssl做自簽證書。

  • Step1:所以第一步下載cfssl工具,藉助它的能力模擬CA機構的能力
wget "https://pkg.cfssl.org/R1.2/cfssl_linux-amd64" -O /usr/local/bin/cfssl
wget "https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64" -O /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl /usr/local/bin/cfssljson
  • Step2:初始化我們的根證書
$ cfssl gencert -initca ca-csr.json | cfssljson -bare /etc/kubernetes/pki/ca

# ca-csr.json檔案長下面這樣(裡面有過期時間,簽發機構的基礎資訊)
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes-manual"
    }
  ],
  "ca": {
    "expiry": "876000h"
  }
}

這一步相當於我們家自己開了個CA簽發公司,經過如上的命令我們能得到下面的三個證書檔案,分別是

ca-key.pem:可以理解成CA簽發機構的私鑰(絕對不能洩漏,不然CA機構將毫無存在的意義)

ca.pem:可以理解成CA簽發機構的公鑰,可以給任何人

ca.csr:證書請求檔案

  • Step3:給ApiServer頒發證書

首先給ApiServer頒發證書並不難理解,本質上就是ApiServer提供給CA機構一個公鑰,然後CA機構用自己的私鑰對ApiServer的公鑰進行加密,得到一個證書檔案。

其次是我們為啥要給ApiServer頒發證書?

原因是在啟動apiserver的時候啟動引數需要如下:(要自己的公私鑰和ca機構的公鑰)

然後就是對於ApiServer來說,他想讓CA機構給他頒發證書,它得提供一個csr證書請求檔案,一般長下面這樣

#  apiserver-csr.json 這裡面描述了加密演演算法、請求者機構基礎資訊
{
  "CN": "kube-apiserver",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "Beijing",
      "L": "Beijing",
      "O": "Kubernetes",
      "OU": "Kubernetes-manual"
    },
   "hosts": [
        "127.0.0.1",
        "192.168.0.1",
        "kubernetes.default",
        "kubernetes.default.svc",
        "kubernetes.default.svc.cluster",
        "kubernetes.default.svc.cluster.local",
        "10.10.10.12",
        "10.10.10.13",
        "10.10.10.14",
        "10.10.10.15"
    ],
  ]
}
  • Step4:然後CA機構為ApiServer頒發證書

對於我們自己家開的CA機構來說,執行如下命令即可完成證書的頒發

cfssl gencert   \ 
      -ca=/etc/kubernetes/pki/ca.pem  \
      -ca-key=/etc/kubernetes/pki/ca-key.pem   \
      -config=ca-config.json   \
      -profile=kubernetes  \
      apiserver-csr.json | cfssljson -bare /etc/kubernetes/pki/apiserver

然後我們解析一個各引數的含義

  1. apiserver-csr.json:是有step3中提到的,誰想讓CA機構給他頒發證書,誰就得提供csr檔案
  2. ca:我們自己家CA機構的公鑰,step2中生成了。
  3. ca-key:我們自己家CA機構的私鑰,step2中生成了。
  4. profile:指定使用config中的哪個usage。
  5. config:一版長下面這樣,裡面定義了證書的有效時間、還有一些usage
{
  "signing": {
    "default": {
      "expiry": "876000h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth", # 表示client可以用該 CA 對server提供的證書進行驗證;
            "client auth"  # 表示server可以用該CA對client提供的證書進行驗證;
        ],
        "expiry": "876000h"
      }
    }
  }
}

命令執行之後我們就能得到為apiserver的頒發的證書了

同樣的,對與ApiServer來說,它的公鑰證書apiserver.pem可以給任何人,但是它的私鑰apiserver-key.pem只有自己持有。

九、文末

本文到這裡就行將結束了,歡迎大家關注~

公眾號首發:https://mp.weixin.qq.com/s/RbvonLcS_mHza87bPkNdsQ
公眾號首發:https://mp.weixin.qq.com/s/RbvonLcS_mHza87bPkNdsQ
公眾號首發:https://mp.weixin.qq.com/s/RbvonLcS_mHza87bPkNdsQ

參考:https://cloud.tencent.com/developer/article/1802714