1. 程式人生 > >Docker 生產環境之安全性

Docker 生產環境之安全性

原文地址

在審查 Docker 安全性時,需要考慮四個主要方面:

  • 核心固有的安全性及其支援的 namespace 及 cgroup
  • Docker 守護程序本身的攻擊面(attack surface)
  • 容器預設的或使用者自定義的配置中的漏洞
  • 核心的“強化”安全功能以及它們如何與容器互動

1. 核心名稱空間 namespace

Docker 容器跟 LXC 容器類似,並且它們具有相似的安全特性。通過 docker run 命令啟動容器時,Docker 會在背後為這個容器建立一組名稱空間和控制組。

名稱空間提供了第一個也是最直接的隔離形式:在容器中執行的程序看不到並且幾乎不會影響在另一個容器或主機系統中執行的程序。

每個容器具有獨立的網路堆疊,這意味著容器不會獲得對另一個容器的套接字或介面的特權訪問。當然,如果主機系統進行相應設定,容器可以通過各自的網路介面相互互動 - 就像他們可以與外部主機進行互動一樣。當你為容器指定公共埠或使用 link 時,容器之間允許 IP 流量。它們可以互相 ping 通,傳送/接收 UDP 資料包,並建立 TCP 連線,當然如果需要的話可以限制它們之間的連線。從網路體系結構的角度來看,給定 Docker 主機上的所有容器都位於網橋介面上。這意味著它們就像通過普通乙太網交換機連線的物理機器一樣,完全類似。

用於核心名稱空間和私有網路的程式碼有多成熟呢?核心名稱空間在 核心的 2.6.15 和 2.6.26 版本之間引入

。這意味著自從 2008 年 7 月(2.6.26 版本釋出時間)開始,名稱空間程式碼已經在大量的生產系統上被執行和審查。還有更多:名稱空間程式碼的設計和靈感甚至更老。名稱空間實際上是為了重新實現 OpenVZ 的功能,以便它們可以在主流核心中合併。OpenVZ 最初於2005年釋出,因此設計和實現都相當成熟。

2. 控制組 control groups

控制組是 Linux 容器的另一個關鍵元件。它們實現了資源認定和限制(They implement resource accounting and limiting)。控制組提供許多有用指標,但是它們還有助於確保每個容器公平的獲得記憶體,CPU,磁碟 I/O;更重要的是,單個容器是無法耗盡這些資源中的某一種,從而避免了系統性能下降。

因此,儘管它們不能阻止一個容器訪問或影響另一個容器的資料和程序,但它們對抵禦一些拒絕服務攻擊至關重要。它們對於多租戶平臺尤其重要,例如公共和私有 PaaS,即使在某些應用程式開始出現故障時也能保證一致的正常執行時間(和效能)(to guarantee a consistent uptime (and performance) even when some applications start to misbehave.)。

控制組也有一段時間了:程式碼是在2006年開始的,最初被合併到核心 2.6.24 中。

3. Docker 守護程序攻擊面

使用 Docker 執行容器(和應用程式)意味著執行 Docker 守護程序。這個守護程序當前需要 root 許可權,因此你應該知道一些重要的細節。

首先,只允許可信使用者控制你的 Docker 守護程序。這是因為一些強大的 Docker 功能的可能帶來嚴重後果。具體來說,Docker 允許你在 Docker 主機和訪客容器之間共享一個目錄;它允許你在不限制容器訪問許可權的情況下這樣做。這意味著可以啟動一個容器,其中 /host 目錄是主機上的 / 目錄;容器可以不受任何限制地改變你的主機檔案系統。這與虛擬化系統如何允許檔案系統資源共享類似。沒有什麼能夠阻止你與虛擬機器共享你的根檔案系統(甚至你的根塊裝置)。

這具有很強的安全意義:例如,如果你通過 Web 伺服器指示 Docker 通過 API 調配容器,則應該比平時更加仔細地進行引數檢查,以確保惡意使用者無法傳遞偽造的引數,從而導致 Docker 建立任意容器。

考慮到這個問題,REST API 終端(被 Docker CLI 用來跟 Docker 守護程序通訊)從 Docker 0.5.2 起發生變化,使用 UNIX 套接字替代繫結到 127.0.0.1 的 TCP 套接字(如果你直接在 VM 之外的本地主機上執行 Docker,後者可能會有跨站請求偽造攻擊)。然後你就可以使用傳統的 UNIX 許可權檢查來限制對控制套接字的訪問。

只有願意,還可以通過 HTTP 公開 REST API。但是,如果這樣做,請注意上述安全隱患。確保它只能從受信任的網路或 VPN 訪問,或者使用 stunnel 和客戶端 SSL 證書等機制進行保護。還可以使用 HTTPS 和證書 來保護 API 端點。

守護程序也可能容易受到其他輸入的影響,例如通過 docker load 從磁碟載入映象或通過 docker pull 從網路載入映象。從 Docker 1.3.2 開始,映象現在在 Linux/Unix 平臺的 chrooted 子程序中提取,這是實現特權分離的工作的第一步。從 Docker 1.10.0 開始,所有映象都通過其內容的加密校驗和(cryptographic checksum)進行儲存和訪問,從而限制了攻擊者與現有映象發生衝突的可能性。

