selinux简介

selinux概念

由美国国家安全局(NSA)和SCC联合开发的,强制访问控制的安全模块。2000年以GPL开源,linux2.6内核后集成在内核里。

不启用selinux时,访问模式叫:DAC(discretionary access control)自由访问控制

在DAC模式下的进程能够访问哪些资源是由启用这个进程的用户身份决定的,这个用户能访问的,这个进程都可以访问。

启用selinux时,访问模式叫:MAC(Mandatory access control)强制访问控制

在MAC模式下的进程能够访问哪些资源是由selinux设定的。

selinux的工作类型

selinux的工作类型定义在/etc/selinux/config文件中

centos7:

# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

centos6:

# cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted
  • targeted:保护常见的网络服务(默认工作类型)
  • minimum:只对选择的服务保护

selinux安全上下文

  • 传统linux,一切皆文件,由用户,组,权限控制访问

  • 在selinux中,一切皆对象(object),由存放在inode的扩展属性域的安全元素所访问控制。

    查看inode的扩展属性域的命令:ls -Zps -Z

    这些属性起名叫标签或context。

    ls:

    # ls -lZ
    -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg
    -rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg
    -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 linux-3.10.67.tar.xz
    drwxr-xr-x. root root unconfined_u:object_r:admin_home_t:s0 scripts

    ps:

    # ps auxZ
    LABEL                           USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    system_u:system_r:init_t:s0     root         1  0.0  0.1 193788  6904 ?        Ss   05:25   0:06 /usr/lib/systemd/systemd --swit
    system_u:system_r:kernel_t:s0   root         2  0.0  0.0      0     0 ?        S    05:25   0:00 [kthreadd]
    system_u:system_r:kernel_t:s0   root         3  0.0  0.0      0     0 ?        S    05:25   0:00 [ksoftirqd/0]
  • 所以文件,端口,进程都具备安全标签:安全上下文(security context)

  • 安全上下位由5个元素组成:user:role:type:sensitivity:category

    • user:登录系统的用户类型
      • root:root用户
      • user_u:普通用户
      • system_u:系统用户
      • unconfined_t:自由进程/文件。多数本地进程都属于此。
    • role:定位文件,进程和用户的用途。文件:object_r;进程和用户:system_r
    • type:数据类型。最常用的属性,target策略就是根据type的值,控制可以访问/不可访问哪些资源。但是有个问题,每个资源只有唯一的type,当有多个别的东西想访问同一个资源的时候就麻烦了,就要修改type成public_content_t(只读,不可以修改这个资源);public_content_rw_t(读写)
    • sensitivity:默认是s0
    • category:target工作类型下,不使用。
  • 标签/context分实际的标签和期望标签

    • 实际标签:使用ls -Z和ps -Z看到的标签。

    • 期望标签:安装操作系统后,系统给的标签。标签是可以修改的,所以有期望标签,修改了某个文件的标签后,这个文件的期望标签和实际标签就不一样了。

      查看文件,进程,端口的期望标签:semanage fcontext -l

      # semanage fcontext -l | grep "/var/log/messages"
      /var/log/messages[^/]*                             all files          system_u:object_r:var_log_t:s0
      # ls -Z /var/log/messages
      -rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages

      期望标签存放在:/etc/selinux/targeted/contexts/files/目录

      # ls /etc/selinux/targeted/contexts/files/
      file_contexts           file_contexts.homedirs.bin  file_contexts.subs
      file_contexts.bin       file_contexts.local         file_contexts.subs_dist
      file_contexts.homedirs  file_contexts.local.bin     media

selinux策略

  • object:所以可以读取的对象,包括文件,目录,进程,端口
  • subject:进程
  • 当一个subject要访问object时,selinux执行AVC(access vector cache)检查,在AVC中,subject和object的权限被缓存。
  • 安全策略:定义subject读取object的规则数据库,规则中记录了哪个类型的(type)的subject使用哪个方法读取哪一个object是允许的还是拒绝的,并且定义了哪种行为是允许或拒绝的。

