SELinux 详解

Linux ginotang 1949℃ 0评论

什么是SELinux

SELinux是一个权限控制系统,全称Security-Enhanced Linux。关于权限的控制,前面的文章已经介绍过,分别是基于传统文件系统的权限控制和基于ACL的权限控制,这两者控制的是用户对系统资源的权限,即面向的是系统中的用户;而SELinux面向的是应用程序,控制的是应用程序对系统资源的权限:即应用程序可以访问系统哪些目录或者文件。

SELinux主要控制对外提供服务(通常是网络服务)的程序,例如ftp、apache(nginx)等等,对于这些服务的进程,出于安全考虑,它们只能访问具有特定属性的资源,这是SELinux限制的。

各版本Linux的SELinux安装情况

SELinux对于Linux系统并不是标配的,它是一个可选组件。也就是说,不是每种Linux发行版都默认安装有SELinux,从目前的情况来看,一般基于RPM包管理的发行版例如:RedHat、Centos、Fedora都预装SELinux,而基于deb包管理的发行版例如:Ubuntu、Debian都没有安装。

检查系统是否安装了SELinux

getenforce命令

在终端中输入getenforce命令,无论它返回什么值,只要这个命令可以正常运行,就说明系统中安装了SELinux组件,相反,如果运行getenforce命令的时候提示没有这个命令,则表示没有安装SELinux组件。

SELinux的三种模式

假设系统中安装了SELinux,那么运行getenforce命令可能的返回值如下:

  • enforcing
  • permissive
  • disabled

enforcing:强制模式,程序被SELinux严格控制,enforcing模式是SELinux的核心模式。

permissive:宽容模式,跟踪程序的行为,如果程序访问的资源超出SELinux的限制,则给出警告,并使用日志记录,但放行。

disabled:完全禁用SELinux

在讨论SELinux的时候,基本上使用的都是enforcing模式。

setenforce命令

setenforce命令用于切换SELinux的工作模式,但紧限于enforcing和permissive模式,disabled模式只能通过配置文件设置,不能通过setenforce命令禁用SELinux。

setenforce命令的参数只有1个,它是数字1或者0,1对应enforcing,0对应permissive。这个命令只能通过管理员权限运行

SELinux的组成部分

我们说,SELinux是限制应用程序对系统资源(通常是文件或者目录)的使用,那么,最基本的组成必然是:应用程序、系统资源和权限,这三者,都有一个专业的术语:

  • Subject:即应用程序,通常是指进程或者线程
  • Object:指系统资源,除了常见的文件和目录,其他的例如端口、sockets、IO设备等都属于资源的范围
  • Policy:即权限,Policy由多个rule(规则)组成

安全上下文(Security Context)

在Subject和Object中,都有一个安全上下文,用于保存它们的权限标识(但Subject和Object中的上下文并不一样),这个安全上下文存在于文件的inode中,就像传统文件的权限(rwx)一样。安全上下文是给操作系统使用的,通过对比Subject和Object的安全上下文,如果匹配,Subject就拥有操作Object的权限。

查看Object(文件)的安全上下文

使用ls的时候,通过参数-l就可以查看文件的传统权限(rwx),同样,ls命令也提供了检查文件安全上下文的参数,它就是-Z。

unconfined_u:object_r:admin_home_t:s0 就是文件的安全上下文,由4个部分构成,但是第4个部分是可选的,因此,重要的是前3个部分。

分别是:

  • 用户(user)
  • 角色(role)
  • 类型(type)

用户通常分为两种,他们是:

  • 受SELinux限制的用户(system_u),一般是系统内建用户
  • 还没有被SELinux限制的用户(unconfined_u),一般是后期创建的用户

角色用来标识资源的类型,也可以分成两种,他们是:

  • 文件(object_r)      说明资源是一种文件,例如普通文件、sockets或者管道
  • 程序 (system_r)    说明该资源是一个进程

其中类型(type)是三个之中最重要的一列,当type作用于进程的时候,叫做domain type,而当type作用于资源的时候,叫做object type。操作系统正是通过对比domain type和object type来匹配权限的。

查看Subject(进程)的安全上下文

ls通过-Z参数检查文件的Security Context,ps命令也提供了-Z参数来列出进程的Security Context。

第一列就是进程的安全上下文,它的组成列和文件的上下文基本匹配。

Policy、Rule和Type Environment

Policy由一系列Rule组成,Rule决定了一个进程是否能够访问指定的资源。Policy、Rule和上面的Security Context共同构成Type Environment。

那么Rule是什么,它是如何确立进程和资源之间的关系的呢?下面一步步来解释,以nginx进程为例子,它的domain type是httpd_t,常见的Rule格式如下:

意思是:允许类型为httpd_t的进程对类型为httpd_config_t的文件(file)进行ioctl、read、open等操作

一个Rule由5个部分组成,它们是:

  • Rule类型(允许、禁止等)
  • domain type(进程的类型)
  • object type(资源的类型)
  • class(用于标识资源是什么,一个文件,还是文件夹或者其他)
  • permission(具体权限,多个权限使用大括号括起来,分隔符为空格)

