TT Lab
开始
学习 学习路径 课程

LFCS — Linux 基金会认证系统管理员

当前值与永久值住在不同地方 — SELinux、firewalld、sudoers、ACL、sshd

在 TT Lab 中继续学习

一句话总结

RHEL 系列的管理工具几乎都把“当前”和“永久”分开处理。setsebool 与 -P、chcon 与 semanage fcontext、firewalld 的 runtime 与 permanent。而生效值不是由文件,而是由工具告知——getsebool、firewall-cmd --list-all、sudo -l -U、getfacl、sshd -T。本模块的实验在 AlmaLinux 9 VM 上对这两者都评分。

为什么需要它

LFCS 的 Operations 领域明确要求“用 SELinux 管理访问”,Networking 领域则要求数据包过滤和 OpenSSH 配置。Pod 中既没有 SELinux 也没有 firewalld,所以这些内容只在模拟考试中一带而过。前面的 RHCE 实验用 Ansible 做了同样的事,但在考场上你手里有的是 semanage 和 firewall-cmd。

这台 VM 处于 Enforcing 状态。因此,如果漏掉端口上下文,httpd 就无法绑定 8081,真的起不来;如果在 firewalld 中漏掉 permanent,一执行 --reload 规则就会消失。评分代理通过 8899/tcp 进入,所以一旦删除该端口或改变默认 zone,评分就无法到达 VM——这正是在 RHCE 实验中实测到的陷阱。

工作原理

SELinux 是叠加在 DAC 之上的一层。 如 RHEL 9 Using SELinux 所述,进程和文件上附带的上下文(类型)必须与策略中的允许规则匹配,才能访问。即使是 root 也不例外。布尔值是无需重新构建策略就能开关的开关,而 setsebool(8) 的 -P 如果缺失,现在会改变,重启后又会恢复原样。semanage boolean -l -C 只显示与默认值相比被修改过的部分,(on , on) 表示(当前,永久)。

文件上下文存在于两处:文件的 xattr(当前值)和策略的规则列表(本应具有的值)。chcon 只修改前者,semanage-fcontext(8) 修改后者。如果不修改后者,执行一次 restorecon 就会恢复原样。所以顺序是先添加规则,再执行 restorecon -R。端口也有类型。如果没有用 semanage-port(8) 把 8081 加入 http_port_t,httpd_t 就无法打开这个端口,而拒绝记录会留在 ausearch -m avc 中。

firewalld 有 zone,也有两种状态。 在 firewall-cmd 中,加上 --permanent 只作用于配置文件,不加则只作用于当前正在运行的规则。--reload 会把 permanent 重新读取为 runtime,所以只放进 runtime 的内容在此时会消失。firewalld.zone(5) 中的 zone 是按来源或接口设置不同允许列表的单位,新的 zone 只能以 permanent 方式创建,reload 之后才会出现在 runtime 中。无法仅用服务、端口表达的条件(来源 + 端口 + 动作),用一行 rich rule 来写。

sudoers 用片段文件,先检查再保存。 sudoers(5) 中的 %ops ALL=(ALL) NOPASSWD: /usr/bin/systemctl 表示“ops 组可以在任何地方、以任何用户身份、无需密码,只执行 systemctl”。放在 /etc/sudoers.d/ 中,软件包更新就不会覆盖它,而且即使某个片段有错,也只会过滤掉那个片段。如果带着语法错误放着不管,整个 sudo 都会拒绝工作,所以要先用 visudo -cf 检查。结果由 sudo -l -U deploy 告知。

登录环境和资源限制在登录的瞬间生效。 /etc/profile.d/*.sh 是登录 shell 在经过 /etc/profile 时读取的片段,没有 export 的话,变量只在该 shell 内部可见,不会传给 shell 启动的程序。limits.conf(5) 的四个字段(对象、soft/hard、项目、值)由 pam_limits 在打开会话时应用,所以在已经打开的 shell 中查看 ulimit 是不会变化的。组写作 @ops。

ACL 是九个权限位之外的权限。 用所有者、组、其他人无法表达“再多加这一个用户”。setfacl(1) 的 -m u:deploy:rwx 就能做到,而 -d 的默认 ACL 会被目录中以后创建的内容继承。一旦设置了 ACL,ls -l 中组的位置显示的不是真正的组权限,而是 mask——对 750 设置 ACL 后看起来像 770,这是正常的。mask 会裁剪生效的权限,所以要查看 getfacl 的 #effective。

sshd 使用先读到的值。 按照 sshd_config(5),同一个关键字出现多次时,第一个值生效。RHEL 9 的 sshd_config 第一行是 Include /etc/ssh/sshd_config.d/*.conf,所以 drop-in 会压过正文。sshd -t 检查语法,sshd -T 则给出展开了所有 Include 和 Match 之后的生效值。

dnf 是事务。 dnf 命令参考中的 history 以事务为单位记录历史,并用 undo 回退。让软件包不参与升级的方法有两种。versionlock 插件把软件包固定在当前版本,dnf.conf 的 exclude= 则是直接把它从候选项中剔除。它与 Ubuntu 的 apt-mark hold 处于同样的位置。

在现场相遇的样子

“httpd 起不来,配置是对的”在 RHEL 上十有八九是 SELinux。如果 journalctl -u httpd 中出现 Permission denied,就查看 ausearch -m avc -ts recent。如果是端口问题,答案是 semanage port;如果是文件问题,答案是 semanage fcontext + restorecon,而 setenforce 0 不是答案。

“开了防火墙,重启后又关上了”,是漏掉了 --permanent;“开了却现在不生效”,是只加了 --permanent 而没有执行 --reload。这是同一个工具的两副面孔,所以症状恰恰相反。

“给了 ACL 却写不进去”要查看 mask。像 chmod g-w 这样的组权限修改会同时削减 mask,使 user:deploy:rwx 的生效值降为 r-x。getfacl 会以 #effective:r-x 告知。

下一项实验要做什么

保存 sestatus + setsebool -P → /srv/web 的 fcontext 规则 + restorecon + 把 8081 设为 http_port_t + httpd 响应 → 在 public zone 中同时于 runtime 和 permanent 两侧添加 http 和 8081(保留 8899)→ zone lab + 来源 + rich rule → ops/deploy + sudoers.d/ops(0440,visudo -cf)→ profile.d 的 export + limits.d → /srv/web/upload 的 ACL 与默认 ACL → sshd drop-in + sshd -T → 安装 tree、锁定、dnf history。评分器会用 getsebool、semanage … -C、firewall-cmd --permanent、su - deploy、sshd -T 查看生效值。只有写在文件里的内容与工具所说的一致时才能通过。