這裡除了安全,什麼都不會發生!Docker映象P2P加速之路
  1. 1問題:

       在使用Docker執行容器化應用時,宿主機通常先要從Registry服務(如Docker Hub)下載相應的映象(image)。這種映象機制在開發環境中使用還是很有效的,團隊成員之間可以很方便地共享同樣的映象。然而在實際的生產環境中,當大量主機需要同時從Registry下載映象執行容器應用時(比如釋出新版本,打補釘等情形),Registry 服務往往會成為映象分發的瓶頸,應用映象需要較長時間才能傳送到所有主機上,使得應用釋出的週期大大延長。

不少企業提出了P2P加速映象下載的解決方案,但都是私有云及內部環境的使用場景,在公有云為得到使用。其中很大一部分原因是共有云使用P2P的安全性問題,如何確保使用者資料在P2P傳輸中是安全的成為了其中的難點。我們就該問題設計實現了確保使用者資料安全的P2P映象分發系統。本文就其安全性展開闡述。

 

  1. 2架構:

菊廠P2P容器映象分發系統包含3個元件:客戶端代理(Proxy)、BT客戶端和BT Tracker。

客戶端代理(Proxy)

客戶端代理部署在叢集的每個節點中,配置為Docker的Http Proxy,截獲Docker Daemon的映象下載請求,通知Client下載,並最終將映象匯入到Docker daemon中。

BT客戶端

部署在叢集節點的BT客戶端和Tracker共同組成了一個完整的P2P檔案傳輸系統。在整個映象的分發過程中,它們利用BT協議完成映象下載。

BT Tracker

Tracker是BT系統的一部分,它儲存了BT客戶端下載過程中所需要的後設資料資訊和種子資訊,並協助各個BT客戶端完成整個通訊過程。

 

  1. 3 安全:

       首先,我們限制了跨叢集的P2P下載,最大限度的租戶間的資料洩露。

之後,在鏈路層面的安全性和業務層面的安全性做了增強。

  1. 3.1 鏈路安全

一想到鏈路安全,我們首先會想到的是加密。

對稱加密服務端和客戶端採用相同的祕鑰加密和解密,只要這個祕鑰不公開,並且祕鑰足夠安全,那麼鏈路就是安全的。但是在網路中都使用相同的對稱加密祕鑰,無異於公開傳輸,如果祕鑰被劫持,那麼就可以篡改鏈路的所有資料。

然後我們肯定會想到HTTPS,它是怎麼實現安全的?我們先來了解下HTTPS的實現方式。

在具體的資料傳輸過程中,HTTPS採用的是對稱加解密的方式,但是它在連線建立時增加了握手協商的過程。

什麼是公鑰:

公鑰是非對稱加密中的概念。非對稱加密演算法方式基於一個祕鑰對,資料通過一個祕鑰加密,只有通過另外一個祕鑰才能解密。服務端儲存私鑰,公鑰發給客戶端。

我們假設一個場景,我們生成祕鑰對,客戶端通過公鑰加密資料,服務端通過私鑰解密。那麼即使使用者劫持到公鑰,他無法劫持篡改使用者的資料。然而從服務端到客戶端的鏈路還是不安全的。

HTTPS藉助了非對稱加密的這個特性,確保對稱機密祕鑰的傳輸是安全的,最後採用對稱加密傳輸資料。

證書的意義:

然而,這又產生了一個新的問題,公鑰被劫持了怎麼辦?

HTTPS當然不會這麼簡單就被劫持,為了解決上訴問題,它引入了數字證書和第三方機構。證書是由第三方認證機構通過公鑰簽發的,其中不僅包含公鑰,還包含簽名( 由簽發節點的私鑰加密產生)、有限期、簽發機構、網址、失效日期等。

HTTPS返回的不在是私鑰,而是證書。當客戶端接收到證書,會對證書做一個校驗。在各個機器中都會維護一個權威的第三方機構列表(包括它們的公鑰),當客戶端需要公鑰時,可根據頒發機構資訊本地查詢到公鑰。客戶端通過頒發機構的公鑰驗證簽名的有效性和證書的完整性,保證公鑰未被篡改。

HTTPS通過私鑰、證書、和CA(簽發機構)確保了鏈路的安全性。在P2P場景下,BT Client之間是對等的,他們相互傳輸資料,更應該是服務端校驗客戶端,而不是HTTPS的客戶端校驗服務端。並且由於BT Client是部署在使用者的節點,還需要考慮證書和私鑰都被劫持的風險。

 

