7

保护容器部署安全的一些技巧

 3 years ago
source link: https://www.lujun9972.win/blog/2018/08/18/%E4%BF%9D%E6%8A%A4%E5%AE%B9%E5%99%A8%E9%83%A8%E7%BD%B2%E5%AE%89%E5%85%A8%E7%9A%84%E4%B8%80%E4%BA%9B%E6%8A%80%E5%B7%A7/index.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

保护容器部署安全的一些技巧

摘录自 《Docker开发指南》 13.7 "安全建议"

设置容器内运行用户或开启USER NAMESPACE

永远不要以root用户的身份在容器内运行正式的应用,否则一旦攻击者攻破了应用就能获取容器的全部访问权限。

而且在未开启USER NAMESPACE的情况下,该权限会蔓延到主机挂载到容器中的卷上。

更糟糕的是,若他能突破容器的限制,则它就能获得主机上的root权限了。

限制容器联网

容器应该仅仅打开必须的端口,且只对所需的容器开放。

为了实现这一点,Docker守护进程启动时需要加上 --icc=false 参数以关容器间的默认通讯。

另外,在主机上发布端口时,Docker默认在主机所有接口上发布,最好明确指定希望绑定的接口以减少攻击面

docker run -p 192.168.1.9:8080:8080 -d httpd

删除容器中的setuid和setgid文件

这类文件一般只在构建镜像时有用,但却极易被利用来发动提权攻击。

可以通过下面命令来找出并移除二进制文件的suid/sgid设置

RUN find / -perm /6000 -type f -exec chmod a-s {} \;||true

限制内存使用

限制容器内存使用可以防止DoS攻击和应用程序的内存泄漏。

限制CPU使用

若不限制容器的CPU使用率,则攻击者可以通过一个容器将主机CPU完全占用,从而导致系统被DoS攻击瘫痪。

CPU的限制参数包括如下:

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
docker help run |grep -E 'jbps|IO'
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
      --blkio-weight uint16            Block IO (relative weight),
      --blkio-weight-device list       Block IO weight (relative device
      --device-read-iops list          Limit read rate (IO per second)
      --device-write-iops list         Limit write rate (IO per second)

限制重启次数

若系统不断崩溃又不断重启,将会造成大量系统时间和资源浪费。

为了防止这种情况出现,我们可以将重启策略由 always 改成 on-failure 并指定重启次数

docker run -d --restart=on-failure:10 $image

容器的重启次数可以通过 docker inspect.RestartCount 元数据找到

docker inspect -f "{{.RestartCount}}" $container

另外,Docker重启容器的时间间隔采用指数递增的方式进行,即第一次重启等待100ms,第二次200ms,第三次400ms,这个措施能有效防止利用重启机制引发DoS攻击

设置文件系统只读

阻止攻击者对容器内文件系统的写入可以抵御系统的攻击。

docker run 中使用 --read-only 参数可以把容器的文件系统设置为只读:

docker run --read-only ubuntu touch x 2>&1 || exit 0
touch: cannot touch 'x': Read-only file system

给数据卷参数后加上 :ro 则能够把卷设为只读

docker run -v ${pwd}:/pwd:ro ubuntu touch /touch /pwd/x 2>&1 ||exit 0
touch: cannot touch '/pwd/x': No such file or directory

限制内核能力

我们可以通过 docker run--cap-add--cap-drop 参数来控制容器允许使用的内核能力。

最不安全的做法就是通过 --privileged 参数放开权限。

一般的做法是先把所有权限清空,再把需要的权限添加回去

docker run --cap-drop all --cap-add CHOWN ubuntu chown 770 /tmp

应用资源限制

Linux内核定义了一些用于进程的资源限制,可以限制进程允许fork的子进程数,或者允许打开的文件描述符数量等。

通过 docker run 的 --ulimit 选项可以将限制也用于容器上。 同时,我们可以在启动Docker守护进程时加上 --default-ulimit 选项来给所有容器设置资源限制的默认值。 选项参数中包括两个数值,其格式为 资源=软限制:硬限制 ,若只提供一个值,则表示同时作为软限制和硬限制。

比较常用的限制包括以下几个:

把CPU时间限制为给定参数,以秒为单位。

当达到软限制后,会发送一个 SIGXCPU给容器,达到硬限制后则会发送一个 SIGKILL 信号给容器

docker run --ulimit cpu=12:14 stress stress --cpu 1

nofile

制定容器中能够同时打开的最多文件描述符数量

docker run --ulimit nofile=5 ubuntu cat /etc/hostname

需要注意的是,操作系统本身会占用3个文件描述符,分别对应stdin,stdout,stderr

nproc

指定运行容器的用户能够创建进程的最大数量。

docker run --user 500 --ulimit nproc=2 -d ubuntu sleep 100

需要注意的是: nproc限制的不是容器,而是运行这个容器的用户的所有进程数量

启用Linux安全模块(LSM)

最常见的Linux安全模块包括AppArmor和SELinux。

通过 docker run--security-opt 选项可以设置容器的标签,使之与LSM整合在一起

审核容器和镜像

  • 定期检查正在运行的容器,确保使用的镜像是最新的,而且这些镜像所使用的如那件也是最新的,没有安全隐患的。
  • 使用 docker diff 检查容器与镜像之间的差异
  • 运行极简的镜像,其中只包含应用程序必需的文件和程序库

为Docker Daemon开启TLS加密传输

若Docker Daemon通过TCP方式与外界通讯,则可能传输内容会被截获,为此Docker Daemon提供了4个参数来开启TLS加密传输

docker daemon --tlsverify \
       --tlscacert=ca.pem \
       --tlscert=server-cert.pem \
       --tlskey=server-key.pem \
       -H=0.0.0.0:2376

--tlsverify安全传输验证 --tlscacert=ca.pem信任的证书 --tlscert=server-cert.pem --tlskey=server-key.pem服务器或客户端密钥

当然,相应的在客户端连接时也需要设置这四个参数:

docker --tlsverify \
       --tlscacert=ca.pem \
       --tlscert=cert.pem \
       --tlskey=key.pem \
       -H=${DAEMON_HOST}:2376

注意那些未隔离的内核资源

目前namespace在隔离上并不完善,还有许多未隔离的内核资源可能会影响到容器安全,比如 procfs, syslog


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK