Docker 安全加固措施

# 我們運行一個容器
[root@server1 ~]# docker run -it --rm --memory 256MB --memory-swap 256MB ubuntu
root@3f308cdd0b55:/# free -m			# 查看內存
             total       used       free     shared    buffers     cached
Mem:           991        433        557         12          2        249
-/+ buffers/cache:        181        809
Swap:         2047          0       2047
root@3f308cdd0b55:/# exit
[root@server1 ~]# free -m			# 容器外查看內存
              total        used        free      shared  buff/cache   available
Mem:            991         125         579          12         286         704
Swap:          2047    
  • 發現我們開啓容器時雖然已經限制了內存爲256M,但是看到的總內存和容器外一樣,沒有做到完全的隔離,這是一個不安全的點,需要進行安全加固。

lxcfs 文件系統

首先我們可以通過 lxcfs 文件系統增強 docker 容器的隔離性和資源可見性.

[root@server1 ~]# docker run -it --name vm1 -m 256M ubuntu		# 運行一個容器
root@6718c6a02544:/# free  -m
             total       used       free     shared    buffers     cached
Mem:           991        434        556         12          2        251
-/+ buffers/cache:        180        810
Swap:         2047          0       2047
# 內存大小和外界相同。

root@6718c6a02544:/# cat /proc/cpuinfo 
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 61
model name	: Intel Core Processor (Broadwell)
stepping	: 2
microcode	: 0x1
cpu MHz		: 2495.998
cache size	: 4096 KB
physical id	: 0
siblings	: 1
core id		: 0
cpu cores	: 1
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
# 這裏和我們在外面看到的時一樣的,因爲它的信息都是共享宿主機的。

我們安裝 lxcfs 文件系統:

[root@server1 lxcfs]# yum install lxcfs-2.0.5-3.el7.centos.x86_64.rpm  -y
[root@server1 ~]# lxcfs /var/lib/lxcfs/ &	# 後臺運行啓動,/var/lib/lxcfs 是 lxcfs 默認數據目錄
[1] 3876
[root@server1 ~]# hierarchies:
  0: fd:   5: freezer
  1: fd:   6: devices
  2: fd:   7: memory
  3: fd:   8: cpuacct,cpu
  4: fd:   9: hugetlb
  5: fd:  10: pids
  6: fd:  11: net_prio,net_cls
  7: fd:  12: blkio
  8: fd:  13: cpuset
  9: fd:  14: perf_event
 10: fd:  15: name=systemd

[root@server1 ~]# cd /var/lib/lxcfs/		
[root@server1 lxcfs]# ls
cgroup  proc		# ccgroup 是資源限制,proc 是系統信息

[root@server1 proc]# ls
cpuinfo  diskstats  meminfo  stat  swaps  uptime
# 所以我們可以把這個目錄掛載到容器裏面,就可以看到我們想要的信息了,我們只需要在這裏限制就行了

設置特權級運行的容器:

加 --privileged=true 參數。

有時候我們需要容器具備更多權限,比如操作內核模塊,控制 swap 分區,修改 MAC 地址等。

root@9b2f8448999b:/# id			# 當前是root用戶
uid=0(root) gid=0(root) groups=0(root)
root@9b2f8448999b:/# ip addr add 172.17.0.3/24 dev eth0
RTNETLINK answers: Operation not permitted			# 加一個ip地址卻不被允許,因爲沒有實際權限

[root@server1 ~]# docker run --help | grep priv 	# 查看權限參數
--privileged			Give extended privileges to this container	# 給額外的權限
#默認這個權限是被禁掉的

[root@server1 proc]# docker run -it --name vm3 --privileged=true ubuntu		# 運行成功
root@c685225f26f0:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    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
root@c685225f26f0:/# ip addr add 172.17.0.10 dev eth0		# 添加一個ip地址
root@c685225f26f0:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    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
    inet 172.17.0.10/32 scope global eth0		# 添加成功。
       valid_lft forever preferred_lft forever
       
[root@server1 proc]# docker inspect vm3 | grep Pri
            "Privileged": true,		# 當前只有vm3 開啓了這個權限
[root@server1 proc]# docker inspect vm2 | grep Pri
            "Privileged": false,