我們是怎麼做的

  1. Client之間

BT Client間傳輸資料肯定是需要加密的,防止鏈路的資料被劫持。但是隻增加HTTPS,雖然鏈路被加密,但是客戶端可能會被假冒,只要假冒者不校驗服務端的證書,直接和服務端握手,就能從其他BT Client獲取到他想要的資料。

我們借鑑和HTTPS的實現,採用了雙向驗證的模式。

需要有證書,首先需要一個統一的CA(簽發機構),因此我們在Tracker中儲存證書和私鑰做為簽發機構,Proxy獲取種子的同時返回CA,使用者校驗客戶端的證書。

然後,只使用一個證書對並且放在Bt Client是危險的,很有可能性被入侵截獲到證書,因此我們獲取證書的方式改為從Tracker獲取,獲取種子的同時獲取Tracker生成的臨時證書私鑰對,把它加入BT Client的下載佇列。在BT Client開始相互連線時,首先相互確認對方的證書的有效性(簽名、簽發機構等資訊),校驗通過後才能請求並相互下載資料。

這種方式下,Client之間的鏈路是安全的。

  1. 鏈路經過證書加密,直接截獲鏈路是不可行的
  2. 即使仿照BT Client的方式,由於Client每個連線都需要進行雙向的證書校驗,想通過這個方式截獲資料就必須請求Tracker去獲取,而訪問Tracker首先是HTTPS的,然後我們還做了業務層的安全校驗(下文業務層安全會提及),也是不可行的。

 

·Docker Daemon 到 Proxy

我們在Proxy中需要劫持Docker的請求,因為Docker在不配置時訪問Registry採用的是HTTPS,因此Proxy劫持Docker請求就必須和Docker保持HTTPS連線。

我們讓客戶端代理只監聽localhost埠,杜絕外部使用該代理的可能性。同時,客戶端代理繫結一套臨時生成的簽發給registry域名的自簽名證書和CA證書,用於劫持Docker Daemon的請求,並將CA證書新增到機器的信任證書當中。

代理繫結的證書只儲存在記憶體中,即使通過特定方式獲取到當前節點的CA證書和服務端證書,也無法擷取其他節點資料。

·從使用者節點到Registry、Tracker

首先,為了確保鏈路的安全,Regstry、Tracker都繫結從權威第三方機構購買的HTTPS證書私鑰對。Proxy和BT Client在訪問它們的時候都會去校驗證書的有效性,只要在證書有效的情況下才傳送請求,這從根源上杜絕了Regstry、Tracker被假冒的可能。

 

  1. 3.2業務加密

在確保鏈路安全後,我們還做了一層業務安全加固。首先我們先了解下JWT Token。

Json web token(JWT)是為了網路應用環境間傳遞宣告而執行的一種基於JSON的開發標準(RFC 7519),該token被設計為緊湊且安全的,特別適用於分散式站點的單點登陸(SSO)場景。JWT的宣告一般被用來在身份提供者和服務提供者間傳遞被認證的使用者身份資訊,以便於從資源伺服器獲取資源,也可以增加一些額外的其它業務邏輯所必須的宣告資訊,該token也可直接被用於認證,也可被加密。

在我們使用Docker命令下載映象時,Docker首先會到Registy獲取Token,在之後的獲取映象層的過程中,多會帶上該Token用於鑑權。其中Token時組要包含以下資訊:

  1. 使用者資訊
  2. 資源資訊,為操作的映象和namespace的名稱
  3. 許可權資訊:是否有PULL/PUSH許可權
  4. 用於解析Token簽名的證書

利用JWT Token中自帶解析Token證書這個特性,我們在BT Client間通訊又增加了Token的校驗。在前文中的證書校驗通過後,客戶端需要傳送Token給服務端用於校驗。為了防止Token被假冒,入侵者採用第三方生成,我們使用服務端截從Docker擷取的Token中的證書解析校驗客戶端的Token,杜絕這種情況。

同時,Proxy 訪問Tracker的介面也會帶上這個Token,Tracker會校驗Token的許可權,完成業務層的安全驗證,防止證書和種子被盜取。

通過以上鏈路層和業務層的安全加固,使用者資料被盜取的可能性已幾乎為零。