云計算時代容器安全綜述-容器間安全通信

在分布式系統(tǒng)中,通常會有數(shù)量巨大的組件協(xié)作來完成某項具體的工作,協(xié)作的完成需要組件之間相互通信。在容器化部署的場景下,通信主要分為兩類,容器實例之間,以及容器實例和外部系統(tǒng)之間的通信。無論是容器之間還是容器和外部系統(tǒng)之間,為了確保通信的安全,我們需要借助于安全機制來保護通信信息不被惡意攻擊者獲取。

閱讀過筆者安全基礎(chǔ)系列文章的同學(xué)應(yīng)該對如何確保通信線路上的安全不陌生,如果你還有映像的話,我們介紹過如何使用對稱加密以及非對稱加密,哈希來確保通信的機密性和信息的防篡改。雖然筆者在介紹這些內(nèi)容的時候并沒有和具體的部署方式對應(yīng)起來,大家大可粗略的認(rèn)為所有的加密和安全手段在容器通信的場景中都是適用的。雖說筆者已經(jīng)有系列文章詳細(xì)介紹了加密相關(guān)的內(nèi)容,但是對于容器部署的場景來說,咱們需要把前邊介紹的安全基礎(chǔ)內(nèi)容帶入到具體的場景中,來詳細(xì)介紹容器間或者容器和外部系統(tǒng)之間的安全通信如何實現(xiàn),這也是這篇文章的主要內(nèi)容。

作為項目的技術(shù)負(fù)責(zé)人,架構(gòu)師,我們經(jīng)常需要為構(gòu)建的云原生分布式系統(tǒng)配置證書(certificates),秘鑰;特定情況下,我們也需要為Kubernetes集群配置安全認(rèn)證中心(certificate authorities),為etcd配置證書來確保etcd和API server之間的通信安全等等。所說這些安全配置工作沒有什么難度,但是相信有經(jīng)驗的讀者經(jīng)常需要面對:對著操作手冊一頓執(zhí)行后,發(fā)現(xiàn)結(jié)果不符合預(yù)期。背后的主要原因也不難理解,因為這些操作手冊告訴我們的是WHAT(做),而我們可能根本不知道WHY和HOW,因此無論是手冊本身缺少某個參數(shù)(或者由于版本問題未更新,某個命令和參數(shù)已經(jīng)不適用)都會導(dǎo)致我們需要花費大量的時間來搞定。因此對通信安全所涉及到的所有組件有體系化的理解,以及知道這些組件是如何集成在一起提供安全防護是非常必要的。

安全通信這個概念雖然非常簡單,但是筆者最近的實踐經(jīng)驗顯示,大部分關(guān)于技術(shù)的爭論其實都是概念之爭,因為技術(shù)術(shù)語都是經(jīng)過抽象形成的縮略語,每個人的背景知識體系的差異,會導(dǎo)致端看似簡單的概念,有著不小的理解偏差。特別是涉及到核心問題的時候,一般都是由于這些細(xì)小的理解偏差,導(dǎo)致經(jīng)常會出現(xiàn)ppt上講的很歡樂,一到具體落地就是各種理解不一致,爭論。我了讓本文后續(xù)的內(nèi)容更加準(zhǔn)確,咱先從定義什么是安全通信鏈路(secure connections)開始。

隨著互聯(lián)網(wǎng)和互聯(lián)網(wǎng)應(yīng)用的發(fā)展,特別是在中國內(nèi)地,我們的日常生活已經(jīng)徹底離不開”連接“。比如昨天晚上筆者帶孩子和家人出去,路過新竹路保利時代附近看到有藥店,妻子臨時決定下車給孩子買抗過敏的藥,誰知道這一去竟然花費了半個小時(預(yù)期在10分鐘內(nèi),因為這個藥很常見,也不是最近非常敏感的感冒藥),買回來一問原因,智鹿大藥房的網(wǎng)絡(luò)出現(xiàn)故障,因此所有人必須排隊,然后店員用本子記錄每一筆銷售記錄,這就非?;ㄙM時間了。從這個場景可見一斑,我們對網(wǎng)絡(luò)的依賴可能遠遠超過我們的認(rèn)知。

