注意:

在 Oracle Linux 上使用 SELinux

简介

SELinux 是一组内核模式和用户空间工具,提供另一层系统安全性、精确的访问控制、系统范围的管理员定义的策略以及改进的权限升级攻击缓解。

本教程将指导您使用这些用户空间工具来帮助系统在实施模式下运行。

目标

在此实验室中,您将学习:

先决条件

设置实验室环境

注意:使用免费实验室环境时,请参见 Oracle Linux Lab Basics 了解连接和其他使用说明。

创建用户

其他用户允许测试此实验室稍后对 SELinux 用户的分配。

  1. 如果尚未连接,请打开一个终端并通过 ssh 连接到 ol8-server 系统。

    ssh oracle@<ip_address_of_ol8-server>
    
  2. 创建用户并设置密码。

    sudo useradd -u 8000 ralph
    echo "ralph:oracle" | sudo chpasswd
    
  3. 允许 SSH 连接。

    oracle 用户帐户复制 SSH 密钥。

    sudo mkdir /home/ralph/.ssh
    sudo cp /home/oracle/.ssh/authorized_keys /home/ralph/.ssh/authorized_keys
    sudo chown -R ralph:ralph /home/ralph/.ssh
    sudo chmod 700 /home/ralph/.ssh
    sudo chmod 600 /home/ralph/.ssh/authorized_keys
    
  4. 打开新终端并验证 SSH 连接是否正常工作。

    ssh ralph@<ip_address_of_ol8-server>
    

    然后 exit 会话,并关闭终端窗口。

SELinux 模式和状态

默认情况下,Oracle Linux 安装 SELinux 并以 Enforcing 模式运行。

  1. 通过检查 SELinux 模式进行确认。

    它应设置为 Enforcing

    getenforce
    
  2. 检查 SELinux 状态和模式。

    sestatus
    

    sestatus 命令输出显示 SELinux 状态、策略和模式。

    输出示例:

    SELinux status:                 enabled
    SELinuxfs mount:                /sys/fs/selinux
    SELinux root directory:         /etc/selinux
    Loaded policy name:             targeted
    Current mode:                   enforcing
    Mode from config file:          enforcing
    Policy MLS status:              enabled
    Policy deny_unknown status:     allowed
    Memory protection checking:     actual (secure)
    Max kernel policy version:      31
    

SELinux 安全标签

