上一篇 下一篇 分享链接 返回 返回顶部

CentOS 7.9启用SELinux后,主备服务器如何同步策略并降低切换风险?

发布人:Minchunlin 发布时间:2026-10-03 11:19 阅读量:1

先不要把“启用 SELinux 后切换失败”直接归因于 SELinux 本身。主备服务器真正容易出现的问题,是两台机器的策略版本、semanage 本地配置、策略模块、文件安全上下文或服务端口定义不一致。只要备用机在平时没有按主机状态持续校准,切换时就可能出现服务无法启动、数据目录不可读、监听端口被拒绝等现象。

第一步应先判断主备是否具备“同一套策略、同一套路径、同一套服务角色”的前提。如果系统版本、应用目录和端口都一致,可以采用“相同策略包 + semanage 导出导入 + 自定义模块同步 + 数据标签校验”的方式;如果备用机的目录、服务角色或挂载点不同,则不能直接复制主机配置,而应分别维护对应路径的文件上下文和端口规则。排查顺序应从网络和服务状态开始,再进入 SELinux 策略、文件标签和审计日志,避免在服务根本没有启动时误改策略。

先确认主备是否属于同一策略边界

在两台服务器上分别执行基础检查,先记录结果,不要急于修改配置:

cat /etc/centos-release
uname -r
sestatus
getenforce
rpm -q selinux-policy selinux-policy-targeted policycoreutils policycoreutils-python

重点关注以下条件:

检查项可以直接同步的情况需要单独处理的情况
CentOS 版本两台均为 CentOS 7.9小版本、策略包或关键软件版本不同
SELinux 类型均为 targeted一台为其他策略类型,或一台处于 disabled
应用路径主备使用相同绝对路径主备挂载点、目录结构不同
服务端口服务监听端口和协议一致备用机端口发生变化
自定义策略有可追溯的 .pp 模块文件或构建产物只在主机上临时生成,找不到来源
数据标签复制机制保留 security.selinux 扩展属性数据复制后标签丢失或由不同策略生成

如果主备的应用目录都是 /srv/app,服务端口都是 TCP 8080,且策略类型和策略包版本一致,那么直接同步本地策略配置通常风险较低。如果主机使用 /data/app、备用机使用 /srv/app,则不能只导入主机的文件上下文规则,必须重新定义备用机实际路径对应的上下文。

先做基线和可回滚备份

启用或切换 SELinux 前,应确保能够通过控制台、带外管理或其他独立管理入口登录备用机。否则一旦策略阻断远程登录,网络服务和远程运维可能同时失效。

建议在主机和备用机上分别建立备份目录:

BACKUP="/root/selinux-backup-$(date +%F-%H%M%S)"

install -d -m 0700 "$BACKUP"

cp -a /etc/selinux/config "$BACKUP/"
sestatus > "$BACKUP/sestatus.txt"
getenforce > "$BACKUP/getenforce.txt"
semodule -lfull > "$BACKUP/semodule-full.txt"
getsebool -a | sort > "$BACKUP/getsebool.txt"

semanage export -f "$BACKUP/semanage.export"