咱們來看另外一個例子,雖然說大部分的銀行現(xiàn)在都有自己的App,不過在5年前網(wǎng)銀還占據(jù)主流,我們通過自己的瀏覽器打開銀行的網(wǎng)絡(luò)銀行頁面,哪個綠色的padlock讓我們可以安心的輸入自己的銀行卡賬號和密碼,而不用太擔(dān)心自己的賬號被竊取。如果我們扒開這個綠色的padlock,支撐這種安全連接主要由兩部分組成:

- 首先你需要非常小心的確認(rèn)打開的網(wǎng)站是真的銀行網(wǎng)絡(luò)銀行網(wǎng)站,這通過瀏覽器驗證網(wǎng)站證書來實現(xiàn)。

- 其次當(dāng)我們在打開的頁面上輸入銀行卡和個人隱私信息的時候,數(shù)據(jù)在通信鏈路上進行了加密,來確保即便在中間節(jié)點有惡意攻擊者在偵聽通信數(shù)據(jù),也無法對解析這密文從而讓賬戶受損。

這種通信鏈路的安全通常由HTTPS協(xié)議提供,簡單說HTTPS就是安全的HTTP協(xié)議。這種安全主要由傳輸層來保障,因此我們也習(xí)慣于把提供安全通信的手段稱作TLS(Transport layer security)。說到這里,可能有同學(xué)會說,我還聽說過SSL(secure socket layer),這個和HTTPS以及TLS有啥關(guān)系?本質(zhì)上都是一回事,由于傳輸層是安全手段實施的地方,因此業(yè)界逐步用TLS來替換SSL這個術(shù)語。SSL規(guī)范是網(wǎng)景(Netscape)公司在1995年發(fā)布的通信安全規(guī)范,互聯(lián)網(wǎng)工程任務(wù)組(IETF)基于網(wǎng)景公司的SSL v3.0在1999年發(fā)布了國際標(biāo)準(zhǔn)TLS v1.0,目前業(yè)界主要使用的是TLS v1.3。

因此無論是叫SSL還是TLS,本質(zhì)上解決的兩個通過網(wǎng)絡(luò)連接的實體之間安全通信鏈路的問題。不過讓人奔潰的是,經(jīng)過了大約20多年的發(fā)展,還有相當(dāng)一部分人繼續(xù)把這種安全鏈路機制稱作是SSL證書機制,即便是國際標(biāo)準(zhǔn)TLS已經(jīng)更新了三個版本。你以為這就完了,實際上如果你從事的是安全領(lǐng)域,這兩種叫法都不是太準(zhǔn)確,準(zhǔn)確來說,我們應(yīng)該稱這些證書為X.509證書,因為在傳輸層(transport layer)上使用的秘鑰都是通過X.509證書來交換??偨Y(jié)一下筆者覺得如果你不是從事專業(yè)的安全領(lǐng)域,為了統(tǒng)一語言,大家還是稱之為TLS會更加實用,也不會產(chǎn)生很多誤解。

證書的格式由ITU(International Telecommunications Union)定義,也就是前文提到的X.509格式證書,大白話說就是一個數(shù)據(jù)結(jié)構(gòu),里邊包含了證書持有者的identity信息,公鑰信息等(希望讀者還記得咱們前邊關(guān)于非對稱加密算法文章內(nèi)容,公鑰加密就是非對稱加密,通常會產(chǎn)生一對秘鑰:公鑰和私鑰)。如下圖是一張證書的示意圖,包含了證書持有者的信息,秘鑰和過期時間等:

《圖1.1 證書示意圖》

從上邊的示意圖我們可以清晰的看到證書包含的關(guān)鍵信息包含:

