這篇文章主要講解了“Docker的安全性支持舉例分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Docker的安全性支持舉例分析”吧!
Docker作為最重視安全的容器技術之一,在很多方面都提供了強安全性的默認配置,其中包括:容器root用戶的 Capability 能力限制、Seccomp系統調用過濾、Apparmor的 MAC 訪問控制、ulimit限制、pid-limits的支持,鏡像簽名機制等。
Docker利用Namespace實現了6項隔離,看似完整,實際上依舊沒有完全隔離Linux資源,比如/proc 、/sys 、/dev/sd*等目錄未完全隔離,SELinux、time、syslog等所有現有Namespace之外的信息都未隔離。 其實Docker在安全性上也做了很多工作,大致包括下面幾個方面:
1、Linux內核 Capability 能力限制
Docker支持為容器設置Capabilities,指定開放給容器的權限。這樣在容器中的root用戶比實際的root少很多權限。Docker 在0.6版本以后支持將容器開啟超級權限,使容器具有宿主機的root權限。
2、鏡像簽名機制
Docker 1.8版本以后提供了鏡像簽名機制來驗證鏡像的來源和完整性,這個功能需要手動開啟,這樣鏡像制作者可以在push鏡像前對鏡像進行簽名,在鏡像pull的時候,Docker不會pull驗證失敗或者沒有簽名的鏡像標簽。
3、Apparmor的MAC訪問控制
Apparmor可以將進程的權限與進程capabilities能力聯系在一起,實現對進程的強制性訪問控制(MAC)。在Docker中,我們可以使用Apparmor來限制用戶只能執行某些特定命令、限制容器網絡、文件讀寫權限等功能。
4、Seccomp系統調用過濾
使用Seccomp可以限制進程能夠調用的系統調用(system call)的范圍,Docker提供的默認 Seccomp 配置文件已經禁用了大約 44 個超過 300+ 的系統調用,滿足大多數容器的系統調用訴求。
5、User Namespace隔離
Namespace為運行中進程提供了隔離,限制他們對系統資源的訪問,而進程沒有意識到這些限制,為防止容器內的特權升級攻擊的最佳方法是將容器的應用程序配置為作為非特權用戶運行,對于其進程必須作為容器中的 root 用戶運行的容器,可以將此用戶重新映射到 Docker 主機上權限較低的用戶。映射的用戶被分配了一系列 UID,這些 UID 在命名空間內作為從 0 到 65536 的普通 UID 運行,但在主機上沒有特權。
6、SELinux
SELinux主要提供了強制訪問控制(MAC),即不再是僅依據進程的所有者與文件資源的rwx權限來決定有無訪問能力。能在攻擊者實施了容器突破攻擊后增加一層壁壘。Docker提供了對SELinux的支持。
7、pid-limits的支持
在說pid-limits前,需要說一下什么是fork炸彈(fork bomb),fork炸彈就是以極快的速度創建大量進程,并以此消耗系統分配予進程的可用空間使進程表飽和,從而使系統無法運行新程序。說起進程數限制,大家可能都知道ulimit的nproc這個配置,nproc是存在坑的,與其他ulimit選項不同的是,nproc是一個以用戶為管理單位的設置選項,即他調節的是屬于一個用戶UID的最大進程數之和。這部分內容下一篇會介紹。Docker從1.10以后,支持為容器指定--pids-limit 限制容器內進程數,使用其可以限制容器內進程數。
8、其他內核安全特性工具支持
在容器生態的周圍,還有很多工具可以為容器安全性提供支持,比如可以使用 Docker bench audit tool(工具地址:https://github.com/docker/docker-bench-security)檢查你的Docker運行環境,使用Sysdig Falco(工具地址:https://sysdig.com/opensource/falco/)來檢測容器內是否有異?;顒?,可以使用GRSEC 和 PAX來加固系統內核等等。
這次分享我們帶大家了解一下Docker對前四項是如何安全支持的,下一篇文章會帶大家了解剩余內容。
1Linux內核Capability能力限制
Capabilities簡單來說,就是指開放給進程的權限,比如允許進程可以訪問網絡、讀取文件等。Docker容器本質上就是一個進程,默認情況下,Docker 會刪除 必須的 capabilities 外的所有 capabilities,可以在 Linux 手冊頁 中看到完整的可用 capabilities 列表。Docker 0.6版本以后支持在啟動參數中增加 --privileged 選項為容器開啟超級權限。
Docker支持Capabilities對于容器安全意義重大,因為在容器中我們經常會以root用戶來運行,使用Capability限制后,容器中的 root 比真正的 root用戶權限少得多。這就意味著,即使入侵者設法在容器內獲取了 root 權限,也難以做到嚴重破壞或獲得主機 root 權限。
當我們在docker run時指定了--privileded 選項,docker其實會完成兩件事情:
獲取系統root用戶所有能力賦值給容器;
掃描宿主機所有設備文件掛載到容器內。
下面我們給大家實際演示一下:
當執行docker run 時未指定--privileded 選項
lynzabo@ubuntu:~$ docker run --rm --name def-cap-con1 -d alpine /bin/sh -c "while true;do echo hello; sleep 1;done"
f216f9261bb9c3c1f226c341788b97c786fa26657e18d7e52bee3c7f2eef755c
lynzabo@ubuntu:~$ docker inspect def-cap-con1 -f '{{.State.Pid}}'
43482
lynzabo@ubuntu:~$ cat /proc/43482/status | grep Cap
CapInh: 00000000a80425fb
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
CapBnd: 00000000a80425fb
CapAmb: 0000000000000000
lynzabo@ubuntu:~$
lynzabo@ubuntu:~$ docker exec def-cap-con1 ls /dev
core fd full mqueue null ptmx pts random shm stderr stdin stdout tty urandom zero ...總共15條
lynzabo@ubuntu:~$
△左右滑動看全部△
如果指定了--privileded 選項
lynzabo@ubuntu:~$ docker run --privileged --rm --name pri-cap-con1 -d alpine /bin/sh -c "while true;do echo hello; sleep 1;done"
ad6bcff477fd455e73b725afe914b82c8aa6040f36326106a9a3539ad0be03d2
lynzabo@ubuntu:~$ docker inspect pri-cap-con1 -f '{{.State.Pid}}'
44312
lynzabo@ubuntu:~$ cat /proc/44312/status | grep Cap
CapInh: 0000003fffffffff
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
lynzabo@ubuntu:~$ docker exec pri-cap-con1 ls /dev
agpgart autofs bsg btrfs-control bus core cpu_dma_latency cuse dmmidi dri ecryptfs
...總共186條
lynzabo@ubuntu:~$
△左右滑動看全部△
對比/proc/$pid/status ,可以看到兩個容器進程之間能力位圖的差別,加上--privileged 的能力位圖與超級用戶的能力位圖一樣。再對比增加--privileged后目錄/dev 下文件變化,可以看到,加了特權后,宿主機所有設備文件都掛載在容器內。
我們可以看到,使用--privileged 參數授權給容器的權限太多,所以需要謹慎使用。如果需要掛載某個特定的設備,可以通過--device方式,只掛載需要使用的設備到容器中,而不是把宿主機的全部設備掛載到容器上。例如,為容器內掛載宿主機聲卡:
$ docker run --device=/dev/snd:/dev/snd …
此外,可以通過--add-cap 和 --drop-cap 這兩個參數來對容器的能力進行調整,以最大限度地保證容器使用的安全。
例如,給容器增加一個修改系統時間的命令:
$ docker run --cap-drop ALL --cap-add SYS_TIME ntpd /bin/sh
查看容器PID,執行getpcaps PID查看進程的能力,執行結果如下:
[root@VM_0_6_centos ~]# getpcaps 652
Capabilities for `652': = cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_sys_time,...
[root@VM_0_6_centos ~]#
△左右滑動看全部△
可以看到容器中已經增加了sys_time 能力,可以修改系統時間了。
2Docker鏡像簽名機制
當我們執行docker pull 鏡像的時候,鏡像倉庫再驗證完用戶身份后,會先返回一個manifest.json文件,其中包含了鏡像名稱、tag、所有layer層SHA256值,還有鏡像的簽名信息,然后docker daemon會并行的下載這些layer層文件。Docker 1.8以后,提供了一個數字簽名機制——content trust來驗證官方倉庫鏡像的來源和完整性,簡單來說就是鏡像制作者制作鏡像時可以選擇對鏡像標簽(tag)進行簽名或者不簽名,當pull鏡像時,就可以通過這個簽名進行校驗,如果一致則認為數據源可靠,并下載鏡像。
默認情況下,這個content trust是被關閉了的,你需要設置一個環境變量來開啟這個機制,即:
$ export DOCKER_CONTENT_TRUST=11
當content trust機制被開啟后,docker不會pull驗證失敗或者沒有簽名的鏡像標簽。當然也可以通過在pull時加上--disable-content-trust來暫時取消這個限制。
3Apparmor的MAC訪問控制
AppArmor和SELinux都是Linux安全模塊,可以將進程的權限與進程capabilities能力聯系在了一起,實現對進程的強制性訪問控制(MAC)。由于SELinux有點復雜,經常都被人直接關閉,而AppArmor就相對要簡單點。Docker官方也推薦這種方式。
Docker 自動為容器生成并加載名為 docker-default 的默認配置文件。在 Docker 1.13.0和更高版本中,Docker 二進制文件在 tmpfs 中生成該配置文件,然后將其加載到內核中。在早于 1.13.0 的 Docker 版本上,此配置文件將在 /etc/apparmor.d/docker 中生成。docker-default 配置文件是運行容器的默認配置文件。它具有適度的保護性,同時提供廣泛的應用兼容性。
注意:這個配置文件用于容器而不是 Docker 守護進程。運行容器時會使用 docker-default 策略,除非通過 security-opt 選項覆蓋。
下面我們使用Nginx做演示,提供一個自定義AppArmor 配置文件:
1、創建自定義配置文件,假設文件路徑為 /etc/apparmor.d/containers/docker-nginx 。
#include <tunables/global>
profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
...
deny network raw,
...
deny /bin/** wl,
deny /root/** wl,
deny /bin/sh mrwklx,
deny /bin/dash mrwklx,
deny /usr/bin/top mrwklx,
...
}
△左右滑動看全部△
2、加載配置文件
$ sudo apparmor_parser -r -W /etc/apparmor.d/containers/docker-nginx
3、使用這個配置文件運行容器
$ docker run --security-opt "apparmor=docker-nginx" -p 80:80 -d --name apparmor-nginx nginx12
4、進入運行中的容器中,嘗試一些操作來測試配置是否生效:
$ docker container exec -it apparmor-nginx bash2
root@6da5a2a930b9:~# ping 8.8.8.8
ping: Lacking privilege for raw socket.
root@6da5a2a930b9:/# top
bash: /usr/bin/top: Permission denied
root@6da5a2a930b9:~# touch ~/thing
touch: cannot touch 'thing': Permission denied
root@6da5a2a930b9:/# sh
bash: /bin/sh: Permission denied
可以看到,我們通過 apparmor 配置文件可以對容器進行保護。
4Seccomp系統調用過濾
Seccomp是Linux kernel 從2.6.23版本開始所支持的一種安全機制,可用于限制進程能夠調用的系統調用(system call)的范圍。在Linux系統里,大量的系統調用(systemcall)直接暴露給用戶態程序,但是,并不是所有的系統調用都被需要,而且不安全的代碼濫用系統調用會對系統造成安全威脅。通過Seccomp,我們限制程序使用某些系統調用,這樣可以減少系統的暴露面,同時使程序進入一種“安全”的狀態。每個進程進行系統調用(system call)時,kernel 都會檢查對應的白名單以確認該進程是否有權限使用這個系統調用。從Docker1.10版本開始,Docker安全特性中增加了對Seccomp的支持。
使用Seccomp的前提是Docker構建時已包含了Seccomp,并且內核中的CONFIG_SECCOMP已開啟??墒褂萌缦路椒z查內核是否支持Seccomp:
$ cat /boot/config-`uname -r` | grep CONFIG_SECCOMP=
CONFIG_SECCOMP=y
默認的 seccomp 配置文件為使用 seccomp 運行容器提供了一個合理的設置,并禁用了大約 44 個超過 300+ 的系統調用。它具有適度的保護性,同時提供廣泛的應用兼容性。默認的 Docker 配置文件可以在moby源碼profiles/seccomp/下找到。
默認seccomp profile片段如下:
{
"defaultAction": "SCMP_ACT_ERRNO",
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
"subArchitectures": [
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
]
},=
...
],
"syscalls": [
{
"names": [
"reboot"
],
"action": "SCMP_ACT_ALLOW",
"args": [],
"comment": "",
"includes": {
"caps": [
"CAP_SYS_BOOT"
]
},
"excludes": {}
},
...
]
}
seccomp profile包含3個部分:默認操作,系統調用所支持的Linux架構和系統調用具體規則(syscalls)。對于每個調用規則,其中name是系統調用的名稱,action是發生系統調用時seccomp的操作,args是系統調用的參數限制條件。比如上面的“SCMP_ACT_ALLOW”action代表這個進程這個系統調用被允許,這個call,允許進程可以重啟系統。
實際上,該配置文件是白名單,默認情況下阻止訪問所有的系統調用,然后將特定的系統調用列入白名單。
seccomp 有助于以最小權限運行 Docker 容器。不建議更改默認的 seccomp 配置文件。
運行容器時,如果沒有通過 --security-opt 選項覆蓋容器,則會使用默認配置。例如,以下顯式指定了一個策略:
$ docker run --rm \
-it \
--security-opt seccomp=/path/to/seccomp/profile.json \
hello-seccomp
感謝各位的閱讀,以上就是“Docker的安全性支持舉例分析”的內容了,經過本文的學習后,相信大家對Docker的安全性支持舉例分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。