由於容器運行在主機上,且與主機共用一套內核,因此在容器的安全使用上會涉及到容器本身以及主機的安全加固,如針對系統調用,系統資源,遠程訪問等都需要進行安全方面的考量。
docker官網給出了簡單的一些建議,如使用命名空間進行用戶隔離,使用cgroup限制容器使用的資源上限,使用apparmor限制容器對資源的訪問以及使用seccomp限制容器的系統調用等。但官方文檔描述的場景比較簡單,更多場景可以參考Dosec整理的Docker容器安全最佳實踐白皮書V1.0,也可以微信關注公眾號"Dosec"查看更多容器安全相關的文章。
下面簡單了解下內核安全組件seccomp和apparmor
seccomp:
seccomp主要用於限制容器程序可以使用的系統調用,可以使用如下方式查看當前系統是否支持seccomp
# grep CONFIG_SECCOMP= /boot/config-$(uname -r)
CONFIG_SECCOMP=y
seccomp使用profile 白名單機制來配置容器程序的權限,在運行容器時會使用默認配置,當然也可以使用--security-opt選項來覆蓋默認的配置。seccomp默認情況下會block大約44個系統調用。使用docker info可以看到如下信息,默認會啟動seccomp且使用默認profile
Security Options: seccomp Profile: default
下面為使用自定義profile文件testprofile.json替換默認profile的操作
# docker run -itd --security-opt seccomp=testprofile.json busybox:latest /bin/sh
在docker的go源碼中定義了seccomp支持的平台以及action和operation,源碼總對seccomp的結構體定義如下,包含默認動作,使用的平台集以及系統調用集
// LinuxSeccomp represents syscall restrictions type LinuxSeccomp struct { DefaultAction LinuxSeccompAction `json:"defaultAction"` Architectures []Arch `json:"architectures,omitempty"` Syscalls []LinuxSyscall `json:"syscalls,omitempty"` }
系統調用中包含系統調用的名稱,動作和參數等
// LinuxSyscall is used to match a syscall in Seccomp type LinuxSyscall struct { Names []string `json:"names"` Action LinuxSeccompAction `json:"action"` Args []LinuxSeccompArg `json:"args,omitempty"` }
支持如下平台架構
const ( ArchX86 Arch = "SCMP_ARCH_X86" ArchX86_64 Arch = "SCMP_ARCH_X86_64" ArchX32 Arch = "SCMP_ARCH_X32" ArchARM Arch = "SCMP_ARCH_ARM" ArchAARCH64 Arch = "SCMP_ARCH_AARCH64" ArchMIPS Arch = "SCMP_ARCH_MIPS" ArchMIPS64 Arch = "SCMP_ARCH_MIPS64" ArchMIPS64N32 Arch = "SCMP_ARCH_MIPS64N32" ArchMIPSEL Arch = "SCMP_ARCH_MIPSEL" ArchMIPSEL64 Arch = "SCMP_ARCH_MIPSEL64" ArchMIPSEL64N32 Arch = "SCMP_ARCH_MIPSEL64N32" ArchPPC Arch = "SCMP_ARCH_PPC" ArchPPC64 Arch = "SCMP_ARCH_PPC64" ArchPPC64LE Arch = "SCMP_ARCH_PPC64LE" ArchS390 Arch = "SCMP_ARCH_S390" ArchS390X Arch = "SCMP_ARCH_S390X" ArchPARISC Arch = "SCMP_ARCH_PARISC" ArchPARISC64 Arch = "SCMP_ARCH_PARISC64" )
下面的常量定義可以參見linux系統調用seccomp_rule_add
// Define actions for Seccomp rules const ( ActKill LinuxSeccompAction = "SCMP_ACT_KILL" ActTrap LinuxSeccompAction = "SCMP_ACT_TRAP" ActErrno LinuxSeccompAction = "SCMP_ACT_ERRNO" ActTrace LinuxSeccompAction = "SCMP_ACT_TRACE" ActAllow LinuxSeccompAction = "SCMP_ACT_ALLOW" )
... // Define operators for syscall arguments in Seccomp const ( OpNotEqual LinuxSeccompOperator = "SCMP_CMP_NE" OpLessThan LinuxSeccompOperator = "SCMP_CMP_LT" OpLessEqual LinuxSeccompOperator = "SCMP_CMP_LE" OpEqualTo LinuxSeccompOperator = "SCMP_CMP_EQ" OpGreaterEqual LinuxSeccompOperator = "SCMP_CMP_GE" OpGreaterThan LinuxSeccompOperator = "SCMP_CMP_GT" OpMaskedEqual LinuxSeccompOperator = "SCMP_CMP_MASKED_EQ" )
apparmor:
apparmor使用上與seccomp類似,也是需要一個profile。apparmor也有一個默認的profile,相比seccomp,apparmor可以限制更多的資源,如文件權限,網絡,capabilities等。
ubuntu下多個版本的apparmor手冊可以參見AppArmor
SELinux:
TIPS:
- 在run一個容器的時候,通過--security-opt seccomp:unconfined參數來允許容器執行全部的系統的調用
- centos使用的安全模塊為SELinux,暫不支持apparmor;Debian和Ubuntu支持apparmor