SELinux 下的每个进程和系统资源都有一个称为 SELinux 上下文的安全标签。SELinux 上下文(也称为 SELinux 标签)侧重于安全属性,并确保以一致的方式引用 SELinux 策略中的对象。

  1. 显示文件的 SELinux 安全标签。

    ls -ldZ /etc/passwd
    

    输出示例:

    -rw-r--r--. 1 root root system_u:object_r:passwd_file_t:s0 1892 Apr 13 14:39 /etc/passwd
    

    带有 -Z 选项的 ls 输出显示四个 SELinux 属性字段:

    • 用户:system_u
    • 角色:object_r
    • 类型:passwd_file_t
    • 安全:s0

    其中最重要的是 SELinux 类型,因为大多数 SELinux targeted 策略规则利用 SELinux 类型定义一个对象(例如进程)和另一个对象(例如文件)之间允许的交互。

  2. 获取可用 SELinux 类型的列表。

    seinfo --type | head
    
    • head 命令将输出限制为仅前十个输出行。

    完整输出显示许多不同的命令和服务(例如 sshsshd)存在 SELinux 类型。

  3. 获取特定 SELinux 类型的列表。

    grep 将输出限制为仅包含单词 ssh 的类型。

    seinfo -t | grep ssh
    
  4. 获取特定进程和配置文件的安全 Lables 的列表。

    使用 ps 获取进程的安全标签。

    ps -efZ | grep sshd
    

    输出示例:

    system_u:system_r:sshd_t:s0-s0:c0.c1023 root 2535      1  0 14:37 ?        00:00:00 /usr/sbin/sshd -D
    system_u:system_r:sshd_t:s0-s0:c0.c1023 root 18514  2535  0 15:21 ?        00:00:00 sshd: oracle [priv]
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 18528 18514  0 15:21 ? 00:00:00 sshd: oracle@pts/0
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 oracle 23611 18529  0 15:41 pts/0 00:00:00 grep --color=auto sshd
    

    使用 ls 获取配置文件的安全标签。

    ls -lZ /etc/ssh/
    

    输出示例:

    total 600
    -rw-r--r--. 1 root root     system_u:object_r:etc_t:s0      577388 Oct  9  2021 moduli
    -rw-r--r--. 1 root root     system_u:object_r:etc_t:s0        1770 Oct  9  2021 ssh_config
    drwxr-xr-x. 2 root root     system_u:object_r:etc_t:s0          28 Feb 18 08:51 ssh_config.d
    -rw-------. 1 root root     system_u:object_r:etc_t:s0        4268 Apr 13 14:37 sshd_config
    -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0    537 Apr 13 14:37 ssh_host_ecdsa_key
    -rw-r--r--. 1 root root     system_u:object_r:sshd_key_t:s0    197 Apr 13 14:37 ssh_host_ecdsa_key.pub
    -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0    432 Apr 13 14:37 ssh_host_ed25519_key
    -rw-r--r--. 1 root root     system_u:object_r:sshd_key_t:s0    117 Apr 13 14:37 ssh_host_ed25519_key.pub
    -rw-r-----. 1 root ssh_keys system_u:object_r:sshd_key_t:s0   2635 Apr 13 14:37 ssh_host_rsa_key
    -rw-r--r--. 1 root root     system_u:object_r:sshd_key_t:s0    589 Apr 13 14:37 ssh_host_rsa_key.pub
    

    sshd 守护进程使用 sshd_t 类型。因此,在 targeted 策略中,应该有 sshd_t SELinux 属性的规则,该规则规定具有 sshd_t 的对象可以访问具有以下安全属性的任何对象:

    • etc_t
    • sshd_key_t
    • ...

    同样,如果要检查 ssh 命令,我们将能够确定 ssh_home_tssh_exec_t 之间的类似映射。

    ls -lZ /usr/bin/ssh
    

    输出示例:

    -rwxr-xr-x. 1 root root system_u:object_r:ssh_exec_t:s0 775720 Oct  9  2021 /usr/bin/ssh
    
    ls -lZ ~/.ssh
    

    输出示例:

    total 4
    -rw-------. 1 oracle oracle unconfined_u:object_r:ssh_home_t:s0 404 Apr 13 14:39 authorized_keys
    
  5. 获取用户的安全上下文。

    其他相关的上下文类型是 unconfined_t。具有此 SELinux 类型的对象(例如用户)具有不受限制的访问权限。此级别的访问意味着 SELinux 不会限制用户可以执行的操作,并且仅会通过 DAC 权限阻止用户执行这些操作。DAC(自由访问控制)是传统用户、组和其他权限处理的安全策略。

    例如,显示 oracle 用户的安全属性。

    whoami
    
    id -Z
    

    输出示例:

    [oracle@ol-selinux ~]$ whoami
    oracle
    [oracle@ol-selinux ~]$ id -Z
    unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
    

SELinux 和网络服务

SELinux 跟踪其内部数据库中最常用的基于网络的软件包的配置。通过此跟踪,SELinux 可以保护系统免受攻击的面向外部的服务。

因此,如果将软件配置为使用非标准目录或端口,SELinux 可能会阻止服务工作。