[root@server1 proc]# docker inspect vm1 | grep Pri
            "Privileged": false,
  • 默認情況下這個權限比較大,基本上接近宿主機的權限,爲了防止用戶的權限濫用, 需要增加機制,只提供給容器必要的權限’ 相當於做 sudo的用戶權力下放

我們通過設置容器白名單實現。

容器白名單

http://man7.org/linux/man-pages/man7/capabilities.7.html
可以在這個網址進行capability 權限查詢
在這裏插入圖片描述

[root@server1 proc]# docker run -it --name vm4 --cap-add=NET_ADMIN ubuntu	# 這個參數代表只可以控制網絡,但其他不行
root@c8a9b1998cfb:/# ip addr add 172.17.0.5/24 dev eth0
root@c8a9b1998cfb:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:04 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.4/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet 172.17.0.5/24 scope global eth0
       valid_lft forever preferred_lft forever
root@c8a9b1998cfb:/# 
[root@server1 proc]# docker inspect vm4 |grep Pri
            "Privileged": false,			# 但是此時的 privileged 是關閉的
[root@server1 proc]# docker inspect vm4 | less
            "CapAdd": [
                "NET_ADMIN"		# 可以看到我們加的參數
            ],

# 我們還可以用這種方式查看:
[root@server1 proc]# docker inspect -f {{.HostConfig.Privileged}} vm4
false
[root@server1 proc]# docker inspect -f {{.HostConfig.CapAdd}} vm4
[NET_ADMIN]

Docker安全加固思路

  1. 保證鏡像安全:
    使用安全的基礎鏡像(比如看不到構建歷史的不用);刪除鏡像中的 setuid 和 setgid 權限(suid、sgid);;啓用 docker 內容信任(證書認證);最小安裝原則;對鏡像進行安全漏洞掃描,鏡像安全掃描 器(Clair);容器使用非 root 運行

  2. 保證容器安全:
    對 docker 主機進行安全加固;限制容器之間的網絡流量(某個容器流量升高,會對其他容器或主機有影響);配置 docker 守護程序的 TLS 身份驗證;啓用用戶命名空間支持(userns-remap 參數,在容器第一次啓動前就要加上,寫在 /etc/docker/daemon.json 文件裏,還需要對 docker 數據目錄做權限配置 /var/lib/docker);限制容器內存使用量;適當設置容器 CPU 優先級,/sys/fs/cgroup/cpu/cpu.shares 這個文件裏

  3. docker 安全遺留問題:
    默認情況下只有 6 個 namespace,很多主要的內核子系統是沒有命名空間的,如 SELinux,Cgroup,
    /sys 下的文件系統,/proc/sys,/proc/sysrq-trigger 等

[root@server1 ns]# ls /sys
block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
[root@server1 ns]# ls /proc/sys
abi  crypto  debug  dev  fs  kernel  net  sunrpc  user  vm
[root@server1 ns]# ls /proc/sysrq-trigger 
/proc/sysrq-trigger
[root@server1 ~]# docker inspect vm4| grep Pid
            "Pid": 4204,			# 進程爲4024
            "PidMode": "",
            "PidsLimit": 0,
[root@server1 ~]# cd /proc/4204/ns
[root@server1 ns]# ls
ipc  mnt  net  pid  user  uts			# 可以看到只有六個命名空間
命名空間 功能 系統調用參數 內核版本
MNT Namespace(mount) 提供磁盤掛載點和文件系統的隔離能力 CLONE_NEWNS Linux 2.4.19
IPC Namespace(Inter-Process Communication) 提供進程間通信的隔離能力 CLONE_NEWIPC Linux 2.6.19
UTS Namespace(UNIX Timesharing System) 提供主機名隔離能力 CLONE_NEWUTS Linux 2.6.19
PID Namespace(Process Identification) 提供進程隔離能力 CLONE_NEWPID Linux 2.6.24
Net Namespace(network) 提供網絡隔離能力 CLONE_NEWNET Linux 2.6.29
User Namespace(user) 提供用戶隔離能力 CLONE_NEWUSER Linux 3.8

比如我們的設備就沒有命名空間:/dev/mem(進程和物理地址的映射),/dev/sd*文件系統設備,內核模
塊等,都還需要進一步的改進。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章