启用selinux

查看selinux是启用还是禁用

# getenforce
Enforcing
[root@localhost ~]# cat /etc/selinux/config
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

enforcing:启用状态

permissive:没启用,但是违反了selinux的规则,只出警告信息而已。

disabled:禁用状态。

  • 临时启用:

    # setenforce 1
    # getenforce
    Enforcing
  • 临时禁用:

    # setenforce 0
    # getenforce
    Permissive

    注意:使用命令setenforce,只能在Enforcing和Permissive间切换。不能从disabled状态切换成Enforcing。

永久修改selinux启用或禁用:修改文件/etc/selinux/config,重启才生效。

禁用后(disabled而不是permissive)创建的文件就没有标签了,

而且【-rw-r--r--】后面没有点,有点就说明有标签。

# sestatus
SELinux status:                 disabled
# setenforce 1
setenforce: SELinux is disabled
# touch temp2
[root@localhost ~]# ls -Z temp2
-rw-r--r-- root root ?                                temp2

从disabled切换到enabled后,在看刚才创建的temp2文件:

有点了,但是type是unlabeled_t

# getenforce
Enforcing
# ls -Z temp2
-rw-r--r--. root root system_u:object_r:unlabeled_t:s0 temp2

查看详细状态信息:

# sestatus
SELinux status:                 enabled
SELinuxfs mount:                /sys/fs/selinux
SELinux root directory:         /etc/selinux
Loaded policy name:             targeted
Current mode:                   permissive//当前是禁用的
Mode from config file:          enforcing//配置文件是启用的
Policy MLS status:              enabled
Policy deny_unknown status:     allowed
Max kernel policy version:      31

定义的策略存放在:SELinuxfs mount /sys/fs/selinux

avc缓存在avc目录。

# ls /sys/fs/selinux/
access    checkreqprot          context       disable           load    null                 policyvers      status
avc       class                 create        enforce           member  policy               reject_unknown  user
booleans  commit_pending_bools  deny_unknown  initial_contexts  mls     policy_capabilities  relabel

安全布尔值存放在:/sys/fs/selinux/booleans

# pwd
/sys/fs/selinux/booleans
[root@localhost booleans]# ll ftp*
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_anon_write
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_connect_all_unreserved
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_connect_db
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_full_access
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_cifs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_fusefs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_nfs
-rw-r--r--. 1 root root 0 Feb 28 16:44 ftpd_use_passive_mode

文件ftpd_anon_write里的内容是2个0。从文件名字可以看出来是ftp的匿名写,值是0,说明不允许匿名写。

# cat ftpd_anon_write
0 0

管理文件安全标签

1,修改标签中的type:chcon-t file

测试标签中type的作用,/var/log/messages文件的标签中的type是var_log_t。

手动使用logger命令,往它里面写东西,发现是可以写进去的。

修改它的type成tmp_t,再用logger写,发现写不进去了。

# ll /var/log/messages -Z
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages
# logger "test  sdf "
# tail -1 /var/log/messages
Feb 29 18:33:32 localhost root: test  sdf
# chcon -t tmp_t /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:tmp_t:s0       /var/log/messages
# logger "test  2222sdf "
# grep "test  2222sdf " /var/log/messages

根据某个文件的标签,修改:chcon --reference f1 f2

把文件f2的标签修改成和文件f1完全一样。

# ll -Z /tmp/website/
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 aa
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html
# chcon --reference /tmp/website/index.html /tmp/website/aa
# ll -Z /tmp/website/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 aa
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html

选项-R:递归修改目录所有的文件

# ls /tmp/website/d1
11  22
# ll /tmp/website/d1/11 -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/11
# ll /tmp/website/d1/22 -Z
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/22
# ll /tmp/website/d1/ -Zd
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/
# chcon -R --reference /var/www/html/ /tmp/website/d1/
# ll /tmp/website/d1/ -Zd
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /tmp/website/d1/
# ll /tmp/website/d1/ -Z
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 11
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 22