为了显示 SELinux 对系统标准端口的了解,我们需要使用 SELinux 实用程序 semanage。默认情况下,Oracle Linux 不安装该实用程序,因此请安装它。

  1. 确定提供该实用程序的软件包。

    sudo dnf whatprovides semanage
    

    结果显示 /usr/sbin/semanagepolicycoreutils-python-utils 软件包的一部分。

  2. 安装软件包和任何相关项。

    sudo dnf install -y policycoreutils-python-utils
    
  3. 检查 SELinux 允许的 sshd 端口。

    sudo semanage port -l | grep ssh
    

    输出示例:

    ssh_port_t                     tcp      22
    
  4. 将新端口添加到 SELinux 策略。

    如果要将 SSH 守护进程侦听的端口更改为 2222 或更改其存储默认配置的端口,则需要通知 SELinux 我们希望这些更改。我们可以再次使用 semanage 通过添加新的策略规则来允许定制端口。

    sudo sudo semanage port -a -t ssh_port_t -p tcp 2222
    
    • -a 选项添加类型为 -t 的新策略规则。
  5. 检查 SELinux 现在允许的端口。

    sudo semanage port -l | grep ssh
    

    输出示例:

    ssh_port_t                     tcp      2222, 22
    
  6. 修改 SELinux 策略中的端口。

    假设我们要将 SSH 守护进程映射到端口 443。重复同一命令,但会出现错误消息,指出端口已在使用。

    sudo semanage port -a -t ssh_port_t -p tcp 443
    

    输出示例:

    ValueError: Port tcp/443 already defined
    

    出现错误是因为我们尝试将端口 443 从 http_port_t 类型切换到 ssh_port_t 类型。为此,请使用 -m 选项修改端口对象记录。

    sudo semanage port -m -t ssh_port_t -p tcp 443
    

SELinux 用户

每个 Linux 用户都使用 SELinux 策略映射到 SELinux 用户。此方法允许 Linux 用户根据其 SELinux 用户映射继承限制。Oracle Linux 中的默认映射是 __default__ 登录,它映射到 SELinux unconfined_u 用户。

  1. 获取所有当前 Linux 用户映射的列表。

    sudo semanage login -l
    
    • 请注意,oracle 用户未列出,因此映射到 unconfined_u 用户。
  2. 获取 SELinux 用户列表。

    seinfo -u
    
  3. 限制用户的操作。

    虽然默认 Linux 用户不受约束地运行,但用户的操作可能会根据应用程序 domain 产生限制。domain 是一组具有相同 SELinux 类型的对象。

    如果我们希望阻止用户使用 X 窗口系统 sudo 和网络,该怎么办?

    SELinux 有这样的用户。

    要验证这一点,我们需要另一个 Linux 用户。我们将使用用户 ralph

    1. 创建到 guest_u 的新映射。

      sudo semanage login -a -s guest_u ralph
      
    2. 验证映射。

      sudo semanage login -l
      
    3. 测试 ralph 无法访问网络。

      guest_u 继承的限制仅在登录后发生,而不是通过执行 sudosu

      打开一个终端,然后以 ralph 用户身份通过 ssh 连接到 ol8-server 系统。

      ssh ralph@<ip_address_of_ol8-server>
      
    4. 检查用户的上下文。

      id; id -Z
      

      输出示例:

      uid=8000(ralph) gid=8000(ralph) groups=8000(ralph) context=guest_u:guest_r:guest_t:s0
      guest_u:guest_r:guest_t:s0
      
    5. 显示用户当前进程的安全上下文:

      ps axZ
      

      输出显示映射到 guest_u 并且可以登录的用户 ralph。但是,ralph 不应能够访问网络。

    6. 使用 ping 测试网络连接。

      ping localhost
      

      输出示例:

      ping: socket: Permission denied
      
    7. 此外,还使用 curl 测试网络。

      curl ifconfig.me
      

      输出示例:

      curl: (6) Could not resolve host: ifconfig.me
      

      该消息指示 curl 无法将 ifconfig.me 的 DNS 名称解析为 IP 地址。DNS 是 Linux 网络服务,需要打开套接字,因此 SELinux guest_u 用户可以阻止它。

    8. 关闭当前终端窗口。

      我们已完成用户 ralph 的测试,因此请关闭该终端窗口。

      exit
      

SELinux 布尔值

