• 在CentOS上为Docker开启SELinux


    生产服务器使用的是CentOS 7系统,安装Docker也一直都是使用yum命令直接从CentOS自己的源安装。自从Docker项目改名为moby,进而诞生CE和EE两个不同版本后。不知是因为版权还是其他的什么原因,CentOS源中的Docker版本不再更新了,default维持在1.12.6,latest为1.13.1。

    为了使用新版本的Docker,只能添加官方repo,然后安装docker-ce。安装完成后,在默认配置上与CentOS自带版相比,发现了两个不同之处:

    1. 存储驱动默认换成了overlay
    2. SELinux默认没有开启(指Docker服务配置)

    分析

    关于存储驱动的问题,这里暂时不做讨论,只是来看一下SELinux的问题。这里说的SELinux没有开启不是指在操作系统层面上将其disable掉了,而是说Docker服务的配置中没有将其enable。毕竟在Docker中开启SELinux是要在操作系统也就是Linux内核开启了SELinux的前提下进行的。首先,Docker没有开启SELinux,在现象上会有什么不同?

    我们有两台服务器,第一台上Docker开启了SELinux,而第二台没有。两台上面都有运行nginx容器,执行如下命令对比一下:

    [admin@server1 ~]$ ps -AZ | grep nginx
    system_u:system_r:svirt_lxc_net_t:s0:c375,c378 2285 ? 00:00:22 nginx
    system_u:system_r:svirt_lxc_net_t:s0:c245,c772 2407 ? 00:00:00 nginx
    system_u:system_r:svirt_lxc_net_t:s0:c245,c772 2453 ? 00:00:02 nginx
    system_u:system_r:svirt_lxc_net_t:s0:c375,c378 24771 ? 00:00:00 nginx
    
    [admin@server2 ~]$ ps -AZ | grep nginx
    system_u:system_r:spc_t:s0       4375 ?        00:00:00 nginx
    system_u:system_r:spc_t:s0       4419 ?        00:00:00 nginx
    system_u:system_r:spc_t:s0       4739 ?        00:00:01 nginx
    system_u:system_r:spc_t:s0       4752 ?        00:00:01 nginx
    system_u:system_r:spc_t:s0       9536 ?        00:00:00 nginx
    system_u:system_r:spc_t:s0       9564 ?        00:00:00 nginx
    system_u:system_r:spc_t:s0      19178 ?        00:00:00 nginx
    system_u:system_r:spc_t:s0      19255 ?        00:00:00 nginx
    

    通过对比,我们发现开启SELinux后的Docker服务:

    1. 容器内的进程运行在svirt_lxc_net_t domain下
    2. 不同容器内的进程,安全上下文sensitivity段是不相同的(SELinux的MCS隔离)

    对于没有开启SELinux的Docker服务:

    1. 容器进程domain为spc_t
    2. 所有容器进程的安全上下文sensitivity完全相同

    根据以上对比,显而易见的是,在SElinux没有开启时容器进程拥有相同的sensitivity,所以就无法依赖SELinux实现容器间的安全隔离了。也就是说如果某个容器内的服务进程因为漏洞等原因被入侵,进而被黑客控制,SELinux不会阻止此进程去访问其他容器的资源。

    对于svirt_lxc_net_tspc_t,可能第一眼看来不会有那么多的想法,我们先来看看svirt_lxc_net_t的进程是个什么体验:

    [admin@server2 ~]$ runcon -u system_u -r system_r -t svirt_lxc_net_t -l s0:c125,c512 /bin/bash
    bash: /home/admin/.bashrc: Permission denied
    bash-4.2$ ls
    ls: cannot open directory .: Permission denied
    bash-4.2$ ps -Z
    system_u:system_r:svirt_lxc_net_t:s0:c125,c512 23686 pts/0 00:00:00 bash
    system_u:system_r:svirt_lxc_net_t:s0:c125,c512 23722 pts/0 00:00:00 ps
    bash-4.2$
    

    因为当前目录的安全上下文类型是user_home_t,按照SELinux策略,svirt_lxc_net_t是没有权限访问的。虽然能够感受到进程确实受到了限制,但是还不是很直观。接下来用sepolicy命令分析一下安全策略:

    [admin@server2 ~]$ sepolicy communicate -s svirt_lxc_net_t -t svirt_lxc_net_t
    sysctl_net_unix_t
    cifs_t
    svirt_lxc_net_t
    fusefs_t
    cgroup_t
    svirt_sandbox_file_t
    usermodehelper_t
    svirt_home_t
    hugetlbfs_t
    nfs_t
    

    根据man page中的说明,这个命令用来分析source和target两个domain可以通过哪些type来通信,也就是哪些type对于source来说可写,对于target来说可读。我们把source和target指定为同一domain,来看看该domain能够读写哪些type。

    我们看到了,一个很熟悉的svirt_sandbox_file_t,正是给Docker容器挂载volume时经常看到、用到的。据了解svirt_lxc_net_t相关策略就是为容器、虚拟化技术而设计的,除了可以访问svirt_sandbox_file_t类型的文件还拥有网络能力,并且可以执行/usr下大多数的命令。

    再用以上命令看一下spc_t,因为行数太多,所以做一下统计:

    [admin@server2 ~]$ sepolicy communicate -s spc_t -t spc_t | wc -l 
    3816
    [admin@server2 ~]$ sepolicy communicate -s unconfined_t -t unconfined_t | wc -l      
    3816
    

    根据当前的安全策略,3816个type,比起svirt_lxc_net_t的10个,不可同日而语。而且我们发现,不受限domain unconfined_t也是3816。那么spc_t就等于unconfined_t了吗?其实也不是。

    根据Dan Walsh的Blog所讲,unconfined_t是为管理员而设置的一个user domain,SELinux安全策略会阻止绝大多数的受限domain和unconfined_t通信。spc_t全称为Super Privileged Container,也就是特权容器。根据SELinux策略,Docker daemon container_runtime_t可以通过transition转变为spc_t,而且大多数重要的受限domain可以通过unix domain socket和spc_t进行通信。

    配置

    上面的分析只是为了对SELinux对Docker的影响有更深入地了解,同时感受SELinux的重要性。其实在Docker服务配置中开启SELinux很简单:

    1. 一种方法是在dockerd启动时加上--selinux-enabled参数,在CentOS上可以修改systemd Unit文件docker.service
    2. 另一种方法实在/etc/docker/daemon.json配置文件中加上:
      {
       "selinux-enabled": true
      }
      
      然后重启docker服务

    需要注意的是,在SELinux开启之前创建的容器不会受到影响。如果要为这些容器应用SELinux,可以重建,或者尝试自己修改容器的配置文件和文件系统。

    参考

    1. 官方文档 https://docs.docker.com/edge/engine/reference/commandline/dockerd/
    2. Dan Walsh的Blog https://danwalsh.livejournal.com/74754.html
    3. https://help.replicated.com/docs/kb/supporting-your-customers/selinux/
  • 相关阅读:
    八大排序
    链表的合并
    记录B站yxc的背包九讲相关代码
    C++中多态实现
    YOLOV4所用到的一些tricks
    C++中的string 和 stringstream 的知识
    博客园中插入视频
    博客园中插入网页
    面试前必须要知道的【可重入锁 自旋锁】
    面试前必须要知道的【乐观锁 悲观锁】
  • 原文地址:https://www.cnblogs.com/youlin/p/enable_selinux_for_docker_on_centos.html
Copyright © 2020-2023  润新知