EN
注册
我要评分
文档获取效率
文档正确性
内容完整性
文档易理解
在线提单
论坛求助
鲲鹏小智

容器运行配置规则

启用cgroups能力进行恰当的资源限制

为了防止通过耗尽系统资源引发拒绝服务(DoS)攻击,可使用特定的命令行参数被来启用一些资源限制。

Kbox的base_box脚本中通过docker启动参数“--cpuset-cpus”“--memory”限制CPU和内存的使用。由于Kbox使用ext4文件系统,其不支持“--storage-opt”参数,因此Kbox未限制存储使用。

限制运行容器的Linux内核Capability能力

在默认情况下,Docker会通过有限的Linux内核Capability启动容器。也就是说,任何进程都会被授予必要的Capability,而不是root访问。通过Linux内核Capability,在通常需要root权限的几乎所有特定 区域 ,进程都无需作为root运行。使用非默认配置文件的用户可以通过Docker来增加或删减Capability。这样,通过删减Capability,Docker会更安全;而增加Capability,Docker安全性会降低。

Kbox的base_box脚本中通过以下方式默认关闭所有Capability再按需增加必要的,其中{"Capability 1", ..., "Capability n"}集合具体值可查询base_box脚本。

1
# docker run --cap-drop=ALL --cap-add={"Capability 1", ..., "Capability n"} 

可通过以下命令查看是否只有必要的Capability被添加。

1
# docker ps --quiet --all |xargs docker inspect --format '{{ .Id }}:CapAdd={{ .HostConfig.CapAdd }}CapDrop={{ .HostConfig.CapDrop }}'

在Android容器运行时需要开启SYS_ADMIN Capability,且在apparmor中打开mount能力,容器具有mount能力后可以通过挂载cgroup、proc、sysfs等文件系统进行容器逃逸,建议用户在apparmor中对敏感文件系统进行过滤或对宿主机OS、内核进行安全加固。

限制容器通过SUID/GUID位获得额外权限

限制容器通过SUID或GUID位获取额外权限。SUID和GUID程序在受攻击导致任意代码执行(如缓冲区溢出)时将非常危险,因为它们将可以运行在进程文件所有者或组的上下文中。

建议通过以下步骤删除系统中不需要的SUID和GUID程序。

  1. 找到系统中不需要的SUID和GUID程序。
    1
    2
    # find / -perm -4000 -exec ls -l {} \; 2>/dev/null
    # find / -perm -2000 -exec ls -l {} \; 2>/dev/null
    
  2. 移除SUID和GUID文件权限,下列命令中的“filename”“directory”请根据实际情况修改。
    1
    2
    # sudo chmod u-s filename
    # sudo chmod -R g-s directory
    

不要在容器上挂载主机系统敏感目录

主机系统敏感目录(包括根目录、/boot、/dev、/etc、/lib、/proc、/sys、/usr)不能作为容器卷挂载,尤其是在读写模式下。如果在读写模式下挂载,敏感目录中的文件可能会被更改。这些更改可能没有必要,还可能会带来安全问题,侵害docker主机。

Kbox的base_box脚本中将“/proc”“/sys”“/dev”目录下子目录的挂载方式修改为只读。

可通过以下命令确认,结果不匹配“Source:(/|/boot|/dev|/etc|/lib|/proc|/sys|/usr)\s+.*RW:true”,则修改成功。

1
# docker ps --quiet --all| xargs docker inspect --format '{{ .Id }}: Volumes={{ .Mounts }}' 2>/dev/null

容器中只运行必需的软件,不以root权限运行不受信的应用

容器中若使用不必要的软件,可能会加大容器的攻击面,同时也违背了最小和精简容器镜像的概念。因此,不要为容器安装或运行任何不必要的软件。

只打开容器需要的端口

容器可以只使用Dockerfile中为其镜像定义的端口运行,也可以任意传递运行时参数以打开端口列表。此外,随着时间的推移,Dockerfile可能会经历各种更改,暴露的端口列表可能与容器中运行的应用程序相关,也可能不相关。打开不需要的端口会加大容器和容器化应用程序的攻击面。因此不要暴露不需要的端口。

建议修改方式:

启动容器时,使用“--publish”“-p”选项明确指定特定容器实例所需的端口。例如:

1
# docker run --interactive --tty --publish 5000 --publish 5001 --publish 5002 my_container /bin/bash

Kbox的base_box脚本中通过以下方式指定容器实例所需的端口。

1
2
3
4
local PORT
for PORT in ${PORTS[@]}; do
    RUN_OPTION+=" -p $PORT "
done

设置容器CPU适当优先级

CPU时间默认在各容器之间平均分配。如有需要,可以使用CPU共享特性控制CPU时间在容器实例之间的分配。CPU共享功能将容器进行优先级排序,并禁止优先级低的容器频繁地占用CPU资源,确保优先级高的容器得到更好的服务。

Kbox的base_box脚本中通过启动参数“--cpu-shares”管理容器之间的CPU份额。

将传入的容器流量绑定到特定主机接口