SELinux 引导器允许在运行时进行特定的策略更改,而无需知道如何编写 SELinux 策略。Oracle Linux 提供了许多内置的布尔值,或者熟悉 SELinux 策略的管理员可以自己编写。如果实施的策略是可选的,则鼓励管理员将策略编写为布尔值。

  1. 获取布尔值的列表及其含义。

    切换回以 oracle 身份登录的终端,然后运行以下命令。

    sudo semanage boolean -l
    

    输出示例:

    SELinux boolean                State  Default Description
    
    abrt_anon_write                (off  ,  off)  Allow abrt to anon write
    abrt_handle_event              (off  ,  off)  Allow abrt to handle event
    abrt_upload_watch_anon_write   (on   ,   on)  Allow abrt to upload watch anon write
    antivirus_can_scan_system      (off  ,  off)  Allow antivirus to can scan system
    antivirus_use_jit              (off  ,  off)  Allow antivirus to use jit
    auditadm_exec_content          (on   ,   on)  Allow auditadm to exec content
    authlogin_nsswitch_use_ldap    (off  ,  off)  Allow authlogin to nsswitch use ldap
    authlogin_radius               (off  ,  off)  Allow authlogin to radius
    ...
    
    • 输出说明了每个布尔值的作用以及是启用 (on) 还是禁用 (off)。
  2. 只列出布尔值及其状态。

    sudo getsebool -a
    

    输出示例:

    abrt_anon_write --> off
    abrt_handle_event --> off
    abrt_upload_watch_anon_write --> on
    antivirus_can_scan_system --> off
    antivirus_use_jit --> off
    auditadm_exec_content --> on
    authlogin_nsswitch_use_ldap --> off
    authlogin_radius --> off
    authlogin_yubikey --> off
    ...
    
  3. 获取单个布尔值的状态。

    如果布尔名称已知,则将该名称作为参数传递以仅获取该布尔值状态。

    sudo getsebool virt_use_nfs
    
  4. 查询 SELinux 策略以获得布尔值。

    还不知道 SELinux 策略中的布尔值触发器是什么?SELinux 提供了用于查询这些规则的实用程序。

    sesearch -b virt_use_nfs -A
    

    输出示例:

    allow fsdaemon_t autofs_t:dir { getattr open search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:dir { getattr ioctl lock open read search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:dir { getattr open search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:dir { getattr open search }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:file { getattr ioctl lock open read }; [ virt_use_nfs ]:True
    allow fsdaemon_t nfs_t:lnk_file { getattr read }; [ virt_use_nfs ]:True
    ...
    
  5. 查询布尔值是否允许访问。

    关于是否允许基于条件布尔值进行特定访问呢?回答问题:用户 ping 是否允许从用户域 (user_t) 转换到 ping 域 (ping_t)?

    sesearch -s user_t -t ping_t -c process -p transition -AT
    

    输出示例:

    allow user_t ping_t:process transition; [ selinuxuser_ping ]:True
    
    • 如果启用了 user_ping SELinux 布尔值,则允许转换。
  6. 启用布尔值。

    假设我们希望允许 KVM 在 Samba 共享资源上存储映像?还有一个布尔值。

    1. 找到布尔值。

      sudo semanage boolean -l | grep virt | grep samba
      

      输出示例:

      virt_use_samba                 (off  ,  off)  Allow virt to use samba
      
    2. 将布尔值更改为 enabled。

      sudo setsebool virt_use_samba on
      

      或者

      sudo semanage boolean -m --on virt_use_samba
      
    3. 检查当前状态。

      getsebool virt_use_samba
      
    4. 确保更改在重新引导后仍然存在。

      sudo setsebool -P virt_use_samba on
      
  7. 显示本地 SELinux 策略定制。

    知道我们更改了默认设置,我们可以显示这些本地自定义。

    sudo semanage boolean -l -C
    

    输出示例:

    SELinux boolean                State  Default Description
    
    virt_use_samba                 (on   ,   on)  Allow virt to use samba
    
    • 输出显示默认值现在为 on。在使交换机成为永久性交换机并将暂挂值写入磁盘上的策略文件之后,默认值已更改。

SELinux 文件上下文

运行 SELinux 时,所有文件和目录都标有 SELinux 上下文。我们将分析一些用于管理文件系统标签的命令。

一个熟悉的示例是为 Nginx 的文档根目录创建一个新目录。

  1. 创建新目录以及三个文件。

    sudo mkdir -p /web
    sudo touch /web/file{1,2,3}
    
  2. 检查新目录和文件标签。

    ls -lZ /web
    

    输出示例:

    total 0
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
    
    • 新目录的上下文类型和文件为 default_t

    注:新创建的文件和目录会继承其父目录的 SELinux 类型。

  3. 进行临时标签更改。

    作为故障排除或测试的一部分,我们可以暂时更改上下文。

    sudo chcon -R -t httpd_sys_content_t /web/
    
    ls -lZ /web
    
  4. 将标签恢复为默认设置。

    将上下文切换回默认上下文类型。

    sudo restorecon -R -v /web/
    

    输出示例:

    [oracle@ol-selinux ~]$ sudo restorecon -R -v /web/
    Relabeled /web from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
    Relabeled /web/file1 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
    Relabeled /web/file2 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
    Relabeled /web/file3 from unconfined_u:object_r:httpd_sys_content_t:s0 to unconfined_u:object_r:default_t:s0
    [oracle@ol-selinux ~]$ ls -lZ /web
    total 0
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
    
  5. 使标签更改成为永久性更改。

    要使更改成为永久性更改并在重新引导后保留更改,请使用 semanage fcontext 命令。-a 将记录添加到文件 /etc/selinux/targeted/contexts/files/file_contexts.local 中,-t 定义类型。

    sudo semanage fcontext -a -t httpd_sys_content_t "/web(/.*)?"
    

    注:使用 semanage fcontext 更改 SELinux 上下文时,建议使用文件或目录的完整路径,以避免在文件系统重新设置标签之后或在运行 restorecon 之后设置错误标签。

  6. 检查上下文。

    ls -ldZ /web; ls -lZ /web
    

    输出示例:

    [oracle@ol-selinux ~]$ ls -ldZ /web; ls -lZ /web
    drwxr-xr-x. 2 root root unconfined_u:object_r:default_t:s0 45 Apr 14 19:00 /web
    total 0
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file1
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file2
    -rw-r--r--. 1 root root unconfined_u:object_r:default_t:s0 0 Apr 14 19:00 file3
    

    请注意,上下文并没有改变,我们预期。

  7. 显示新创建的文件和目录的上下文。

    sudo semanage fcontext -C -l
    

    输出示例:

    [oracle@ol-selinux ~]$ sudo semanage fcontext -C -l
    SELinux fcontext                                   type               Context
    
    /web(/.*)?                                         all files          system_u:object_r:httpd_sys_content_t:s0 
    
  8. 将更改应用于上下文。

    sudo restorecon -R -v /web
    

    输出示例:

    [oracle@ol-selinux ~]$ sudo restorecon -R -v /web
    Relabeled /web from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    Relabeled /web/file1 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    Relabeled /web/file2 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    Relabeled /web/file3 from unconfined_u:object_r:default_t:s0 to unconfined_u:object_r:httpd_sys_content_t:s0
    
  9. 删除新的 SELinux 上下文。

    sudo semanage fcontext -d "/web(/.*)?"
    
    • 此示例传递创建上下文时使用的正则表达式,并将其置于上下文记录的开头。因为这是一个正则表达式,所以将其括在引号内。
  10. 应用更改并验证返回到 default_t 的上下文。

    sudo restorecon -R -v /web; ls -ldZ /web; ls -lZ /web
    

有关显示的实用程序,请查看 man 页面。然后使用您学到的知识将 SELinux 保持在 Enforcing 模式。

详细信息

请参阅其他相关资源:

更多学习资源

浏览 docs.oracle.com/learn 上的其他实验室,或者在 Oracle Learning YouTube 频道上访问更多免费学习内容。此外,请访问 education.oracle.com/learning-explorer 以成为 Oracle 学习资源管理器。

有关产品文档,请访问 Oracle 帮助中心