栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

p7云原生架构师一期

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

p7云原生架构师一期

如何提高DOCKER 的安全性

Docker容器多年来一直是开发人员工具箱的重要组成部分,通过 docker 以标准化的方式构建、分发和部署应用程序。随着容器技术的发展以及应用越来越广泛,其安全性问题也逐渐凸显出来。我们都知道容器其实就是运行在操作系统上的一个线程,通过 namespace 和 cgroup 技术与宿主机进行隔离。但这种隔离并非十分安全的,攻击者可以很容易利用参数的错误配置从容器内逃逸到宿主机上。

“容器”一词经常被误解,因为许多开发人员倾向于将隔离的概念与错误的安全感联系起来,认为这种技术本质上是安全的。

所谓的容器的安全,其实完全取决于以下几个方面:

  • 配套基础设施的安全(例如操作系统、基础设施平台)
  • 基础设施上的软件组件
  • 运行时环境及相关配置

目前有很多有关容器的最佳实践都包含了提高容器的安全性措施。这些措施大都围绕着镜像构建、资源特权管理、文件系统、网络等方面。为了长期维护容器安全,- Clair 、Trivy、Docker Bench for Security 这些安全扫描工具不可或缺。

以下这些最佳实践的安全性措施仅限于对 Docker 的使用,并未包含任何 K8s 及 Docker Compose的理念与操作。但是对使用 K8s 或 Docker Compose 也有参考意义。
1. 镜像构建

1. 1 基础镜像的选择

基础镜像尽量选用可信的镜像,比如docker hub 的官方镜像。如果需要使用基础的发行版,则推荐使用 Alpine Linux 的基础镜像,因为他轻量级以及阉割部分功能,可以保证受攻击面比较小。当然使用alpine版本的镜像也有缺点,由于缺少linux部分依赖,则需要手动补全、安装软件的各种依赖,也有一定的使用门槛。

当然也可以使用 Google 所引入的 Distroless 镜像作为基础镜像。其最大的特点是仅仅包含程序以及其依赖项,并不包含标准 Linux 发行版中的包管理器、shell或其他任何程序。

这里有一个实验,分别基于 Apline 和 Distroless 作为基础镜像,来构建简单的 Hello World 的 Springboot 应用镜像。此处参考文章 使用哪个容器镜像——Distroless 还是 Alpine? 最终结论是:

镜像大小— 使用 Alpine 基础镜像编译的镜像为93.5 MB,而 distroless 镜像为139 MB。因此,与 distroless 镜像相比,Alpine 镜像更轻巧。
漏洞数量——Alpine 镜像共有:216 个漏洞(未知:0,低:106,中:79,高:27,关键:4)而 Distroless Image 共有:50 个漏洞(未知:0,低) : 30, 中: 6, 高: 9, 关键: 5)

1.2 使用非特权用户

在默认的情况下,容器内的进程是以 root(id=0)来运行程序的,这是一个十分危险的行为。所以需要通过以下两种方式来设定一个默认用户

  1. 在docker run时,指定一个容器中不存在的 user id docker run -u 4000
  2. 在 Dockerfile 中创建一个默认用户
FROM 

RUN addgroup -S appgroup 
 && adduser -S appuser -G appgroup
 
USER appuser

...  ...
这种方案则需要关注基础镜像中使用何种工具来创建用户了

1.3 使用单独的用户ID命名空间

默认情况下,Docker守护进程使用主机的用户ID所在的命名空间。因此,当容器内权限提升后,则会以root方式来访问宿主机主机以及其他容器。 为了降低此风险,应该将主机和Docker守护程序配置为使用带有--userns remap选项的单独名称空间。

1.4 当心环境配置

在 Dockerfile中,ENV指令中不应包含任何敏感信息。例如:

ENV $VAR
RUN unset $VAR

即使这样做,$VAR其实仍在镜像中,且很容易被读取。

为了增加读取限制,应该在构建的每一层中,在引入环境变量后将其销毁:

RUN export ADMIN_USER="admin" 
    && do something    
    && unset ADMIN_USER
1.5 不要将 docker.sock 暴露在容器中

这个不用多说了,由于Docker的 C/S 架构,docker.sock 是 Docker API的主要入口。如果放开这个入口,相当于把自家的大门完全敞开了。

2. 资源特权管理

特权是十分危险的,容器永远不应该以特权运行,否则容器中的进程将会拥有主机上的root权限及功能。docker 的创建应该增加--security-opt=no-new-privileges 参数来限制这种特权。

另一方面,Docker 利用linux的capabilities机制来进行细粒度的权限控制访问。容器会使用默认的一组capabilities,但是大部分我们基本都不会用到。一种建议是将所有的 capabilities 删除,仅根据程序需求来单独添加。例如运行 web 服务器的容器, 其实仅需要 NET_BIND_SERVICE 的能力,用于绑定服务器低于1024端口的权限(一般web服务器需要使用 80 端口)

第三,不要共享主机文件系统中的敏感目录:

  • root (/),
  • device (/dev)
  • process (/proc)
  • virtual (/sys) mount points. 如有需要,则谨慎的选择目录的权限设置

2.1 使用 Control Group 限制对资源的访问

控制组是用于控制每个容器对CPU、内存、磁盘I/O的访问的机制。默认情况下,容器与独立的cgroup相关联,但如果存在选项--cgroup parent,则会使主机资源面临DoS攻击的风险,因为这允许主机和容器之间共享资源。

3. 文件系统

3.1 使用只读权限

当容器是临时启用,且是无状态服务时,则应该将挂载的文件系统限制为只读。 docker run --read-only

3.2 对非持久性数据使用临时目录

docker run --read-only --tmpfs /tmp:rw ,noexec,nosuid

3.3 对持久化数据使用特定的文件系统

如果需要与主机文件系统或其他容器共享数据,则有两个选项:

  1. 创建挂载点,并对其使用限额进行限制。--mount type=bind,o=size
  2. 为专用分区创建绑定卷 --mount type=volume

在这两种情况下,如果共享数据不需要由容器修改,则使用 --read-only。 docker run -v :/path/in/container:ro
或是 docker run --mount source=,destination=/path/in/container,readonly

4. 网络

4.1 不要使用Docker的默认桥接docker0

docker0 是Docker用于将主机网络与容器网络分离的网桥。 当一个容器创建时,默认情况下Docker会将其连接到docker0网络。因此,所有容器都连接到docker0,并能够相互通信。这也将存在安全隐患。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/831312.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号