2,cp命令和mv命令多标签的影响。

cp命令type会改变。

# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages
# cp /var/log/messages /root/
# ll -Z messages
-rw-------. root root unconfined_u:object_r:admin_home_t:s0 messages

mv命令不改变type

# mv messages /tmp/
# ll /tmp/messages  -Z
-rw-------. root root unconfined_u:object_r:admin_home_t:s0 /tmp/messages

3,修改回原来的type,但是忘了原来的type是啥了怎么办,去看期望(原始)策略是啥。

# semanage fcontext -l | grep "/var/log/message"
/var/log/messages[^/]*       all files       system_u:object_r:var_log_t:s0

还有一种更简单的方法:restorecon

# chcon -t tmp_t /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:tmp_t:s0       /var/log/messages
# restorecon /var/log/messages
# ll -Z /var/log/messages
-rw-------. root root system_u:object_r:var_log_t:s0   /var/log/messages

把/var/log/messages回复成原来的标签后,有可能还log还是写不进去,这时就要重启服务了。systemctl rsyslog restart

4,修改httpd的默认根目录,导致selinux标签不对,网页文件无法访问。

  • 修改httpd的配置文件/etc/httpd/conf/httpd.conf,把服务的目录修改成/tmp/website/

    # ll -Z /tmp/website/ -d
    drwxr-xr-x. root root unconfined_u:object_r:user_tmp_t:s0 /tmp/website/

    type是user_tmp_t

  • 在/tmp/website/建立index.html文件

    # ll -Z /tmp/website/
    -rw-r--r--. root root unconfined_u:object_r:user_tmp_t:s0 index.html

    type是user_tmp_t

  • 启动httpd

  • 在浏览器访问index.html

  • 结果是访问不到

原因:/tmp/website/index.html的标签的type不符合selinux对httpd的要求,所以httpd进程无法访问它。

httpd能够访问的标签是:httpd_sys_content_t。

而/tmp/website/index.html文件的type是user_tmp_t,所以httpd不可以访问它,被selinux给挡住了。

# ll -Zd /var/www/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /var/www/

解决办法:

1,安装桌面小程序,能够把selinux相关的信息显示出来。(不安装也无所谓)

2,添加/tmp/website/目录的期望(默认)策略,到selinux。

添加选项:-a

指明type:-t

/tmp/website(/.*)?:正则表达式/tmp/website目录自身和目录下的所有文件的意思。

# semanage fcontext -a -t httpd_sys_content_t "/tmp/website(/.*)?"
# semanage fcontext -l | grep "/tmp/website"
tmp/website(/.*)?                                  all files          system_u:object_r:httpd_sys_content_t:s0

3,由于/tmp/website/有了期望策略,所以恢复/tmp/website/的标签成,默认标签。

选项-R:递归修改目录下的所有文件。

# restorecon -R /tmp/website/
# ll -Zd /tmp/website/
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 /tmp/website/
# ll -Z /tmp/website/
-rw-r--r--. root root system_u:object_r:httpd_sys_content_t:s0 index.html

4,重启httpd

5,当不想让/tmp/website/是httpd的根目录了,删除它在selinux里的期望策略

删除选项:-d

# semanage fcontext -d -t httpd_sys_content_t "/tmp/website(/.*)?"

管理端口标签

1,查看端口期望(默认)策略:

http协议的端口的期望(默认)策略:80, 81, 443, 488, 8008, 8009, 8443, 9000是可以使用的。

所以不能把其他的端口用于http服务。

# semanage port -l
SELinux Port Type              Proto    Port Number

afs3_callback_port_t           tcp      7001
afs3_callback_port_t           udp      7001
# semanage port -l | grep http
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

2,添加端口到默认策略

选项-a:添加

选项-t:指定type

选项-p:指定传输层的协议(tcp或udp)类型

