Docker Engine 安全性

檢視 Docker 安全性時,有四個主要考量領域:

  • 核心本身的安全性及其對命名空間 (namespaces) 和控制群組 (cgroups) 的支援
  • Docker 守護程式本身的攻擊面
  • 容器配置檔案中的漏洞,無論是預設的,或是使用者自訂的。
  • 核心的「強化」安全性功能及其與容器的互動方式。

核心命名空間 (Kernel namespaces)

Docker 容器與 LXC 容器非常相似,它們具有類似的安全性功能。當您使用 docker run 啟動容器時,Docker 會在幕後為該容器建立一組命名空間和控制群組。

命名空間提供了第一種也是最直接的隔離形式。在容器中執行的程序無法看到,更不用說影響,在另一個容器或主機系統中執行的程序。

每個容器也有自己的網路堆疊,這表示容器無法取得對另一個容器的插槽或介面的特權存取。當然,如果主機系統設定得當,容器可以透過各自的網路介面相互互動,就像它們可以與外部主機互動一樣。當您為容器指定公開連接埠或使用 連結 時,容器之間允許 IP 流量。它們可以相互 ping,傳送/接收 UDP 封包,並建立 TCP 連線,但如有必要,這可以受到限制。從網路架構的角度來看,特定 Docker 主機上的所有容器都位於橋接介面上。這意味著它們就像透過共同的乙太網路交換器連接的實體機器一樣;不多也不少。

提供核心命名空間和私人網路的程式碼有多成熟?核心命名空間是在 核心版本 2.6.15 和 2.6.26 之間 引入的。這意味著自 2008 年 7 月(2.6.26 版本發佈日期)以來,命名空間程式碼已在大量生產系統上進行過演練和審查。還有更多:命名空間程式碼的設計和靈感甚至更早。命名空間實際上是為了重新實現 OpenVZ 的功能,以便它們可以合併到主流核心中。OpenVZ 最初於 2005 年發佈,因此設計和實作都相當成熟。

控制群組 (Control groups)

控制群組 (Control Groups) 是 Linux 容器的另一個關鍵組件。它們實作了資源會計和限制。它們提供了許多有用的指標,但更重要的是,它們還有助於確保每個容器獲得其公平的記憶體、CPU、磁碟 I/O 份額;並且,單一容器不會因耗盡其中一個資源而導致系統癱瘓。

因此,儘管它們在防止一個容器存取或影響另一個容器的資料和程序方面沒有作用,但它們對於抵禦某些阻斷服務攻擊至關重要。它們在多租戶平台(例如公共和私有 PaaS)上尤其重要,即使某些應用程式開始行為異常,也能保證一致的正常運行時間(和效能)。

控制群組也存在已久:該程式碼始於 2006 年,最初合併於核心 2.6.24 版。

Docker 守護程式攻擊面 (Docker daemon attack surface)

使用 Docker 執行容器(和應用程式)意味著執行 Docker 守護程式。除非您選擇 無根模式 (Rootless mode),否則此守護程式需要 root 權限,因此您應該注意一些重要細節。

首先,只有受信任的使用者才應被允許控制您的 Docker 守護程式。這是 Docker 某些強大功能的直接結果。具體來說,Docker 允許您在 Docker 主機和訪客容器之間共享目錄;並且允許您在不限制容器存取權限的情況下這樣做。這意味著您可以啟動一個容器,其中 /host 目錄是您主機上的 / 目錄;並且該容器可以不受任何限制地更改您的主機檔案系統。這與虛擬化系統允許檔案系統資源共享的方式類似。沒有什麼可以阻止您與虛擬機共享您的根檔案系統(甚至您的根區塊裝置)。

這具有強大的安全性含義:例如,如果您從 Web 伺服器操作 Docker 透過 API 提供容器,則應比平常更加小心參數檢查,以確保惡意使用者無法傳遞精心設計的參數,導致 Docker 建立任意容器。

因此,Docker 0.5.2 中更改了 REST API 端點(Docker CLI 用於與 Docker 守護程式通訊的端點),現在使用 Unix socket 而不是綁定在 127.0.0.1 上的 TCP socket(後者容易受到跨站請求偽造攻擊,如果您碰巧在本地機器上直接執行 Docker,而不是在 VM 內部)。然後,您可以使用傳統的 Unix 權限檢查來限制對控制 socket 的存取。

如果您明確決定這樣做,您也可以透過 HTTP 暴露 REST API。然而,如果您這樣做,請注意上述安全性含義。請注意,即使您有防火牆來限制來自網路中其他主機對 REST API 端點的存取,該端點仍然可以從容器存取,並且很容易導致權限提升。因此,強制使用 HTTPS 和憑證 來保護 API 端點。不允許在沒有 TLS 的情況下透過 HTTP 暴露守護程式 API,此類配置會導致守護程式在啟動時提早失敗,請參閱 未經身份驗證的 TCP 連線。還建議確保它只能從受信任的網路或 VPN 存取。

如果您偏好 SSH 而非 TLS,您也可以使用 DOCKER_HOST=ssh://USER@HOSTssh -L /path/to/docker.sock:/var/run/docker.sock

守護程式也可能受到其他輸入的潛在攻擊,例如使用 docker load 從磁碟載入映像,或使用 docker pull 從網路載入映像。從 Docker 1.3.2 開始,映像現在在 Linux/Unix 平台上的一個 chrooted 子程序中解壓縮,這是朝向權限分離更廣泛努力的第一步。從 Docker 1.10.0 開始,所有映像都透過其內容的加密雜湊總和儲存和存取,限制了攻擊者造成與現有映像衝突的可能性。