- 證書的持有者唯一標(biāo)識符信息(云攀),我們通常把證書頒發(fā)給的實體(entity)也稱作subject,而subject的名稱一般在網(wǎng)絡(luò)通信領(lǐng)域為domain name的形式,比如http://wwww.example.com 之類的,在真實使用場景中,證書還包含一個叫subject alternative name的字段,用來提供靈活性

- subject的公鑰信息

- 證書的辦法機構(gòu)名稱

- 證書的有效期,比如上圖中的2099-11-28

咱們來說說這個公鑰字段,非對稱加密需要一對秘鑰,公鑰和私鑰,如其名所指,公鑰就是公鑰的秘鑰的意思,任何人都可以獲取到網(wǎng)站的公鑰。和公鑰對應(yīng)的是私鑰,私鑰信息應(yīng)該保證機密性,只有owner才知道的信息。

我們通過openssl這樣的工具創(chuàng)建證書的時候,私鑰(private key)會首先被創(chuàng)建出來,然后基于私鑰來計算創(chuàng)建公鑰(public key),公鑰和私鑰雖然看起來很簡單,但是使用場景和范圍遠超大家的想象:

- 通過公鑰加密的信息,只有私鑰才能解密,這解決了數(shù)據(jù)在傳輸過程中的機密性,也解決了秘鑰交換的問題,因為公鑰是可以通過公共渠道獲取的信息

- 私鑰可以用來對消息進行簽名,這個簽名信息可以用公開的公鑰進行驗證(verify),用來證明”我是我“的問題

咱們接下來請出愛麗斯女王和鮑勃領(lǐng)主,看看在王國內(nèi)安全的傳遞八卦信息是如何借助于公鑰和私鑰提供的加密和簽名能力的。女王可以通過自己的”寶箱“產(chǎn)生一對秘鑰:公鑰和私鑰。然后將公鑰讓信使帶給領(lǐng)主,這樣領(lǐng)主就可以用女王的公鑰來加密信息,然后將密文發(fā)送給女王,女王收到密文后,從保險箱中拿出自己的私鑰,對密文進行解密,就獲知了領(lǐng)主發(fā)送給自己的八卦信息。

但是這里有個問題,不知道大家是否覺察到?當(dāng)女王讓信使將自己的公鑰穿越荒蠻之地帶給領(lǐng)主的時候,領(lǐng)主如何能夠相信這個公鑰就是女王的?換句話說,如果信使換成自己公鑰,或者半路上信使被斯塔克城堡主給活捉了,然后信使和斯塔克城堡主做了交易,信使帶著斯塔克城堡主的公鑰去見領(lǐng)主,這都是可能存在的場景。其實這種場景在我們?nèi)粘I钪须S處可見,過去幾年網(wǎng)絡(luò)上流行的段子”證明你媽是你媽“要解決的就是這個問題。

為了讓領(lǐng)主能夠驗證收到的證書的確來自于女王,我們需要在通信雙方之間引入大家都信任的第三方,通過第三方公證機構(gòu)來為證書的可信背書,這在日常生活中就是派出所,而在安全中心中叫證書中心,證書頒發(fā)中心(certificate authority)。

證書中心,或者也叫CA,是一個被廣泛信任的機構(gòu),主要的職責(zé)就是證書管理,包括證書的簽發(fā),驗證等工作。CA在安全通信的場景中主要用來解決證書的可信任性問題,舉個例子,當(dāng)我們打開一個”自認(rèn)為“是招商銀行的網(wǎng)站,我們的瀏覽器收到對端的證書后,需要驗證兩個信息:第一個是證書是否頒發(fā)給這個URL;第二個是頒發(fā)證書的機構(gòu)是否可信。

