Docker 引擎安全性

檢閱 Docker 安全性時,需要考慮四個主要方面

  • 核心的內在安全性及其對命名空間和 cgroup 的支援
  • Docker 精靈本身的攻擊面
  • 容器設定檔中的漏洞,無論是預設情況下還是使用者自訂時
  • 核心的「強化」安全功能,以及它們如何與容器互動

核心命名空間

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

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

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

提供核心命名空間和私人網路的程式碼有多成熟?核心命名空間是在核心版本 2.6.15 和 2.6.26 之間引入的OpenVZ控制群組

控制群組是 Linux 容器的另一個關鍵元件。它們實作資源計帳和限制。它們提供許多有用的指標,但它們也有助於確保每個容器都能獲得其公平份額的記憶體、CPU、磁碟 I/O;更重要的是,單個容器無法透過耗盡其中一個資源來導致系統崩潰。

因此,雖然它們在防止一個容器存取或影響另一個容器的資料和處理程序方面沒有發揮作用,但它們對於抵禦某些阻斷服務攻擊至關重要。它們在多租戶平台(例如公用和私人 PaaS)上尤其重要,即使某些應用程式開始出現問題,也能確保一致的正常執行時間(和效能)。

控制群組也已經存在一段時間了:程式碼始於 2006 年,最初合併於核心 2.6.24 中。

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 套接字(如果您碰巧在本地機器上直接運行 Docker,而不是在虛擬機中,則後者容易受到跨站點請求偽造攻擊)。然後,您可以使用傳統的 Unix 權限檢查來限制對控制套接字的訪問。

如果您明確決定這樣做,您也可以透過 HTTP 公開 REST API。但是,如果您這樣做,請注意上述安全隱患。請注意,即使您有防火牆來限制網路中其他主機對 REST API 端點的訪問,該端點仍然可以從容器訪問,並且很容易導致權限提升。因此,*必須*使用 HTTPS 和證書 來保護 API 端點。不允許透過 HTTP(不使用 TLS)公開守护进程 API,這樣的配置會導致守护进程在啟動早期失敗,請參閱 未經身份驗證的 TCP 連線。還建議確保它只能從受信任的網路或 VPN 訪問。

如果您更喜歡 SSH over TLS,您也可以使用 `DOCKER_HOST=ssh://USER@HOST` 或 `ssh -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 核心功能

默認情況下,Docker 使用一組受限的功能來啟動容器。這是什麼意思?

功能將二進制「root/non-root」二分法轉變為細粒度的訪問控制系統。只需要綁定到 1024 以下端口的進程(如 Web 服務器)不需要以 root 身份運行:它們可以被授予 `net_bind_service` 功能。還有許多其他功能,幾乎涵蓋了通常需要 root 權限的所有特定領域。這對容器安全來說意義重大。

典型的服務器以 `root` 身份運行多個進程,包括 SSH 守护进程、`cron` 守护进程、日誌記錄守护进程、內核模塊、網路配置工具等等。容器則不同,因為幾乎所有這些任務都由容器周圍的基礎架構處理。

  • SSH 訪問通常由在 Docker 主機上運行的單個服務器管理。
  • `cron`(如果需要)應該以用戶進程的形式運行,專用於且專為需要其調度服務的應用程序量身定制,而不是作為平台範圍的設施。
  • 日誌管理通常也交給 Docker 或第三方服務(如 Loggly 或 Splunk)處理。
  • 硬件管理無關緊要,這意味著您永遠不需要在容器中運行 `udevd` 或等效的守护进程。
  • 網路管理發生在容器外部,盡可能地執行關注點分離,這意味著容器永遠不需要執行 `ifconfig`、`route` 或 ip 命令(當然,除非容器專門設計為像路由器或防火牆一樣運行)。

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

  • 拒絕所有「掛載」操作。
  • 拒絕訪問原始套接字(以防止數據包欺騙)。
  • 拒絕訪問某些文件系統操作,例如創建新的設備節點、更改文件的所有者或更改屬性(包括不可變標誌)。
  • 拒絕模塊加載。

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

這不會影響常規 Web 應用程序,但會大大減少惡意用戶的攻擊途徑。默認情況下,Docker 會刪除除 所需功能 之外的所有功能,採用允許清單而不是拒絕清單方法。您可以在 Linux 線上手冊Docker Content Trust 簽章驗證

可以將 Docker Engine 配置為僅運行已簽名的映像。Docker Content Trust 簽名驗證功能直接內建到 `dockerd` 二進制文件中。
這在 Dockerd 配置文件中配置。

要啟用此功能,可以在 `daemon.json` 中配置信任鎖定 (trustpinning), whereby 只有使用用戶指定的根密鑰簽名的存储库才能被拉取和運行。

與之前使用 CLI 執行映像簽名驗證相比,此功能為管理員提供了更多洞察力。

有關配置 Docker Content Trust 簽名驗證的更多信息,請訪問 Docker 中的內容信任

其他核心安全功能

功能只是現代 Linux 內核提供的眾多安全功能之一。也可以將現有的、眾所周知的系統(如 TOMOYO、AppArmor、SELinux、GRSEC 等)與 Docker 一起使用。

雖然 Docker 目前僅啟用功能,但它不會干擾其他系統。這意味著有許多不同的方法可以強化 Docker 主機。以下是一些示例。

  • 您可以使用 GRSEC 和 PAX 運行內核。這在編譯時和運行時都添加了許多安全檢查;由於地址隨機化等技術,它還可以抵禦許多漏洞利用。它不需要特定於 Docker 的配置,因為這些安全功能適用於整個系統,與容器無關。
  • 如果您的發行版附帶了 Docker 容器的安全模型模板,您可以直接使用它們。例如,我們提供了一個適用於 AppArmor 的模板,而 Red Hat 附帶了適用於 Docker 的 SELinux 策略。這些模板提供了一個額外的安全網(即使它與功能有很大的重疊)。
  • 您可以使用您喜歡的訪問控制機制定義自己的策略。

正如您可以使用第三方工具來增強 Docker 容器(包括特殊網路拓撲或共享文件系統)一樣,也存在一些工具可以在無需修改 Docker 本身的情況下強化 Docker 容器。

從 Docker 1.10 開始,docker 守护进程直接支持用戶命名空間。此功能允許將容器中的 root 用戶映射到容器外部的非 uid-0 用戶,這有助於減輕容器突破的風險。此功能可用,但默認情況下未啟用。

參考命令列參考文件中daemon 命令,以取得關於此功能的更多資訊。關於 Docker 中使用者命名空間實作的更多資訊,請參閱這篇部落格文章

結論

Docker 容器預設情況下相當安全;尤其是在容器內以非特權使用者身分執行程序時。

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

如果您有讓 Docker 更安全的方法,歡迎在 Docker 社群論壇上提出功能請求、提交程式碼或發表評論。