# semanage port -a -t http_port_t -p tcp 9932
[root@localhost ~]# semanage port -l | grep "^http_port_t"
http_port_t          tcp      9932, 80, 81, 443, 488, 8008, 8009, 8443, 9000

3,从默认策略里删除端口

# semanage port -d -t http_port_t -p tcp 9932
# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000

4,把端口策略里的某个端口,移动到另一个策略

让9000端口也能用于ssh服务。

# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443, 9000
# semanage port -m -t ssh_port_t -p tcp 9000
# semanage port -l | grep "^ssh_port_t"
ssh_port_t                     tcp      9000, 22
# semanage port -l | grep "^http_port_t"
http_port_t                    tcp      80, 81, 443, 488, 8008, 8009, 8443

管理selinux布尔值开关

布尔值的作用:细化控制某个服务里的某个小功能是否可以使用。

1,查看布尔值

State:是当前的状态(内存中的)

Default:是默认值(本地磁盘存储的)

# semanage boolean -l
SELinux boolean                State  Default Description

privoxy_connect_any            (on   ,   on)  Allow privoxy to connect any
smartmon_3ware                 (off  ,  off)  Allow smartmon to 3ware

比如:

httpd_enable_cgi:控制httpd的cgi功能是否可用。

httpd_enable_homedirs:控制httpd是否可以访问家目录。

# semanage boolean -l | grep httpd_enable
httpd_enable_cgi               (on   ,   on)  Allow httpd to enable cgi
httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs

另一种命令:getsebool

选项-a:查看全部布尔值

# getsebool -a | grep httpd_use
httpd_use_cifs --> off
httpd_use_fusefs --> off

2,修改布尔值:setsebool

只修改当前状态(重启后,恢复成default):

# setsebool httpd_enable_homedirs=on
# semanage boolean -l | grep httpd_enable
httpd_enable_cgi               (on   ,   on)  Allow httpd to enable cgi
httpd_enable_homedirs          (on   ,  off)  Allow httpd to enable homedirs
httpd_enable_ftp_server        (off  ,  off)  Allow httpd to enable ftp server

既修改当前状态,也修改default状态:

# semanage boolean -l | grep httpd_enable
httpd_enable_homedirs          (off  ,  off)  Allow httpd to enable homedirs
# setsebool -P httpd_enable_homedirs=on
# semanage boolean -l | grep httpd_enable
httpd_enable_homedirs          (on   ,   on)  Allow httpd to enable homedirs

3,查看都修改过哪些布尔值

# semanage boolean -l -C
SELinux boolean                State  Default Description

httpd_enable_homedirs          (on   ,   on)  Allow httpd to enable homedirs

管理日志

日志工具: yum install -y setroubleshoot。有图形界面。

使用下面命令启动图形界面:

# sealert

1,查看由selinux的限制导致的服务不好用的日志,日志文件:/var/log/message

由selinux的限制导致的服务不好用的日志的特点是有:setroubleshoot字样,并告诉使用sealert命令去查看详细的日志。选项-l后面的串是这条日志的标识。

Mar  1 00:04:05 localhost python: SELinux is preventing in 。。。。。。。。
sealert -l 0d882054-5ff7-4693-bf09-7b02f763df6c

使用sealert查看:

# sealert -l 0d882054-5ff7-4693-bf09-7b02f763df6c

使用sealert输出的日志是保存在文件: /var/log/audit/audit.log

2,整理/var/log/audit/audit.log文件,输出可读的格式

# sealert -a /var/log/audit/audit.log

查看selinux帮助

安装selinux帮助文档:

# yum install selinux-policy-doc

查看与selinux相关的帮助文档有哪些:

# man -k _selinux

如果没有显示出来,说明没有更新man的数据库,使用下面的命令更新:

  • centos6:makewhatis
  • centos7:mandb

查看与ftp相关的selinux帮助:

# man 8 ftpd_selinux

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854