查看原文
其他

【技术分享】浅谈Docker技术及取证原理

拓界科技 南京拓界 2023-01-26

Docker是一种容器技术,诞生于2013年初,是基于Google公司的Go语言开发实现的。在容器技术流行之前常用的是虚拟机技术,虚拟机最大的缺点是笨重、启动比较耗时。Docker技术采用隔离的思想,旨在通过隔离来达到极致高效利用资源的目的。本期小拓和读者一起了解Docker核心技术并对Docker下的取证原理进行简单分析。


  01  Docker技术简介  

  1   Docker镜像
Docker镜像含有Docker容器运行所需的文件系统结构及其内容,因此是启动一个Docker容器的基础。如果将 Docker容器看作一套程序的运行环境,那么Docker镜像就是构造这个运行环境的模板。基于同一个Docker镜像,用户可以在短时间内迅速构造大量运行环境一致但各自独立的Docker容器。

Docker镜像采用分层结构,它的底层称为启动文件系统(bootfs)层,这一层对用户来说是透明的。bootfs 的上层为根镜像(rootfs)层,rootfs层通常是精简后的操作系统文件,如 CentOS、Debian和 Ubuntu等。当需要修改镜像内的某个文件时,只对处于最上方的读写层进行修改,而不覆写下层已有文件系统的内容,已有文件在只读层中的原始版本仍然存在,但是会被读写层中的新版文件所隐藏。当将这个修改过的容器文件系统保存为一个新的镜像时,保存的内容仅为最上层的读写层中更新过的文件,这也是Docker 如此轻巧的重要原因之一。这种增量式的修改使Docker镜像易于存储和传输,当用户向Docker Registry推送或者从 Docker Registry拉取一份新的镜像时,不需要下载或推送镜像中所有的文件层,而只需要下载或者推送有变化的文件层即可。

Docker镜像通过联合挂载技术将各层文件系统叠加在一起,最终形成包含所有底层文件与目录的文件系统,镜像按照一定的层次结构叠加而成,一个新的镜像可以基于另一个镜像构建。如无特别说明,下文中的镜像都指的是Docker镜像。


  2   Docker容器
Docker容器是Docker镜像的一个运行实例,或者说是处于运行状态的镜像,不同之处是它在镜像的只读文件层之上覆盖了一个额外的可写文件层。Docker容器内所有的文件变化都不会影响其基础镜像,除非以此容器为基础生成一个新的镜像,此时容器相对于镜像有修改的部分将作为一个文件层固化在新的镜像中。

Docker将标准集装箱的概念运用到了自身的设计哲学中,就像货轮只需要运输集装箱而无需关心箱内的货物一样。容器可以用来“运输”一个或一组应用,它里面封装了应用所需要的全部运行环境。基于这个特性,Docker容器可以非常方便地分发复用,拥有强大的可移植性。如无特别说明,下文中的容器都指的是Docker容器。


  3   Docker Registry
Docker Registry是一个集中化存储、管理和分发Docker镜像的仓库,其中还包括镜像层次结构和关于镜像的元数据,因此可以将Docker Registry简单看作类似于Git仓库之类的实体。当使用docker run命令启动一个容器时,若镜像没有存储在本地,Docker将从 Docker Registry中下载该镜像并保存到本地。
用户可以在自己的数据中心中搭建registry,同时也可以使用Docker公司维护的公共镜像仓库,即Docker Hub,其中包含了4万多个公共镜像可供用户下载。理论上Docker Hub中的镜像经过官方验证,通常认为是架构良好且安全的,用户在Docker Hub官方网站使用电子邮箱注册账户即可免费使用其服务。用户首次向Docker Hub推送镜像时,须在命令行客户端登录账号,用户密码经哈希变换后保存在~/.docker/config.json文件的auth字段中。

用户通过docker push命令将镜像推送到Docker Hub后,可以在网站页面中对自己的镜像进行添加描述信息等管理操作,若某一镜像被设定为“公开”状态,则其他用户可以使用docker search和docker pull命令搜索并拉取该镜像。


  02 Docker文件存储与配置信息分析

支撑Docker环境的镜像、容器和数据卷等要素及其配置信息都以一定规则存储在宿主机文件系统中,在了解它们的存储机制后,取证人员可以有的放矢地进行调查取证,按需求对特定容器的相关数据信息进行固定和保全。

