:first-child,
ol li > :first-child,
ul li ul:first-of-type,
ol li ol:first-of-type,
ul li ol:first-of-type,
ol li ul:first-of-type {
margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}

dl {
padding: 0;
}

dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}

dl dt:first-child {
padding: 0;
}

dl dt>:first-child {
margin-top: 0px;
}

dl dt>:last-child {
margin-bottom: 0px;
}

dl dd {
margin: 0 0 15px;
padding: 0 15px;
}

dl dd>:first-child {
margin-top: 0px;
}

dl dd>:last-child {
margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
font-size: 12px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
margin: 0 0px;
padding: 0px 0px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}

pre>code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}

pre {
background-color: #f8f8f8;
border: 1px solid #ccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}

pre code, pre tt {
background-color: transparent;
border: none;
}

kbd {
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background-color: #DDDDDD;
background-image: linear-gradient(#F1F1F1, #DDDDDD);
background-repeat: repeat-x;
border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
border-image: none;
border-radius: 2px 2px 2px 2px;
border-style: solid;
border-width: 1px;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
line-height: 10px;
padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
border-left: 4px solid #DDD;
padding: 0 15px;
color: #777;
}

blockquote>:first-child {
margin-top: 0px;
}

blockquote>:last-child {
margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
clear: both;
margin: 15px 0;
height: 0px;
overflow: hidden;
border: none;
background: transparent;
border-bottom: 4px solid #ddd;
padding: 0;
}

.highlight { background: #ffffff; }
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { font-weight: bold } /* Keyword */
.highlight .o { font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { font-weight: bold } /* Keyword.Constant */
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d14 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
.highlight .sc { color: #d14 } /* Literal.String.Char */
.highlight .sd { color: #d14 } /* Literal.String.Doc */
.highlight .s2 { color: #d14 } /* Literal.String.Double */
.highlight .se { color: #d14 } /* Literal.String.Escape */
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
.highlight .si { color: #d14 } /* Literal.String.Interpol */
.highlight .sx { color: #d14 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d14 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
.pl-c {
color: #969896;
}

.pl-c1,.pl-mdh,.pl-mm,.pl-mp,.pl-mr,.pl-s1 .pl-v,.pl-s3,.pl-sc,.pl-sv {
color: #0086b3;
}

.pl-e,.pl-en {
color: #795da3;
}

.pl-s1 .pl-s2,.pl-smi,.pl-smp,.pl-stj,.pl-vo,.pl-vpf {
color: #333;
}

.pl-ent {
color: #63a35c;
}

.pl-k,.pl-s,.pl-st {
color: #a71d5d;
}

.pl-pds,.pl-s1,.pl-s1 .pl-pse .pl-s2,.pl-sr,.pl-sr .pl-cce,.pl-sr .pl-sra,.pl-sr .pl-sre,.pl-src,.pl-v {
color: #df5000;
}

.pl-id {
color: #b52a1d;
}

.pl-ii {
background-color: #b52a1d;
color: #f8f8f8;
}

.pl-sr .pl-cce {
color: #63a35c;
font-weight: bold;
}

.pl-ml {
color: #693a17;
}

.pl-mh,.pl-mh .pl-en,.pl-ms {
color: #1d3e81;
font-weight: bold;
}

.pl-mq {
color: #008080;
}

.pl-mi {
color: #333;
font-style: italic;
}

.pl-mb {
color: #333;
font-weight: bold;
}

.pl-md,.pl-mdhf {
background-color: #ffecec;
color: #bd2c00;
}

.pl-mdht,.pl-mi1 {
background-color: #eaffea;
color: #55a532;
}

.pl-mdr {
color: #795da3;
font-weight: bold;
}

.pl-mo {
color: #1d3e81;
}
.task-list {
padding-left:10px;
margin-bottom:0;
}

.task-list li {
margin-left: 20px;
}

.task-list-item {
list-style-type:none;
padding-left:10px;
}

.task-list-item label {
font-weight:400;
}

.task-list-item.enabled label {
cursor:pointer;
}

.task-list-item+.task-list-item {
margin-top:3px;
}

.task-list-item-checkbox {
display:inline-block;
margin-left:-20px;
margin-right:3px;
vertical-align:1px;
}
-->

生产服务器使用的是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/

在CentOS上为Docker开启SELinux的更多相关文章

  1. 简单介绍一下在CentOS上安装Docker。

    简单介绍一下在CentOS上安装Docker. 前置条件: 64-bit 系统 kernel 3.10+ 1.检查内核版本,返回的值大于3.10即可. $ uname -r 2.使用 sudo 或 r ...

  2. 在CentOS上使用Docker镜像安装Jenkins

    1.必须先在CentOS上安装Docker,使用以下命名先在Docker Hub上搜索Jenkins镜像 docker search jenkins 2.下载Jenkins镜像,命令如下:(我下载的是 ...

  3. 在CentOS上通过Docker方式安装Redis

    在CentOS上通过Docker方式安装Redis 首先保证已经安装docker. 拖拽redis镜像 docker pull redis 启动redis docker run -p 6379:637 ...

  4. 关于RHEL6下桥网配置的写法(ifcfg-eth0,ifcfg-br0) / 在阿里云的CentOS上安装docker

    Posted on 2011-07-28 16:46 zhousir1991 阅读(1978) 评论(0) 编辑 收藏 以下仅仅是我在做练习的时候下的环境,参照写即可:  [root@desktop2 ...

  5. centos上安装docker

    一 docker安装: 1 首先需要检查linux内核的版本,docker要求linux内核是在3.10之上的, uname -r 2 更新yum源,注意这步应该是管理员权限,如果当前不是管理员,切换 ...

  6. 在Centos上安装docker,部署mysql数据库

    何为docker? Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化. 本机环境 24小时不关机的Centos ...

  7. Docker笔记4:在 CentOS 上安装 Docker

    Docker 是一个开源的应用容器引擎,主要有两个分支,一个是社区免费版(Docker CE),一个是企业版(Docker EE). 第1步:系统环境要求 Docker 支持的 CentOS 版本: ...

  8. 在centos上安装docker

    安装docker 卸载旧版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docke ...

  9. 在RedHat/CentOS下安装Docker(不升级内核)

    由于内核版本问题,最初仅Ubuntu可以较好的支持Docker.不过,由于RedHat系列OS(REHL.CentOS)是目前主流的Linux服务器操作系统,所以令RedHat系列OS支持Docker ...

随机推荐

  1. Toxophily

    Problem Description The recreation center of WHU ACM Team has indoor billiards, Ping Pang, chess and ...

  2. hbase的HQuorumPeer和QuorumPeerMain

    hbase是列式数据库,既可以单机也可以以集群的方式搭建,以集群的方式搭建一般建立在hdfs之上. 分布式的hbase如何启动? 首先启动hadoop,然后就来问题了:zookeeper和hbase的 ...

  3. asp.net core 开发的https证书服务-agilelabs.net

    创建证书-生成CSR(Certificate Sign Request): 填写证书基本信息 接下来我们就可以看到创建的证书签名请求信息(CSR): 为我们刚才创建的CSR签名: 签名的意思是说通过证 ...

  4. How to set up Dynamics CRM 2011 development environment

    Recently I have been starting to learn Microsoft Dynamics CRM 2011 about implement plugin and workfl ...

  5. jquery多种方式实现输入框input输入时的onput,onpropertychange,onchange触发事件及区别

    有关inputs输入内容的事件监听,一般我们会想到下面几个关键词:onput,onpropertychange,onchange onput与onchange的一个区分 onput:该事件在 < ...

  6. 学python+django去北京找工作,靠谱吗?

    有些朋友说,自己的学习能力还可以.倾向于python加框架,如django,python本来就会一些.不太了解北京公司的情况,想知道现学的python+django在北京找到工作有多少可能性. 要想知 ...

  7. [转载] 一致性hash算法释义

    转载自http://www.cnblogs.com/haippy/archive/2011/12/10/2282943.html 一致性Hash算法背景 一致性哈希算法在1997年由麻省理工学院的Ka ...

  8. MySQL中Left Join和Right Join的理解

    虽然之前一直见过两个Join,对于其具体的含义也在参考书上读过,但是一直没有记住.现在换一种方式进行学习,改为实验方式理解. Left Join 测试表: 表结构很简单,test包括两个int字段,t ...

  9. YII2调试 通过日志记录将变量保存到文件

    $log = new \yii\log\FileTarget(); $content=var_export($menu,"true");//将数组或对象转换字符串格式   $con ...

  10. java oop详解

    近日来重温了一下java oop的知识.加深了对面向对象的理解.尤其时继承方面.故写一篇博客.记录一下自己的想法和心得 1.面向对象主要分为三大点(封装,继承,多态) 封装的思想促进了类的形成.相比于 ...