最後,如果您在伺服器上執行 Docker,建議僅在該伺服器上執行 Docker,並將所有其他服務移至由 Docker 控制的容器內。當然,保留您最喜歡的管理工具(可能至少是一個 SSH 伺服器)以及現有的監控/監督程序(例如 NRPE 和 collectd)是可以的。

Linux 核心權限 (Linux kernel capabilities)

預設情況下,Docker 會以一組受限的權限 (capabilities) 啟動容器。這是什麼意思?

權限 (Capabilities) 將「root/非 root」的二分法轉變為精細的存取控制系統。僅需綁定在 1024 以下連接埠的程序(如 Web 伺服器)不需要以 root 身分執行:它們只需被授予 net_bind_service 權限即可。還有許多其他權限,幾乎適用於所有通常需要 root 權限的特定領域。這對容器安全性意義重大。

典型的伺服器以 root 身分執行多個程序,包括 SSH 守護程式、cron 守護程式、日誌守護程式、核心模組、網路配置工具等等。容器則不同,因為幾乎所有這些任務都由容器周圍的基礎設施處理:

  • SSH 存取通常由運行在 Docker 主機上的單一伺服器管理
  • cron 在必要時,應作為使用者程序運行,專用於需要其排程服務的應用程式,而非作為平台範圍的設施
  • 日誌管理通常也交由 Docker,或 Loggly、Splunk 等第三方服務處理
  • 硬體管理無關緊要,這意味著您永遠不需要在容器內執行 udevd 或等效的守護程式
  • 網路管理發生在容器外部,盡可能強制關注點分離,這意味著容器永遠不需要執行 ifconfigroute 或 ip 命令(當然,除非容器經過特別設計,以表現為路由器或防火牆)

這意味著在大多數情況下,容器根本不需要「真正的」root 權限*。因此,容器可以以縮減的權限集運行;這表示容器內的「root」比真正的「root」擁有少得多的權限。例如,可以:

  • 拒絕所有「掛載」操作
  • 拒絕存取原始 socket (以防止封包欺騙)
  • 拒絕存取某些檔案系統操作,例如建立新的裝置節點、更改檔案所有者或更改屬性(包括不可變標誌)
  • 拒絕模組載入

這意味著即使入侵者設法在容器內升級到 root 權限,也很難造成嚴重損壞,或升級到主機。

這不影響一般的 Web 應用程式,但顯著減少了惡意使用者的攻擊途徑。預設情況下,Docker 會刪除所有權限 (capabilities),除了 所需的功能,這是一種允許列表而非拒絕列表的方法。您可以在 Linux manpages 中查看所有可用權限的完整列表。

運行 Docker 容器的一個主要風險是,預設授予容器的權限 (capabilities) 和掛載集可能提供不完整的隔離,無論是獨立的,還是與核心漏洞結合使用時。

Docker 支援新增和移除權限 (capabilities),允許使用非預設的配置。這可能透過移除權限使 Docker 更安全,或透過新增權限使其安全性降低。對使用者來說,最佳實踐是移除所有權限,除了其程序明確需要的功能。

Docker 內容信任簽章驗證 (Docker Content Trust signature verification)

Docker Engine 可以配置為僅執行簽署的映像。Docker 內容信任簽章驗證功能直接內建於 dockerd 二進位檔中。
這在 Dockerd 配置檔案中配置。

要啟用此功能,可以在 daemon.json 中配置信任釘選 (trustpinning),這樣只有使用使用者指定的根金鑰簽署的儲存庫才能被拉取和執行。

此功能為管理員提供了比以前透過 CLI 可用的更多洞察力,用於強制執行和執行映像簽章驗證。

有關配置 Docker 內容信任簽章驗證的更多資訊,請前往 Docker 中的內容信任

其他核心安全性功能

權限 (Capabilities) 只是現代 Linux 核心提供的眾多安全性功能之一。也可以將現有且知名的系統(例如 TOMOYO、AppArmor、SELinux、GRSEC 等)與 Docker 結合使用。

雖然 Docker 目前只啟用權限 (capabilities),但它不會干擾其他系統。這意味著有許多不同的方法可以強化 Docker 主機。以下是一些範例。

  • 您可以運行帶有 GRSEC 和 PAX 的核心。這增加了許多安全檢查,包括編譯時和運行時;它還透過位址隨機化等技術擊敗了許多漏洞。它不需要 Docker 特定的配置,因為這些安全性功能適用於整個系統,獨立於容器。
  • 如果您的發行版帶有 Docker 容器的安全模型範本,您可以直接使用它們。例如,我們提供一個與 AppArmor 配合使用的範本,而 Red Hat 則提供適用於 Docker 的 SELinux 策略。這些範本提供了一個額外的安全網(儘管它與權限 (capabilities) 有很大的重疊)。
  • 您可以使用您最喜歡的存取控制機制來定義自己的策略。

就像您可以使用第三方工具來增強 Docker 容器一樣,包括特殊的網路拓撲或共享檔案系統,也有工具可以在不需要修改 Docker 本身的情況下強化 Docker 容器。

從 Docker 1.10 開始,Docker 守護程式直接支援使用者命名空間 (User Namespaces)。此功能允許容器中的 root 使用者映射到容器外部的非 uid-0 使用者,這有助於減輕容器突破的風險。此功能可用但預設未啟用。

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

結論

預設情況下,Docker 容器相當安全;特別是如果您在容器內以非特權使用者身分執行程序。

您可以透過啟用 AppArmor、SELinux、GRSEC 或其他適當的強化系統來增加額外的安全性層。

如果您想到讓 Docker 更安全的方法,我們歡迎在 Docker 社群論壇上提出功能請求、拉取請求或評論。

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.