Docker的默认工作目录位于/var/lib/docker,其中包含于用来构建Docker容器所需的文件系统环境的重要目录和文件,如图1所示。

图1 Docker相关目录及文件

  1   Docker镜像存储机制

在Docker的工作根目录中,graph目录(/var/lib/docker/graph)存储所有镜像的描述文件。对于每一个镜像层,graph目录中都有json和layersize两个文件,其中json文件记录了相应 Docker镜像的ID、依赖关系、创建时间和配置信息等;layersize则记录Docker镜像的大小。镜像本身的完整数据则保存在/var/lin/docker/aufs/diff目录的相应目录(相同ID)下。
  2   Docker容器存储机制

Docker中各容器的配置信息存放在/var/lib/docker/containers/路径下,这些配置信息包含了一个容器的所有元数据,各配置文件及其内容如表1所示。

表1 配置文件及其内容

Docker工作根目录中/var/lib/docker/linkgraph. db是记录GraphDB的文件,GraphDB是一个构建在SQLite之上的图形数据库,Docker deamon使用GraphDB记录它所维护的所有容器以及它们之间的link关系。GraphDB能够为调用者提供节点增加、删除、遍历、连接和查询等操作,这里的节点就是一个容器,而节点间的边就是一个Docker link关系。每启动一个容器,GraphDB中将会添加一个节点,当某个容器被设置了link操作时,在 GraphDB中就会为其创建一个父子关系(即一条边)。

  3   Docker数据卷存储机制

Docker数据卷(volume)是为了在容器与宿主机之间、容器与容器之间共享和持久化保存文件和文件夹而引入的机制。当从容器中某个文件夹创建volume时,volume的ID目录被收录在/var/lib/docker/volume路径下,这意味着容器挂载文件夹中的任何变化会直接反映到宿主机/var/lib/docker/volume/[container -ID]/_data路径下,同时这种反映是双向的。当容器从宿主机某个路径挂在volume时,则容器与宿主机挂载点的路径是由容器创建者指定,这时可以使用docker inspect -f { {.Volume} } container-ID命令,从命令输出中定位容器与宿主机挂载点的对应关系。

  03 Docker的网络配置信息分析

容器作为直接对外提供服务的实体,对其网络数据流的实时监控和分析是计算机取证过程中不可或缺的内容。Docker 默认采用网桥的网络连接模式,它会在宿主机中创建一个名为docker0的虚拟网桥和若干对以“veth”开头的虚拟网卡,这些虚拟网卡将各容器与docker0相连,组成了Docker内部的虚拟网络,如图2所示。

图2 Docker内部的虚拟网络

这里网桥的概念等同于交换机,为连接在其上的设备转发数据帧。各容器启动时会分配一个私有的内部P地址,docker0的IP地址作为各容器的网关存在,在与公网通信时则采用NAT地址转换。在同一宿主机中可能同时有多个容器需要对外通信,容器可以在启动时使用docker run命令中的-p选项为容器指定一个暴露端口和宿主机的一个指定端口进行绑定,通过不同的端口来区分不同容器的通信。

针对Docker网络的以上特性,取证人员可重点关注 docker inspect[container-ID]命令输出中的“PortBindings”字段和“Networks”字段。在掌握了IP地址和端口等关键信息后,取证人员可以根据这些参数,运用抓包工具对网络上的数据报文进行截获和分析,并将分析结果呈交法庭,达到认定犯罪行为、确定犯罪嫌疑人的目的。

  04 Docker环境的进程关系信息分析

进程用户空间中的信息往往与特定用户的特定操作行为直接关联,对于证据链的建立意义重大。Docker采用的是典型的C/S(client/server)构架,Docker daemon是构架中的主要用户接口和 Docker最核心的后台进程,它负责响应来自Docker client的请求,然后将这些请求翻译成系统调用以便完成对镜像或容器的管理操作。Docker容器相关的所有进程都是由Docker daemon进程及其子进程派生而出的,如图3所示。在理解各进程的隶属关系和PID获取方式后,取证人员可以精确地对容器中的相关进程进行分析取证。

图3 Docker相关进程关系


   结 语   

本期小拓对Docker技术及基于Docker环境的取证原理进行了阐述。在了解相关技术原理后,取证人员便能按需求对Docker关键数据进行固定,根据IP地址和端口等信息截获和分析数据,然后依照各进程之间的隶属关系和PID获取方式来精确对容器中的进程进行分析取证。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存