最後,如果你在伺服器上執行 Docker,建議在伺服器上專門執行 Docker,並將所有的其他服務移動到由 Docker 控制的容器內。當然,保留管理工具(至少是 SSH)以及現有的監控/監督流程(如 NRPE 和 collectd)是沒問題的。

4. Linux 核心的 capabilities

預設情況下,Docker 使用一組受限制的 capabilities 啟動容器。那是什麼意思?

capabilities 將“root/non-root”二分法轉變為一個細粒度的訪問控制系統。只需要在低於 1024 的埠上繫結的程序(如 Web 伺服器)不需要以 root 身份執行:它們可以被賦予 net_bind_service capabilities。對於幾乎所有需要 root 許可權的特定領域,還有許多其他 capabilities(there are many other capabilities, for almost all the specific areas where root privileges are usually needed.)

這對於容器安全意義重大。讓我們看看為什麼!

通常伺服器會以 root 身份執行幾個程序,包括 SSH 守護程序,cron 守護程序,logging 守護程序,核心模組,網路配置工具等等。容器是不同的,因為幾乎所有這些任務都是由容器周圍的基礎設施處理的:

  • SSH 訪問通常由執行在 Docker 主機上的一個單獨的服務管理
  • cron,如果需要的話,應該以使用者程序執行,專門針對需要其排程服務的應用程式定製,而不是作為平臺範圍的設施
  • 日誌管理通常交給 Docker 或第三方服務,例如 Loggly 或 Splunk
  • 硬體管理是無關緊要的,這意味著你永遠不需要在容器中執行 udevd 或等價的守護程序
  • 網路管理髮生在容器之外,儘可能地強化關注點分離,這意味著容器應該永遠不需要執行 ifconfigrouteip 命令(除非容器專門設計為像路由器或防火牆一樣工作)。

這意味著大多數情況下,容器並不需要真正的 root 許可權。因此,容器可以通過一組受限制的 capabilities 來執行,此時容器中的 root 比真正的 root 許可權少得多。例如,下面的幾個是可能的情況:

  • 禁止所有的掛載 mount 操作
  • 禁止訪問原始套接字(以防止資料包欺騙)
  • 禁止某些檔案系統相關操作,例如建立新的裝置節點,改變檔案所有者或改變屬性(包括只讀標誌)
  • 禁止載入模組
  • 其他

這意味著,即使入侵者設法在容器內獲取了 root 許可權,要難以做到嚴重破壞或獲得主機 root 許可權。

這不會影響常規的 Web 應用程式,但會大大減少惡意使用者的攻擊媒介。預設情況下,Docker 會刪除除了 必須的 capabilities 外的所有 capabilities,即白名單而不是黑名單方法。可以在 Linux 手冊頁 中看到完整的可用 capabilities 列表。

執行 Docker 容器的一個主要風險是給容器預設的一組 capabilities 和掛載可能會提供不完全的隔離或獨立性,或者與核心漏洞結合使用(when used in combination with kernel vulnerabilities)。

Docker 支援新增和刪除 capabilities,允許使用非預設配置檔案。刪除 capabilities 可能會使 Docker 更安全,增加 capabilities 會降低 Docker 的安全性。對於使用者來說,最好的做法是刪除所有不需要的 capabilities。

5. 其他的核心安全特性

capabilities 只是現代 Linux 核心提供的眾多安全功能之一。還可以在 Docker 中使用現有的知名系統,如 TOMOYO,AppArmor,SELinux,GRSEC 等。

雖然現在 Docker 僅支援 capabilities,但不會干擾其他系統。這意味著有很多不同的方法來加固 Docker 主機。這裡有一些例子。

  • 可以使用 GRSEC 和 PAX 執行核心。這在編譯時和執行時都增加了許多安全檢查;它也通過地址隨機化等技術擊敗了許多漏洞。它不需要特定於 Docker 的配置,因為這些安全特性適用於系統範圍,獨立於容器。
  • 如果你的發行版帶有用於 Docker 容器的安全模型模板,可以直接使用。例如,我們釋出了一個可與 AppArmor 配合使用的模板,而 Red Hat 提供了適用於 Docker 的 SELinux 策略。這些模板提供了一個額外的安全網路(儘管它與 capabilities 重疊)。
  • 可以使用你喜歡的訪問控制機制來定義自己的策略。

就像你可以使用第三方工具來擴充 Docker 容器(包括特殊網路拓撲或共享檔案系統)一樣,存在用於強化 Docker 容器而無需修改 Docker 本身的工具。

對於 Docker 1.10 的使用者,Docker 守護程序直接支援名稱空間。這個特性允許容器中的 root 使用者對映到容器外部的非 uid-0 使用者,這有助於減輕容器突破的風險。該工具可用,但預設情況下不啟用。

有關此功能的更多資訊,請參閱命令列參考中的 守護程式命令。有關 Docker 中使用者名稱空間實現的其他資訊可以在 此部落格文章 中找到。

6. 結論

Docker 容器預設情況下十分安全,尤其是你在容器中通過非特權使用者執行程序時。

可以通過開啟 AppArmor、SELinux、GRSEC 或其他強化系統來新增額外的安全層。