sha256sum "$BACKUP"/* > "$BACKUP/SHA256SUMS"

如果提示找不到 semanage,先确认 policycoreutils-python 是否安装:

rpm -q policycoreutils-python
command -v semanage

CentOS 7 中,semanage 通常由 policycoreutils-python 提供。安装缺失软件包前,应确认软件源、维护窗口和本地软件包版本,避免在主备切换前临时引入不同版本的策略工具。

备份的作用不是让两台服务器直接覆盖整个 /etc/selinux 目录,而是保存可审计、可比较、可回滚的策略输入。尤其不要把主机的 /etc/selinux/targeted 目录直接使用 cp 或 rsync 覆盖到备用机,这可能混合不同版本的策略数据库和运行时文件。

同步策略包和 semanage 本地配置

SELinux 的基础策略由软件包提供,主备服务器应尽量保持相同版本。可以分别记录包版本:

rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' \
  selinux-policy selinux-policy-targeted policycoreutils policycoreutils-python

如果结果不一致,优先统一备用机的软件包版本,再导入本地配置。只复制导出文件而不统一策略包,可能导致某些类型、布尔值或规则在备用机上不存在。

主机上的本地策略配置可通过 semanage export 导出:

semanage export -f /root/selinux-backup/current/semanage.export
sha256sum /root/selinux-backup/current/semanage.export

将文件通过受控方式传到备用机后,先保存备用机当前配置:

mkdir -p /root/selinux-backup/before-import
semanage export -f /root/selinux-backup/before-import/semanage.export

确认文件校验值一致,再在维护窗口内导入:

semanage import -f /root/selinux-backup/current/semanage.export

semanage export 通常可以覆盖以下本地定制内容:

  • 持久化布尔值;
  • 文件上下文规则;
  • SELinux 端口类型映射;
  • 用户、登录、接口或节点相关的本地映射;
  • 其他由 semanage 管理的本地策略定制。

导入后,应再次导出并比较:

semanage export -f /root/selinux-backup/after-import.export
diff -u \
  /root/selinux-backup/current/semanage.export \
  /root/selinux-backup/after-import.export

如果差异只来自排序或版本工具格式,应逐项确认;如果出现规则缺失、路径变化或端口类型变化,不要直接进入切换测试。

布尔值不能只看当前运行状态

getsebool -a 显示的是当前状态,但当前状态并不一定代表重启后仍然有效。需要同时确认持久化配置:

getsebool -a | sort
semanage boolean -l | sort

对于应用需要的具体布尔值,应先确认服务文档和实际访问需求,再决定是否使用 setsebool -P。例如,某些应用需要允许特定域进行网络连接,但不应为了“先让服务跑起来”而批量开启所有宽松选项。

setsebool -P  on

这类命令会修改持久化安全策略,执行前应保留备份,并在备用机上完成服务测试。回滚时应根据备份中的原始值恢复,而不是笼统地关闭 SELinux。

自定义策略模块要单独同步

semanage export 不等于完整导出所有自定义策略模块。通过 semodule 安装的模块,需要单独确认:

semodule -lfull

主备同步时,至少应保存以下信息:

  • 模块名称;
  • 模块版本;
  • 模块优先级;
  • .pp 文件或可重复构建的源代码;
  • 模块文件的校验值;
  • 模块对应的应用版本和变更原因。

例如,将经过审核的策略模块放到备用机后:

sha256sum /root/selinux-policy/custom_app.pp
semodule -i /root/selinux-policy/custom_app.pp
semodule -lfull | grep -F custom_app

如果主机上的模块文件已经丢失,只剩下运行中的策略状态,不建议直接从活动策略目录中挑选文件复制。更稳妥的做法是找到原始 .te、.if、.fc 文件或软件包,重新构建出与主机相同的模块。否则即使模块名称相同,也可能存在版本和优先级差异。

安装模块会影响当前策略加载,应该先在备用机上测试,保留旧模块和导入前的备份。若确认新模块导致服务异常,回滚应使用原版本模块重新安装,或在明确模块名称、版本和依赖关系后执行移除操作,不要直接删除整个策略模块目录。

文件上下文决定数据目录能否被服务访问

策略规则同步后,仍要检查数据目录的安全上下文。SELinux 判断访问权限时,不只看 Linux 用户和文件权限,还会检查文件的类型标签。

先查看主机上的规则和实际标签:

semanage fcontext -l | grep -E '/srv/app|/data/app'
ls -ldZ /srv/app
find /srv/app -maxdepth 2 -type f -exec ls -lZ {} \; | head -n 30

在备用机上查看 SELinux 期望的标签:

matchpathcon /srv/app
matchpathcon /srv/app/data
ls -ldZ /srv/app /srv/app/data

如果主备使用相同路径,可以先进行不修改文件的预览:

restorecon -Rnv /srv/app/data

确认输出中的变更符合预期后,再执行实际修复:

restorecon -Rv /srv/app/data

restorecon 会修改文件的 SELinux 标签,目录较大时可能影响正在运行的服务,因此应在维护窗口执行。回滚不能简单依赖“再执行一次 restorecon”,因为原来的标签可能正是错误状态。执行前应保存 ls -lZ 结果,并确保正确的 semanage fcontext 规则已经存在。

如果需要为自定义目录建立规则,应使用 semanage fcontext,不要长期依赖 chcon:

semanage fcontext -a -t  '/srv/app/data(/.*)?'
restorecon -Rv /srv/app/data

其中 必须根据应用域和策略要求确认,不能把 httpd_sys_content_t 等常见类型随意套用到所有应用目录。错误的类型可能导致服务仍然无法访问,或者扩大不必要的访问范围。

数据复制必须保留扩展属性

如果使用文件级复制同步业务数据,应确认复制方式能够保留扩展属性、ACL、硬链接和数值用户组。以 rsync 为例,可以先使用预演模式:

rsync -aHAXn --delete --numeric-ids \
  /srv/app/data/ standby:/srv/app/data/

确认文件列表和删除列表正确后,再执行实际同步:

rsync -aHAX --delete --numeric-ids \
  /srv/app/data/ standby:/srv/app/data/

--delete 会删除备用机目标目录中源端不存在的文件,属于有影响的操作。执行前应确认源目录、目标目录、数据冻结状态和备份可用性;如果业务不允许删除,应去掉该参数或改用带版本保留的同步方式。

-X 用于保留扩展属性,其中可能包含 security.selinux。但即使复制保留了标签,也要确认备用机的策略包和路径完全一致。如果底层复制机制不会传输 SELinux 扩展属性,就应在备用机完成复制后,根据已同步的 fcontext 规则执行 restorecon。

服务端口、网络路径和健康检查要分别验证

端口监听和 SELinux 端口类型是两个不同层面的条件。先看服务实际监听情况:

ss -lntp

再查看 SELinux 端口映射:

semanage port -l

如果应用使用非标准端口,必须确认该端口已映射到应用允许的类型。下面只是操作形式示例,具体类型应以应用策略为准:

semanage port -a -t http_port_t -p tcp 8080

执行新增或修改端口规则前,应确认该端口没有已有映射,并保存导入前的 semanage 备份。错误的端口类型会导致服务仍被拒绝,删除或修改端口规则也可能影响其他服务。

主备切换时,服务访问、数据同步、心跳和管理入口不应全部依赖同一个故障点。至少要确保主服务访问路径不可用时,仍有独立的管理或控制台入口可以完成接管;数据同步链路中断时,应能明确判断数据是否已经追平,而不是仅根据网络连通性判断切换成功。

健康检查也不能只看 TCP 端口是否打开。端口开放只能说明有进程监听,不能证明服务进程能读取数据、访问必要目录或完成一次真实请求。切换测试应至少包含:

systemctl is-active .service
systemctl status .service --no-pager
ss -lntp
journalctl -b -u .service --no-pager -n 100

如果是提供 HTTP 服务的应用,还应从实际访问路径发起一次受控请求;如果是其他协议,则使用该协议对应的业务级检查。测试结束后,应确认服务仍处于 Enforcing 模式,而不是因为故障排查被留在宽松模式。

启用 Enforcing 时的验证和回滚

先确认配置文件当前值:

grep -E '^(SELINUX|SELINUXTYPE)=' /etc/selinux/config

CentOS 7.9 常见配置如下,但应以实际策略类型为准:

SELINUX=enforcing
SELINUXTYPE=targeted

如果当前已经是 permissive,可以在维护窗口内临时切换运行状态:

setenforce 1
getenforce

如果当前为 disabled,不能依靠 setenforce 立即启用,需修改 /etc/selinux/config 后重启,并提前确认备用机具备控制台入口和启动后验证条件。

切换到强制模式后,立即检查服务和审计日志:

getenforce
systemctl is-active .service
ausearch -m AVC,USER_AVC -ts recent -i

出现 AVC 拒绝时,先按以下方式判断:

现象更可能的原因优先处理方式
只有备用机出现 AVC策略、模块、布尔值或文件标签漂移对比 semanage export、semodule -lfull 和 ls -Z
主备都出现同类 AVC应用确实缺少必要策略或访问方式不受支持审核应用访问模型,再设计最小规则
目录访问被拒绝,tcontext 不符合预期文件上下文错误检查 semanage fcontext,预览后执行 restorecon
连接端口被拒绝SELinux 端口类型或服务监听配置不一致检查 ss -lntp 和 semanage port -l
没有 AVC,但服务未启动应用配置、数据状态、依赖服务或网络路径问题查看 systemctl 和 journalctl,不要继续放宽策略
开启宽松模式后服务恢复只能说明强制访问控制阻断了某个动作继续定位具体 AVC,不应长期关闭 SELinux

不要看到 AVC 就直接使用 audit2allow 生成并安装新模块。日志中可能包含应用配置错误、路径标签错误或不应被允许的访问行为。只有在确认访问确实符合业务需求,并经过最小权限审核后,才考虑制作新的策略模块。

如果强制模式导致业务无法恢复,可以在具备控制台或受控维护入口的前提下临时执行:

setenforce 0

这只是应急回退,会降低安全边界,不应作为最终方案。恢复业务后,应保留 AVC 日志、修正策略或标签,再重新执行 setenforce 1。如果已经修改了 /etc/selinux/config,还要同步检查配置是否会在下次重启时再次进入不合适的模式。

把主备切换固定成可重复的动作

一次完整的切换演练不应只验证“备用机能否启动服务”,还要验证策略和数据是否同步完成。推荐按以下顺序执行:

  1. 确认主机仍可管理,保存主备双方的 sestatus、策略包版本和 semanage export。
  2. 暂停主机写入,或确认数据复制已经追平,避免主备同时接受写请求。
  3. 隔离原主机的业务入口,防止切换期间形成双主。
  4. 在备用机确认 getenforce 为 Enforcing,并检查策略模块、布尔值、端口映射和目录标签。
  5. 按既定顺序提升数据服务和应用服务,检查服务状态及业务级健康检查。
  6. 从实际访问路径验证读写、认证、日志和关键数据目录。
  7. 持续观察 journalctl、审计日志和复制状态,确认没有新的 AVC 或数据追赶异常。
  8. 切换完成后重新导出备用机策略,作为下一次主备校准的基线。

这里需要特别区分三个时间指标:策略同步延迟、业务数据复制延迟和人工切换耗时。SELinux 本地配置通常不需要按秒级实时复制,但每次策略变更后都应及时同步;业务数据则可能需要更高频率复制;人工确认、隔离旧主机和业务验证会直接影响实际切换时间。

根据切换要求选择维护方式

如果业务要求较短的恢复时间,备用机应保持为可启动的热备用状态,提前安装相同策略包和应用版本,持续同步策略导出文件及自定义模块,并定期进行强制模式下的切换演练。这样需要投入额外的备用资源、数据复制能力和自动化校验,但可以明显减少临时修改策略的步骤。

如果业务允许较长的恢复时间,可以采用定期导出、人工导入和按计划演练的方式。成本较低,但必须接受策略漂移和人工操作带来的切换风险,尤其不能把“多年未启动的备用机”直接视为可用备用机。

如果主备目录结构不同、应用角色不同或策略模块没有源文件,则不适合直接复制主机策略。应分别维护每台服务器的 fcontext、端口和模块映射,并在每次应用变更后重新验证。若无法提供控制台入口、策略备份和数据回滚能力,也不应在没有演练的情况下把 SELinux 从宽松模式直接切换为强制模式。

最终可以按这条路径判断:主备版本和路径一致,就同步策略包、semanage 导出内容、模块文件和数据标签;路径或角色不同,就只同步通用策略,把文件上下文和端口规则按备用机实际环境重新定义;切换前若发现 AVC 只存在于备用机,先处理策略漂移;若主备都出现同类 AVC,则需要重新审核应用访问模型。这样,SELinux 不会成为主备切换时的临时变量,而会成为两台服务器共同遵守、可验证并可回滚的安全基线。

把主备切换固定成可重复的动作配图

目录结构
全文