Docker容器默认可以连接到外部世界,但外部世界不能连接到容器。每个对外连接显示都是源自主机的IP地址。只允许通过主机上的特定外部接口接触容器服务。如果主机上有多个网络接口,则容器可以接受任何网络接口上暴露的端口连接。这可能不是期望的结果,也可能不受保护。很多时候,特定接口会对外暴露,并且在这些接口上运行诸如入侵检测,入侵防御,防火墙,负载平衡等服务以筛选传入的公共流量。因此,不应接受任何接口上的传入连接,只接受来自特定外部接口的传入连接。这里主机接口通指网络接口,是主机与外部系统的连接通道,而主机端口是指该主机接口对应的TCP/UDP端口,接口一般包含IP地址和端口。

建议修改方式:

将容器端口绑定到所需主机端口上特定的主机接口。如下所示,将容器端口80绑定到49153上的主机端口,并且只接受来自10.2.3.4外部接口的传入链接。

1
# docker run --detach --publish 10.2.3.4:49153:80 nginx

实现此安全加固措施可修改Kbox的base_box脚本中“-p”选项内容,配置格式请参考示例,并根据实际情况自行配置可用ip地址:

1
# RUN_OPTION+=" -p XXX.XXX.XXX.XXX:$PORT "

将容器的根文件系统挂载为只读

容器的根文件系统应该被视为“黄金镜像”,避免任何写操作。应明确定义专门用于写操作的容器卷。

将容器的根文件系统挂载为只读可能会出现兼容性问题,请按照实际业务需求评估是否需要采纳该建议。

不要禁用默认seccomp配置文件

默认seccomp配置文件是一个指定可以执行哪些系统调用的白名单,进程可利用seccomp过滤来为传入的系统调用指定过滤器。Docker默认的seccomp配置文件在白名单基础上工作,允许311个系统调用而阻止其他所有的调用。大量的系统调用暴露给每个用户空间进程,其中许多系统调用在整个进程周期中都未使用。大多数应用程序根本不需要这些系统调用,因此可以使用精简版系统调用。精简版系统调用减小了暴露给应用程序的总内核面,从而提高了应用程序的安全性。

在Ubuntu操作系统中,seccomp配置文件默认开启。除非想修改或使用修改的seccomp配置文件,否则不需做任何操作。

在openEuler 22.03 系统方案中,Android容器运行时需要禁用seccomp配置文件(seccomp=unconfined)。用户需要评估应用场景是否允许禁用seccomp配置文件以及禁用的风险,建议禁用seccomp配置文件后对宿主机OS、内核进行安全加固。

限制文件句柄和fork进程数量

攻击者可以在容器内使用单个命令启动fork炸弹。该fork炸弹能使整个系统崩溃,需要重启主机才能使崩溃系统再次运行。同时攻击者可以开启大量文件句柄,耗尽文件句柄资源,造成拒绝服务攻击。具体设置fork进程、文件句柄的阈值,根据产品实际业务情况决定。

实现此安全加固措施可以修改Kbox的base_box脚本,修改方式请参考示例。该阈值需要客户根据应用场景进行合理的设置,数值不正确可能会导致容器无法使用。

# RUN_OPTION+=" --pids-limit XXX --files-limit XXX "

不要使用Docker默认的网络桥接接口Docker0

使用Docker用户自定义的容器网络,而不使用Docker默认的网络桥接接口docker0。docker0作为默认的网络接口,在没有配置相应网络过滤前,容易遭受ARP欺骗和MAC泛洪攻击。注意:Docker默认是运行在docker0桥接的。

建议修改方式:

  1. 删除旧网桥。在执行此操作之前,先删除服务器上所有容器。
    1
    2
    3
    # sudo systemctl stop docker
    # sudo ip link set dev docker0 down
    # sudo brctl delbr docker0
    
  2. 创建一个名称为“bridge0”的新网桥,以下示例仅作为格式参考,请根据实际情况自行配置可用网段,以保证容器连接网络正常。
    1
    2
    3
    # sudo brctl addbr bridge0
    # sudo ip addr add XXX.XXX.XXX.XXX/XX dev bridge0
    # sudo ip link set dev bridge0 up
    

    上述可用网段可参考默认网桥接口docker0的配置,以下图为例,网段应设置为172.17.0.1/16。

    可通过以下命令确认创建的新网桥“bridge0”详细信息。

    1
    # ifconfig bridge0
    
  3. 添加新网桥的配置信息。
    “/etc/docker/daemon.json”文件中添加属性“"bridge": "bridge0"”
    1
    2
    # vim /etc/docker/daemon.json
    "bridge":"bridge0"
    

    “/etc/docker/daemon.json”文件不存在,则自行创建该文件。

    1
    2
    3
    4
    5
    # touch /etc/docker/daemon.json
    # vim /etc/docker/daemon.json
    {
    "bridge":"bridge0"
    }
    
  4. 重启Docker服务。
    1
    2
    # systemctl daemon-reload
    # systemctl restart docker
    

    重启Docker服务后,可能会重新拉起默认的网络桥接接口“docker0”,因此在执行4后,需要通过以下命令检查当前环境是否还存在“docker0”

    1
    # ifconfig docker0
    

    若仍然能够查询到“docker0”,则需要通过以下命令手动删除。

    1
    2
    # sudo ip link set dev docker0 down
    # sudo brctl delbr docker0
    

    每次重启服务器后,都需要先执行2重新创建新网桥“bridge0” ,才能重启docker服务

搜索结果
找到“0”个结果

当前产品无相关内容

未找到相关内容,请尝试其他搜索词