一 理解Docker安全
Docker容器的安全性,很大程度上依賴于Linux系統自身,評估Docker的安全性時,主要考慮以下幾個方面:
Linux內核的命名空間機制提供的容器隔離安全
Linux控制組機制對容器資源的控制能力安全,
Linux內核的能力機制所帶來的操作權限安全
Docker程式(特別是服務端)本身的抗攻擊性,
其他安全增強機制對容器安全性的影響
命名空間隔離的安全:
當docker run啟動一個容器時,Docker將在后臺為容器創建一個獨立的命名空間,命名空間提供了最基礎也最直接的隔離,
與虛擬機方式相比,通過Linux namespace來實作的隔離不是那么徹底,
容器只是運行在宿主機上的一種特殊的行程,那么多個容器之間使用的就還是同一個宿主機的作業系統內核
在 Linux 內核中,有很多資源和物件是不能被 Namespace 化的,比如:時間memory-swap設定swap交換磁區限額,
內核能力機制:
能力機制(Capability)是Linux內核一個強大的特性,可以提供細粒度的權限訪問控制,
大部分情況下,容器并不需要“真正的”root權限,容器只需要少數的能力即可,
默認情況下,Docker采用“白名單”機制,禁用“必需功能”之外的其他權限,
Docker服務端防護:
使用Docker容器的核心是Docker服務端,確保只有可信的用戶才能訪問到Docker服務,
將容器的root用戶映射到本地主機上的非root用戶,減輕容器和主機之間因權限提升而引起的安全問題,
允許Docker 服務端在非root權限下運行,利用安全可靠的子行程來代理執行需要特權權限的操作,這些子行程只允許在特定范圍內進行操作,
其他安全特性:
在內核中啟用GRSEC和PAX,這將增加更多的編譯和運行時的安全檢查;并且通過地址隨機化機制來避免惡意探測等,啟用該特性不需要Docker進行任何配置,
使用一些有增強安全特性的容器模板,
用戶可以自定義更加嚴格的訪問控制機制來定制安全策略,
在檔案系統掛載到容器內部時,可以通過配置只讀模式來避免容器內的應用通過檔案系統破壞外部環境,特別是一些系統運行狀態相關的目錄,
二 容器資源控制
Linux Cgroups 的全稱是 Linux Control Group,
是限制一個行程組能夠使用的資源上限,包括 CPU、記憶體、磁盤、網路帶寬等等,
對行程進行優先級設定、審計,以及將行程掛起和恢復等操作,
[root@server1 ~]# docker run -d --name demo nginx
c77c7b63544c3a357d5f13f2bdc8b68b3678d8a31234ac170b814ab9d60c2124
[root@server1 ~]# docker inspect demo| grep Pid
"Pid": 2842,
"PidMode": "",
"PidsLimit": null,
[root@server1 ~]# cd /proc/2842
[root@server1 2842]# ls
attr cwd map_files oom_adj schedstat task
autogroup environ maps oom_score sessionid timers
auxv exe mem oom_score_adj setgroups uid_map
cgroup fd mountinfo pagemap smaps wchan
clear_refs fdinfo mounts patch_state stack
cmdline gid_map mountstats personality stat
comm io net projid_map statm
coredump_filter limits ns root status
cpuset loginuid numa_maps sched syscall
[root@server1 2842]# cd ns/
[root@server1 ns]# ls
ipc mnt net pid user uts
[root@server1 ns]# free -m
total used free shared buff/cache available
Mem: 1837 188 1125 16 524 1468
Swap: 2047 0 2047
[root@server1 ns]# docker run --help | grep mem
--cpuset-mems string MEMs in which to allow execution
--kernel-memory bytes Kernel memory limit
-m, --memory bytes Memory limit
--memory-reservation bytes Memory soft limit
--memory-swap bytes Swap limit equal to memory plus
--memory-swappiness int Tune container memory swappiness (0
[root@server1 ns]# docker run --help | grep cpu
--cpu-period int Limit CPU CFS (Completely Fair
--cpu-quota int Limit CPU CFS (Completely Fair
--cpu-rt-period int Limit CPU real-time period in
--cpu-rt-runtime int Limit CPU real-time runtime in
-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution
--cpuset-mems string MEMs in which to allow execution
[root@server1 ns]# docker run --help | grep disk
[root@server1 ns]# docker run --help | grep io
Options:
--blkio-weight uint16 Block IO (relative weight), between
--blkio-weight-device list Block IO weight (relative device
--cgroup-parent string Optional parent cgroup for the container
--cpu-period int Limit CPU CFS (Completely Fair
Scheduler) period
--cpu-rt-period int Limit CPU real-time period in
--cpuset-cpus string CPUs in which to allow execution
--cpuset-mems string MEMs in which to allow execution
--device-read-iops list Limit read rate (IO per second) from
--device-write-iops list Limit write rate (IO per second) to
--disable-content-trust Skip image verification (default true)
--dns-option list Set DNS options
--group-add list Add additional groups to join
--health-interval duration Time between running the check
--health-start-period duration Start period for the container to
--health-timeout duration Maximum time to allow one check to
--isolation string Container isolation technology
--log-opt list Log driver options
--memory-reservation bytes Memory soft limit
--security-opt list Security Options
--storage-opt list Storage driver options for the container
--sysctl map Sysctl options (default map[])
--ulimit ulimit Ulimit options (default [])
--volume-driver string Optional volume driver for the container
Linux Cgroups 給用戶暴露出來的操作介面是檔案系統,
它以檔案和目錄的方式組織在作業系統的 /sys/fs/cgroup 路徑下,
執行此命令查看:mount -t cgroup
在 /sys/fs/cgroup 下面有很多諸如 cpuset、cpu、 memory 這樣的子目錄,也叫子系統
在每個子系統下面,為每個容器創建一個控制組(即創建一個新目錄),
控制組下面的資源檔案里填上什么值,就靠用戶執行 docker run 時的引數指定,
[root@server1 ns]# cd /sys/fs/cgroup/memory/docker/
[root@server1 docker]# ls
c77c7b63544c3a357d5f13f2bdc8b68b3678d8a31234ac170b814ab9d60c2124
cgroup.clone_children
cgroup.event_control
cgroup.procs
memory.failcnt
memory.force_empty
memory.kmem.failcnt
memory.kmem.limit_in_bytes
memory.kmem.max_usage_in_bytes
memory.kmem.slabinfo
memory.kmem.tcp.failcnt
memory.kmem.tcp.limit_in_bytes
memory.kmem.tcp.max_usage_in_bytes
memory.kmem.tcp.usage_in_bytes
memory.kmem.usage_in_bytes
memory.limit_in_bytes
memory.max_usage_in_bytes
memory.memsw.failcnt
memory.memsw.limit_in_bytes
memory.memsw.max_usage_in_bytes
memory.memsw.usage_in_bytes
memory.move_charge_at_immigrate
memory.numa_stat
memory.oom_control
memory.pressure_level
memory.soft_limit_in_bytes
memory.stat
memory.swappiness
memory.usage_in_bytes
memory.use_hierarchy
notify_on_release
tasks
[root@server1 docker]# cd c77c7b63544c3a357d5f13f2bdc8b68b3678d8a31234ac170b814ab9d60c2124
[root@server1 c77c7b63544c3a357d5f13f2bdc8b68b3678d8a31234ac170b814ab9d60c2124]# cat memory.limit_in_bytes
9223372036854771712
CPU限額
cpu_period 和 cpu_quota 這兩個引數需要組合使用,用來限制行程在長度為 cpu_period 的一段時間內,只能被分配到總量為 cpu_quota 的 CPU 時間,以上設定表示20%的cpu時間,
[root@server1 ~]# cd /sys/fs/cgroup/cpu
[root@server1 cpu]# ls
cgroup.clone_children cpuacct.usage cpu.rt_runtime_us release_agent
cgroup.event_control cpuacct.usage_percpu cpu.shares system.slice
cgroup.procs cpu.cfs_period_us cpu.stat tasks
cgroup.sane_behavior cpu.cfs_quota_us docker user.slice
cpuacct.stat cpu.rt_period_us notify_on_release
[root@server1 cpu]# mkdir x2
[root@server1 cpu]# cd x2/
[root@server1 x2]# ls
cgroup.clone_children cpuacct.usage cpu.rt_period_us notify_on_release
cgroup.event_control cpuacct.usage_percpu cpu.rt_runtime_us tasks
cgroup.procs cpu.cfs_period_us cpu.shares
cpuacct.stat cpu.cfs_quota_us cpu.stat
root@server1 x2]# cat cpu.shares
1024
[root@server1 x2]# echo 100 > cpu.shares
[root@server1 x2]# dd if=/dev/zero of=/dev/null &
[1] 7451
[root@server1 x2]# echo 7451 > tasks
[root@server1 x2]# top
[root@server1 x2]# echo 1024 > cpu.shares
[root@server1 x2]# cat cpu.cfs_period_us
100000
[root@server1 x2]# cat cpu.cfs_quota_us
-1
[root@server1 x2]# echo 20000 > cpu.cfs_quota_us
[root@server1 x2]# cat cpu.cfs_quota_us
20000
記憶體限制
容器可用記憶體包括兩個部分:物理記憶體和swap交換磁區
--memory設定記憶體使用限額
memory-swap設定swap交換磁區限額memory-swap設定swap交換磁區限額
下載
[root@server1 shm]# yum install -y libcgroup-tools.x86_64

進行記憶體限制
[root@server1 shm]# cd /sys/fs/cgroup/memory/x1/
[root@server1 x1]# cat memory.limit_in_bytes
209715200
[root@server1 x1]# echo 209715200 > memory.memsw.limit_in_bytes
[root@server1 x1]# cat memory.memsw.limit_in_bytes
209715200

測驗寫入:
[root@server1 x1]# cd /dev/shm/
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 0.0326824 s, 3.2 GB/s
[root@server1 shm]# cgexec -g memory:x1 dd if=/dev/zero of=bigfile bs=1M count=300
Killed

設定的記憶體限制為200M,并且禁止是由交換磁區的記憶體,
我們在第一次寫了100M,顯示成功
第二次寫了300M,失敗,因為我們在前面限制了記憶體大小,禁止使用交換磁區的記憶體,寫入大小超過限制,并且不會使用交換磁區的記憶體,所以失敗
Block IO限制
--device-write-bps限制寫設備的bps
目前的block IO限制只對direct IO有效,(不使用檔案快取)
[root@server1 x2]# cd
[root@server1 ~]# docker run --help | grep device
--blkio-weight-device list Block IO weight (relative device
--device list Add a host device to the container
--device-cgroup-rule list Add a rule to the cgroup allowed
devices list
--device-read-bps list Limit read rate (bytes per second)
from a device (default [])
--device-read-iops list Limit read rate (IO per second) from
a device (default [])
--device-write-bps list Limit write rate (bytes per second)
to a device (default [])
--device-write-iops list Limit write rate (IO per second) to
a device (default [])
--gpus gpu-request GPU devices to add to the container
[root@server1 ~]# docker run -it --rm --device-write-bps /dev/vda:30MB rhel7 bash
bash-4.2# dd if=/dev/zero of=bigfile bs=1M count=200 oflag=direct
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 6.61775 s, 31.7 MB/s
bash-4.2# dd if=/dev/zero of=bigfile bs=1M count=200
200+0 records in
200+0 records out
209715200 bytes (210 MB) copied, 0.294043 s, 713 MB/s
bash-4.2# exit

三 docker安全加固
利用LXCFS增強docker容器隔離性和資源可見性
安裝lxcfs
[root@server1 ~]# yum install -y lxcfs-2.0.5-3.el7.centos.x86_64.rpm

啟動lxcfs
[root@server1 ~]# lxcfs /var/lib/lxcfs/ &

docker run -it -m 256m \
-v /var/lib/lxcfs/proc/cpuinfo:/proc/cpuinfo:rw \
-v /var/lib/lxcfs/proc/diskstats:/proc/diskstats:rw \
-v /var/lib/lxcfs/proc/meminfo:/proc/meminfo:rw \
-v /var/lib/lxcfs/proc/stat:/proc/stat:rw \
-v /var/lib/lxcfs/proc/swaps:/proc/swaps:rw \
-v /var/lib/lxcfs/proc/uptime:/proc/uptime:rw \
ubuntu

設定特權級運行的容器:--privileged=true
有的時候我們需要容器具備更多的權限,比如操作內核模塊,控制swap交換磁區,掛載USB磁盤,修改MAC地址等,
[root@server1 ~]# docker run -it --rm busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
50: eth0@if51: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ # ip link set down eth0
ip: SIOCSIFFLAGS: Operation not permitted

此時沒有權限進行相關的ip設定
打開權限
[root@server1 ~]# docker run -it --rm --privileged=true busybox
/ # ip link set down eth0
/ # ip link set up eth0
/ #

設定容器白名單:--cap-add
--privileged=true 的權限非常大,接近于宿主機的權限,為了防止用戶的濫用,需要增加限制,只提供給容器必須的權限,此時Docker 提供了權限白名單的機制,使用--cap-add添加必要的權限,
capabilities手冊地址: http://man7.org/linux/man-pages/man7/capabilities.7.html
[root@server1 ~]# docker run -it --cap-add=NET_ADMIN --name demo busybox
/ # ip
BusyBox v1.29.3 (2018-10-01 22:37:18 UTC) multi-call binary.
Usage: ip [OPTIONS] address|route|link|tunnel|neigh|rule [COMMAND]
OPTIONS := -f[amily] inet|inet6|link | -o[neline]
COMMAND :=
ip addr add|del IFADDR dev IFACE | show|flush [dev IFACE] [to PREFIX]
ip route list|flush|add|del|change|append|replace|test ROUTE
ip link set IFACE [up|down] [arp on|off] [multicast on|off]
[promisc on|off] [mtu NUM] [name NAME] [qlen NUM] [address MAC]
[master IFACE | nomaster]
ip tunnel add|change|del|show [NAME]
[mode ipip|gre|sit]
[remote ADDR] [local ADDR] [ttl TTL]
ip neigh show|flush [to PREFIX] [dev DEV] [nud STATE]
ip rule [list] | add|del SELECTOR ACTION
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
56: eth0@if57: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
/ #

安全加固的思路
保證鏡像的安全:
使用安全的基礎鏡像
洗掉鏡像中的setuid和setgid權限
啟用Docker的內容信任
最小安裝原則 對鏡像進行安全漏洞掃描,鏡像安全掃描器:Clair
容器使用非root用戶運行
保證容器的安全:
對docker宿主機進行安全加固
限制容器之間的網路流量
配置Docker守護程式的TLS身份驗證
啟用用戶命名空間支持(userns-remap)
限制容器的記憶體使用量
適當設定容器CPU優先級
docker安全的遺留問題
主要的內核子系統都沒有命名空間,如:
SELinux
cgroup
在/sys下的檔案系統
/proc/sys, /proc/sysrq-trigger, /proc/irq, /proc/bus
設備沒有命名空間:
/dev/mem
/dev/sd*檔案系統設備
內核模塊
Docker安全的頂尖開源工具:
Docker Bench for Security 對照安全基準審計Docker容器的腳本
Clair API驅動的靜態容器安全分析工具,擁有龐大的CVE資料庫
Cilium 內核層可感知API的網路和安全工具
Anchore 使用CVE資料和用戶定義的策略檢查容器安全的工具
OpenSCAP Workbench 用于為各種平臺創建和維護安全策略的環境
Dagda 用于在Docker容器中掃描漏洞、特洛伊木馬、病毒和惡意軟體的工具
Notary 使用服務器加強容器安全的框架,用于以加密方式委派責任
Sysdig Falco 提供了行為活動監控,可深入了解容器
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/289959.html
標籤:其他