上面的例子列出的是allow类型的规则,除此之外,还有其他3种,也就是说,规则一共有4种,它们是:

  • allow
  • dontaudit
  • auditallow
  • neverallow

显然,我们常用的还是allow规则。讲到这里,基本上就可以理解SELinux的工作原理,结合下图,理解起来会更简单:

Conditional Policy

Conditional Policy,即条件化策略:根据用户设置的条件来决定应该使用什么规则。

SELinux预设了很多条件化策略,例如和提供web服务相关的httpd_enable_homedirs策略。如果想知道系统中都有什么条件化策略,可以使用下面的命令:

条件化策略只是一个布尔值,非真即假,那么改变这个值,实际上改变了什么?依然使用httpd_enable_homedirs作为例子:

当运行命令之后,会出现一大堆的规则,上面只摘录其中的一部分,规则开头的两个字母例如DT,表示当前规则的状态DT表示Disable True,这是在httpd_enable_homedirs在off状态下的情况。

getsebool和setsebool命令

如果想查看一个条件化策略的布尔值,可以使用getsebool命令,而设置它的值,使用setsebool。

那么,我们更改了它的值,当它在on状态下,受影响的规则是哪些呢,依然可以使用和上面同样的命令查看:

会发现,一部分规则开头的DT(Disable True)变成了ET(Enable True),改变的部分就是条件化策略影响的规则。

相关命令

通过这些命令,可以方便地操作SELinux,它们是seinfo、sestatu、semanage、sesearch、chon、restorecon、getsebool和setsebool。上面的文字中已经涉及到相关命令的简单使用,详细的可以参照man page。

seinfo

没有参数的seinfo命令列出SELinux中的相关信息的数量

通过相关参数,可以单独查询上表中的指定信息,例如:seinfo -c,列出系统中所有的classes数量,即上面的94。

sestatus

不带参数的sestatus用于显示当前SELinux的状态信息

也可以查询指定信息,例如条件策略的状态:sestatus -b

什么时候使用SELinux

前面我们说过,SELinux一般用于控制提供网络服务或者系统服务的进程的权限,从而使运行linux系统的服务器更加安全。当SELinux正常运行的时候,这些进程就已经受SELinux的约束,因此我们多数情况下是被动使用SELinux,也可以说,认识和学习SELinux,多数情况下都是为了在解决问题的时候提供多一个参考。

一个完整的例子

假设有一台提供web服务的服务器,使用的程序是nginx,该服务器原本就运行了一个网站程序,存放于/usr/share/nginx/html下面,现在希望新增一个网站。我是通过下面的步骤创建这个新网站的:

  • 在/usr/share/nginx 目录下创建一个新文件夹名为newsite,用于存放新网站

  • 在用户的家目录创建一个新的网站配置文件名为newsite.conf

  • 把上一步创建好的newsite.conf配置文件复制到/etc/nginx/conf.d目录中,并配置好相关信息

准备好后,通过systemctl restart nginx重启服务,发现nginx重启失败,只留下一段错误信息:

意思是nginx重启失败,通过journalctl -xe命令可以查看相关错误信息,于是我运行journalctl -xe命令,发现了用红色高亮的错误信息:

很明显是SELinux限制了nginx进程访问该配置文件,从而造成了这样的错误。

追踪问题

首先要知道,SELinux禁止了nginx访问这个文件,说明文件的Security Context肯定不正常,那么就应该用ls -lZ命令查看文件的Security Context信息

default.conf是默认的配置文件,newsite.conf是我们添加的,通过对比发现,newsite.conf的type类型是admin_home_t,而default.conf是httpd_config_t,我们猜测nginx要求的type类型应该是httpd_config_t才对,但得到的却是admin_home_t。

问题的产生原因

那么为什么newsite.conf的type类型是admin_home_t呢?实际上,在上面的3个步骤中,从第2个开始就已经会造成这个问题。原因是文件的type类型具有继承性,我们在什么文件夹中创建文件,该文件的type就会继承自父文件夹。

还记得我们是在root的家目录下创建的newsite.conf吗?所以它的类型是admin_home_t。

解决问题

知道问题的原因,就可以着手解决问题了,只要把newsite.conf文件的type改为httpd_config_t就可以了。可以使用chcon(Change Context)命令

除了chon命令外,还可以使用restorecon命名,这个命令更加简单,而且可以递归处理文件夹下的所有文件。

-Rv参数后面有一个点(.)的,即当前文件夹。

延伸阅读

http://linux.vbird.org/linux_basic/0440processcontrol.php#selinux

https://selinuxproject.org/page/NewUsers

https://wiki.gentoo.org/wiki/SELinux

https://wiki.gentoo.org/wiki/SELinux/Tutorials

转载请注明:Pure nonsense » SELinux 详解

喜欢 (0)
0 0 投票数
文章评分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x
()
x