第一個問題比較容易解決,證書中的subject name和alternative subjec name可以用來驗證訪問的網(wǎng)站是否為釣魚網(wǎng)站,而第二個問題就沒有那么檢查,我們?nèi)绾涡湃晤C發(fā)證書的CA?如果解決這問題的方案是再引入一個第三方,那么誰能為這個新引入的第三方可信背書呢?解決這種循環(huán)依賴的問題就是self-signed證書,一個特殊的X.509證書來為自己背書。如下圖所示的證書鏈,女王的證書又鮑勃簽發(fā),鮑勃的證書由卡爾簽發(fā),卡爾通過self-signed類型的證書為自己背書:

《圖1.2 證書可信鏈》

有了卡洛提供的這種self-signed的自驗證證書,我們就解決了這種先后雞還是先有蛋的問題。通常情況下瀏覽器都默認(rèn)安裝了一批可信的證書,這些證書頒發(fā)自可信的CA,我們也把辦法這些證書的機構(gòu)稱作為根CA(root CAs)。具體來說我們的瀏覽器會信任任何來自于這些根CA簽發(fā)的證書,以及證書鏈,如果訪問網(wǎng)站提供的證書不是來自于可信的證書中心CA,那么瀏覽器會顯示錯誤,相信大家應(yīng)該在瀏覽器上看到過類似的證書風(fēng)險提醒信息。

如果我們希望自己的網(wǎng)站能夠被公網(wǎng)用戶訪問,那么我們就需要提供一個來自于受信證書頒發(fā)機構(gòu)簽發(fā)的證書,比如阿里云就提供這樣的服務(wù),有了這個證書后,我們就可以在將證書上傳到網(wǎng)站對應(yīng)的組件上,對外提供安全的HTTPS連接服務(wù)。在分布式系統(tǒng)的設(shè)計中,不是所有組件都需要直接提供外部互聯(lián)網(wǎng)用戶的直接訪問,比如Kubernetes的API Server和ETCD之間的安全線路,由于這是一種典型的內(nèi)網(wǎng)兩個組件之間的互操作,因此這個證書是否被瀏覽器驗證可信并不重要,重要的是兩個組件之間可以通過這個證書安全的通信。

無論是那種類型的證書,通常情況下我們需要請求CA幫助我們產(chǎn)生需要的證書問文件,證書通過CSR(Certificate Signing Request)請求發(fā)送給CA。CSR請求主要包含如下信息:

- 證書關(guān)聯(lián)的公鑰

- 證書簽發(fā)的域名(domain name)

- 證書簽發(fā)實體(entity)的企業(yè)基本信息,比如公司名稱,公司的營業(yè)執(zhí)照信息等

CSR請求會被發(fā)送給CA來生成X.509證書,從上邊的信息的內(nèi)容可以看到和證書中包含的信息相匹配。上邊描述的信息和大家通過openssl生成證書的步驟略微不同,因為咱們通過openssl來創(chuàng)建秘鑰對和證書是一步完成的。如果深入到openssl的秘鑰創(chuàng)建過程,你會發(fā)現(xiàn)openssl只接受唯一的參數(shù):私鑰來創(chuàng)建證書。

背后的原理想必大家也能理解,因為公鑰基于私鑰計算而成,接著openssl會基于私鑰來生成證書并簽名,整個證書生成過程中不會使用公鑰,因為公鑰是用在對端對數(shù)據(jù)加密用,并且對端的公鑰來自于從服務(wù)器上獲得的證書中。有了對證書的初步了解之后,接下來咱們可以聊聊TLS(Transport Layer security)機制了。

傳輸層的安全鏈路的建立由客戶端發(fā)起(client),而響應(yīng)請求的一端叫做服務(wù)端(server),并且從技術(shù)原理的角度看,客戶端和服務(wù)器端的概念只在傳輸層有效,因為在傳輸層之上,我們一般把通信的兩端稱作peers。具體來說客戶端打開網(wǎng)絡(luò)套接字socket發(fā)送請求給服務(wù)端,對于安全鏈路來說,服務(wù)端收到請求后會首先返回證書(certificate)。

