十大 Docker 優(yōu)秀實(shí)踐,望君遵守!!
本文是關(guān)于容器安全的文章,展示了 10 種強(qiáng)化 Docker 基礎(chǔ)架構(gòu)并保護(hù)容器和數(shù)據(jù)免受惡意攻擊的方法。
介紹
隨著許多公司在其基礎(chǔ)設(shè)施中采用 Docker,威脅參與者的攻擊面也增加了。這就需要保護(hù) Docker 基礎(chǔ)設(shè)施。在本文中,提到了一些可以加強(qiáng) Docker 容器安全性的要點(diǎn)。
要充分利用本文,必須具備以下條件:
- 熟悉 Linux 命令行
- 關(guān)于容器化和 Docker 的基本概念
什么是 Docker?
Docker 是一個(gè)開(kāi)源容器化平臺(tái)。它允許開(kāi)發(fā)人員將應(yīng)用程序打包到容器中:標(biāo)準(zhǔn)化的可執(zhí)行組件將應(yīng)用程序源代碼與在運(yùn)行該代碼所需的操作系統(tǒng) (OS) 庫(kù)和依賴項(xiàng)相結(jié)合。
十大優(yōu)秀實(shí)踐
Docker 文檔概述了在保護(hù) Docker 容器時(shí)要考慮的四個(gè)主要方面:
- 內(nèi)核對(duì)命名空間和 cgroup 的支持
- Docker 守護(hù)進(jìn)程的攻擊面
- 容器配置錯(cuò)誤
- 使用 AppArmor、SELinux 等 Linux 內(nèi)核安全模塊等
我們將這些分解為可以遵循的 10 大實(shí)踐來(lái)強(qiáng)化 Docker 環(huán)境。
1. 經(jīng)常更新主機(jī)和 Docker 守護(hù)進(jìn)程
容器與主機(jī)系統(tǒng)共享內(nèi)核。在容器上下文中執(zhí)行的任何內(nèi)核漏洞都會(huì)直接影響主機(jī)內(nèi)核。內(nèi)核提權(quán)漏洞 Dirty Cow 在容器中執(zhí)行時(shí)會(huì)導(dǎo)致對(duì)主機(jī)的 root 訪問(wèn)。因此,保持主機(jī)和 Docker 引擎最新很重要。
2. 不要暴露 Docker daemon socket
Docker 客戶端和 Docker 守護(hù)程序之間發(fā)生的所有通信都通過(guò) Docker 守護(hù)程序套接字進(jìn)行,這是一個(gè) UNIX 套接字,通常位于/var/run/docker.sock,這允許訪問(wèn) Docker API。傳統(tǒng)的 UNIX 文件權(quán)限用于限制對(duì)該套接字的訪問(wèn)。在默認(rèn)配置中,該套接字由 root 用戶擁有。如果其他人獲得了對(duì)套接字的訪問(wèn)權(quán),將擁有對(duì)主機(jī)的 root 訪問(wèn)權(quán)。
- 設(shè)置權(quán)限,以便只有 root 用戶和 docker 組可以訪問(wèn) Docker 守護(hù)進(jìn)程套接字
- 使用 SSH 保護(hù) Docker 守護(hù)進(jìn)程套接字
- 使用 TLS (HTTPS) 保護(hù) Docker 守護(hù)程序套接字。這允許通過(guò) HTTP 以安全的方式訪問(wèn) Docker
- 不要讓守護(hù)程序套接字可用于遠(yuǎn)程連接,除非您使用 Docker 的加密 HTTPS 套接字,它支持身份驗(yàn)證
- 不要使用類(lèi)似的選項(xiàng)運(yùn)行 Docker 鏡像-v /var/run/docker.sock:/var/run/docker.sock,這會(huì)在生成的容器中公開(kāi)套接字。請(qǐng)記住,以只讀方式安裝套接字不是解決方案,只會(huì)使其更難被破壞。docker compose 文件中的一個(gè)例子是:
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
要檢查您是否已經(jīng)有一個(gè)在這種配置中運(yùn)行的容器:
docker inspect --format='{{.HostConfig.Binds}}' [container id]
3. 以無(wú) root 模式運(yùn)行 Docker
可以以非 root 用戶身份運(yùn)行 Docker 守護(hù)程序,以防止 Docker 中的潛在漏洞。這稱(chēng)為“無(wú) root 模式”。無(wú) root 模式不需要 root 權(quán)限安裝 Docker 與 Docker API 通信。
在無(wú) root 模式下,Docker 守護(hù)進(jìn)程和容器在用戶命名空間中運(yùn)行,默認(rèn)情況下沒(méi)有 root 權(quán)限。
(1) 在無(wú) root 模式下運(yùn)行 Docker
使用 sudo 權(quán)限安裝uidmap?軟件包:
apt-get install -y uidmap
從 Docker 的網(wǎng)站獲取安裝腳本并運(yùn)行:
curl -fSsL https://get.docker.com/rootless | sh
獲取無(wú) root 安裝腳本:
復(fù)制以開(kāi)頭的最后兩行export?并將它們粘貼到~/.bashrc?文件的末尾。這樣可以確保每次打開(kāi) Bash shell 時(shí),都會(huì)設(shè)置這兩個(gè)變量:PATH? 和DOCKER_HOST。
.bashrc
運(yùn)行source ~/.bashrc以在您當(dāng)前的 shell 會(huì)話中設(shè)置這些變量。
運(yùn)行systemctl --user start docker以啟動(dòng) Docker 引擎。
我們可以通過(guò)運(yùn)行來(lái)檢查 docker 是否正在運(yùn)行docker version:
4. 容器資源配置
控制組或 cgroups 是 Linux 內(nèi)核功能,在實(shí)現(xiàn)容器的資源分配和限制方面起著關(guān)鍵作用。他們的工作不僅是確保每個(gè)容器獲得其公平份額的資源,如內(nèi)存和 CPU,而且還要確保單個(gè)容器不會(huì)因耗盡其中一個(gè)資源而導(dǎo)致系統(tǒng)崩潰。
限制資源可防止拒絕服務(wù)攻擊。以下是一些可用于限制容器資源的 CLI 標(biāo)志:
- --memory=<memory size>— 最大內(nèi)存量
- --restart=on-failure:<number_of_restarts> — 重啟次數(shù)
- --memory-swap <value>— 交換內(nèi)存量
- --cpus=<number>— 容器可用的最大 CPU 資源
- --ulimit nofile=<number>— 文件描述符的最大數(shù)量
- --ulimit nproc=<number>— 最大進(jìn)程數(shù)
默認(rèn)情況下,Docker 允許容器使用主機(jī)內(nèi)核允許的盡可能多的 RAM 和 CPU 資源。因此有必要設(shè)置資源約束以防止容器和主機(jī)中的安全問(wèn)題。
5. 避免使用特權(quán)容器
(1) 避免使用 --privileged 標(biāo)志
Docker 具有允許容器在主機(jī)上以 root 權(quán)限運(yùn)行的功能。這是通過(guò)—-privileged標(biāo)志完成的。以特權(quán)模式運(yùn)行的容器對(duì)主機(jī)上的所有設(shè)備都具有 root 權(quán)限。
如果攻擊者要破壞特權(quán)容器,他們就有可能輕松訪問(wèn)主機(jī)上的資源。篡改系統(tǒng)中的安全模塊(如 SELinux)也很容易。因此,不建議在開(kāi)發(fā)生命周期的任何階段以特權(quán)模式運(yùn)行容器。
特權(quán)容器是主要的安全風(fēng)險(xiǎn)。濫用的可能性是無(wú)窮無(wú)盡的。攻擊者可以識(shí)別主機(jī)上運(yùn)行的服務(wù)來(lái)發(fā)現(xiàn)和利用漏洞。他們還可以利用容器錯(cuò)誤配置,例如具有弱憑據(jù)或沒(méi)有身份驗(yàn)證的容器。特權(quán)容器為攻擊者提供 root 訪問(wèn)權(quán)限,從而導(dǎo)致執(zhí)行惡意代碼。避免在任何環(huán)境中使用它們。
要檢查容器是否在特權(quán)模式下運(yùn)行,請(qǐng)使用以下命令:
docker inspect --format='{{.HostConfig.Privileged}}' [container_id]
- true意味著容器是特權(quán)的
- false表示容器沒(méi)有特權(quán)
(2) 使用 no-new-privileges 選項(xiàng)
在創(chuàng)建容器時(shí)添加??no-new-privileges?
??安全選項(xiàng),以禁止容器進(jìn)程使用??setuid?
??或??setgid?
?二進(jìn)制文件提升其權(quán)限。這可以防止容器內(nèi)的進(jìn)程在執(zhí)行期間獲得新的權(quán)限。因此,如果有一個(gè)設(shè)置了 setuid 或 setgid 位的程序,任何試圖通過(guò)該程序獲得特權(quán)的操作都將被拒絕。
6. 將文件系統(tǒng)和卷設(shè)置為只讀
Docker 中一個(gè)具有安全意識(shí)的有用功能是使用只讀文件系統(tǒng)運(yùn)行容器。這減少了攻擊向量,因?yàn)槿萜鞯奈募到y(tǒng)不能被篡改或?qū)懭?,除非它?duì)其文件系統(tǒng)文件和目錄具有明確的讀寫(xiě)權(quán)限。
以下代碼將 Docker 容器設(shè)置為只讀:
docker run --read-only alpine sh -c 'echo "read only" > /tmp'
7. Drop capabilities
Linux 內(nèi)核能夠?qū)?root 用戶的權(quán)限分解為不同的單元,稱(chēng)為 capabilities。幾乎所有與 Linux root 用戶相關(guān)的特殊權(quán)限都分解為單獨(dú)的 capabilities。
capsh 顯示的特權(quán)容器的capabilities
Docker 施加了某些限制,使得使用功能變得更加簡(jiǎn)單。文件功能存儲(chǔ)在文件的擴(kuò)展屬性中,并且在構(gòu)建 Docker 鏡像時(shí)會(huì)去除擴(kuò)展屬性。這意味著您通常不必過(guò)多關(guān)注容器中的文件功能。
正如我們之前提到的,記住不要運(yùn)行帶有--privileged標(biāo)志的容器,因?yàn)檫@會(huì)將所有 Linux 內(nèi)核功能添加到容器中。
最安全的設(shè)置是使用--cap-drop all 刪除所有功能,然后僅添加所需的功能。例如:
docker run --cap-drop all --cap-add CHOWN alpine
8. 使用 Linux 安全模塊
考慮使用像 seccomp 或 AppArmor 這樣的安全模塊。以下是一些眾所周知的模塊:
- Seccomp:用于允許/禁止在容器中運(yùn)行的系統(tǒng)調(diào)用
- AppArmor:使用程序配置文件來(lái)限制單個(gè)程序的功能
- SELinux:使用安全策略,這是一組規(guī)則,告訴 SELinux 什么可以訪問(wèn)或不能訪問(wèn),以強(qiáng)制執(zhí)行策略允許的訪問(wèn)。
這些安全模塊可用于為進(jìn)程和用戶的訪問(wèn)權(quán)限提供另一個(gè)級(jí)別的安全檢查,超出標(biāo)準(zhǔn)文件級(jí)訪問(wèn)控制所提供的安全檢查。
(1) seccomp
默認(rèn)情況下,容器獲取默認(rèn)的 seccomp 配置文件。
https://github.com/moby/moby/blob/master/profiles/seccomp/default.json
這可以用以下命令覆蓋:
docker run --rm -it --security-opt seccomp=./seccomp/profile.json hello-world
使用 Seccomp 配置文件運(yùn)行容器
使用 Seccomp 配置文件,您可以選擇容器中允許哪些系統(tǒng)調(diào)用以及拒絕哪些系統(tǒng)調(diào)用,因?yàn)樵谏a(chǎn)環(huán)境中并非全部都需要。您可以從 Docker 文檔中了解有關(guān)編寫(xiě) seccomp 配置文件的更多信息。
(2) AppArmor
默認(rèn)情況下,容器使用docker-default? AppArmor 模板??梢允褂?-security-opt自定義配置文件覆蓋默認(rèn)設(shè)置。
為此,您必須首先將新配置文件加載到 AppArmor 中以與容器一起使用:
apparmor_parser -r -W /path/to/custom_profile
現(xiàn)在使用自定義配置文件運(yùn)行容器
docker run --rm -it --security-opt apparmor=custom_profile hello-world
請(qǐng)參閱此 wiki 以了解如何創(chuàng)建 AppArmor 配置文件。
https://gitlab.com/apparmor/apparmor/-/wikis/QuickProfileLanguage