客戶端收到服務(wù)端返回的證書后,可以從中extract兩個非常重要的信息:服務(wù)器端標(biāo)識和公鑰信息。server identify連同證書會被客戶端進行驗證,驗證證書是否有效以及來自于可信機構(gòu)頒發(fā),以及證書中的domain name和訪問的是否一致(預(yù)防釣魚網(wǎng)站)。如果驗證通過,客戶端會用證書中的公鑰來和服務(wù)器端建立后續(xù)溝通需要的對稱加密秘鑰(symmetirc key),至于為什么用對稱加密秘鑰,主要原因是對稱加密的效率,具體的數(shù)據(jù)原理筆者會在后續(xù)安全基礎(chǔ)類文章中介紹,大白話說就是對稱加密基于bit操作而非對稱加密基于數(shù)學(xué)計算,因此對稱加密的效率要高很多。如下圖所示:

《圖1.3 TLS握手協(xié)議》

大家在實際代碼開發(fā)的過程中,肯定聽說過skip verify機制,大白話說就是在客戶端關(guān)閉對證書的驗證,假設(shè)證書提供的信息可信,這主要是為了方便開發(fā)。但是在生產(chǎn)環(huán)境中千萬不要開啟這個配置,因為我們需要依賴于客戶端的證書驗證機制來確保服務(wù)端的真實有效。另外上圖中也把服務(wù)端對客戶端證書的verify表示出來了,特別是在金融領(lǐng)域,服務(wù)區(qū)需要知道持有這個賬戶的客戶和聲稱的一致,因此需要驗證客戶端的證書來提供敏感賬戶信息,比如余額等。

文章的最后我們來整體看看上邊描述的這些安全手段,對于容器實例間通信意味著什么?基于筆者過往的經(jīng)驗,以下最佳實踐需要讀者在自己的項目中盡量遵守:

- 咱們在安裝K8S集群或者配置K8S集群的某些組件的時候,會涉及到證書的安裝,大家要注意這些證書和我們所說的secure容器間的鏈路或者公網(wǎng)到容器實例間鏈路不同,不是一回事。

- 作為開發(fā)人員,我們編寫代碼的時候可能需要設(shè)置安全訪問鏈路,比如支持HTTPS訪問,那么就需要手動的來進行證書的管理和更新。不過筆者建議大家考慮使用服務(wù)網(wǎng)格的邊車容器模式來替換。

證書在分布式系統(tǒng)中已經(jīng)被當(dāng)做基礎(chǔ)設(shè)施來對待了,由于證書本身包含敏感信息,因此大家需要在自己的應(yīng)用中,特別是K8S集群中安全的管理這類隱私數(shù)據(jù)。筆者在K8S集群系列文章中有關(guān)于secret管理的詳細(xì)介紹,不過我們下篇文章還是會從容器安全的角度進行抽象和信息梳理。

整個基于證書的安全體系很健全,但是如果私鑰的管理出現(xiàn)安全問題,我們所做的所有努力就將付之一炬。因此在大部分安全要求高的業(yè)務(wù)場景中,除了證書機制之外,我們還需從流程上保證證書定期更換??紤]到證書的數(shù)量以及更換可能導(dǎo)致的各種手動配置工作造成的風(fēng)險,筆者強力建議采用自動的證書定期更換,以及使用像阿里云提供的KMS這樣的托管秘鑰管理服務(wù)來streamline這個過程。

好了,今天這篇文章就這么多了,下篇文章咱們來介紹在Kubernetes中如何安全的管理隱私信息,敬請期待!

注:在Kubernetes集群中,kublet和API Server之間需要證書的支持來進行https通信,并且使用的證書可以被很方便的替換;另外所有調(diào)用API Server提供的服務(wù)接口的客戶端都需要證書來證明的identity。不過由于Kuberntes集群的特殊性,目前還不支持證書回收(certificate revocation)。我們需要使用RBAC來顯示的聲明某些賬戶對不可訪問性。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容