
简介一份面向Linux系统管理员与安全初学者的SELinux策略配置实验文档聚焦操作系统安全中强制访问控制的落地操作。文档以实验一为主线完整覆盖SELinux三种模式enforcing、permissive、disabled的切换与查看、安全上下文检查、文件复制与移动时上下文变化、chcon命令修改上下文、布尔值查询与永久修改等核心内容并辅以samba与nfs服务的配置示例便于按步骤实操对照。资源为单个docx文档共216KB内容紧凑适合作为实验指导或复习笔记。已有478人学习下载可用性得到初步验证。通过完成文档中的练习读者能够掌握SELinux核心命令与排错思路提升服务器安全配置能力也能为后续安全实验打下基础。 干过Linux运维或者上过操作系统安全课的人多半都有过这种经历服务端口正常、进程也在跑、防火墙都放行了可客户端就是连不上或者文件明明有权限程序一读取就被拒绝。查了半天最后setenforce 0一试一切正常——罪魁祸首就是SELinux。很多人遇到这种情况就直接关掉SELinux图一时省事可生产环境里这么干隐患非常大。我这篇就把实验一里涉及的SELinux策略配置完整拆开讲从三种模式区别、布尔值开关、文件上下文管理到用audit2allow生成自定义策略把原理和实操串起来新手照着做就能复现老手也能查漏补缺。需要提前说一句这篇实验的操作全部在CentOS 7.9/RHEL 7兼容环境里完成用的都是系统自带工具没有额外装第三方组件。如果你用的是CentOS 8以上的版本部分命令输出格式会略有差异但核心思路完全一致。1. 实验定位与整体思路拆解1.1 为什么SELinux值得单独花一个实验去配很多同学第一次接触SELinux都会觉得它“除了添乱没别的用”。这种印象其实是因为SELinux和传统Linux权限模型根本不在一个维度上。传统Linux权限是DAC自主访问控制意思是文件属主可以自己决定谁能访问自己的文件。这种模型有一个天然缺陷一旦某个进程被攻破攻击者就继承了这个进程的所有权限能在系统里横向移动。而SELinux实现的是MAC强制访问控制它给每个进程和每个文件都贴了安全标签进程能不能访问某个文件不是由文件属主说了算而是由系统全局策略说了算。即使用root账户操作一样要遵守策略约束。这个实验的核心目标就是把SELinux从“知道”变成“会用”。实验一不涉及太复杂的网络策略重点在于让你亲手完成一次策略配置的闭环发现问题、定位授权问题、执行策略调整、验证策略是否生效。这个闭环思路会贯穿后续所有实验。1.2 实验流程的设计逻辑整个实验我建议按四步走顺序不要乱第一确认SELinux当前状态搞清楚系统处于哪种模式、哪些布尔值被修改过、哪些文件上下文异常。第二制造一个典型的访问失败场景比如HTTP服务读取不到自定义目录下的文件让问题真实暴露出来。第三针对问题做策略调整分别用布尔值、文件上下文、自定义策略模块三种手段解决。第四验证调整结果同时测试策略回滚。很多实验指导书上来就让你改配置忽略了第一步结果就是改了半天连问题都复现不了自然也就不知道策略到底生效没有。我先踩过这个坑所以建议你务必按顺序来。2. 实验环境准备与基础概念2.1 系统环境和初始化准备建议准备一台最小化安装的CentOS 7.9虚拟机内存2GB即可磁盘20GB足够。最小化安装默认就带SELinux不需要额外操作。如果你用的系统是CentOS 8或者Rocky Linux同样适用。装完系统后先做两件事。第一件事确认内核启动参数里没有selinux0或enforcing0这两个参数会在内核层面直接禁用或降级SELinuxcat /proc/cmdline正常输出里不应该出现selinux0。第二件事确认SELinux相关的包都已经安装rpm -qa | grep selinux至少能看到selinux-policy、selinux-policy-targeted和libselinux这几个包。缺哪个就yum install补上。2.2 三种运行模式Enforcing、Permissive、DisabledSELinux一共三种模式很多人记住了名字但理解不透。我用大白话解释一下Enforcing强制模式策略完全生效违反策略的操作会被直接拒绝并记录到审计日志。这是生产环境应该使用的模式。Permissive宽容模式策略不真正拦截操作但违反策略的行为会被记录下来。这个模式非常适合排查问题相当于“只警告不处罚”。Disabled禁用模式SELinux彻底关闭连标签都不打。想重新开启只能修改配置文件后重启不能运行时直接切换。三种模式的切换方式getenforce # 查看当前模式 setenforce 0 # 临时切换为Permissive setenforce 1 # 临时切换为Enforcing注意setenforce只能在这两种模式之间切换不能从Disabled切回Enforcing。如果/etc/selinux/config里设置了SELINUXdisabled必须先改配置文件再重启。永久生效需要修改/etc/selinux/configSELINUXenforcing SELINUXTYPEtargeted其中SELINUXTYPEtargeted表示只对部分受保护进程如httpd、sshd、named等强制策略其他进程不受限制这是最常用的策略类型。还有一个mls类型是更严格的多级安全策略一般用不上。2.3 三个核心概念类型强制、布尔值和文件上下文实验一的所有操作都围绕三个核心概念展开。**类型强制Type Enforcement**是SELinux最核心的机制。系统里每个进程都有一个域domain每个文件都有一个类型type规则就定义“哪个域可以访问哪个类型”。举个例子httpd_t这个域能否访问httpd_sys_content_t类型的文件就是由策略规则决定的。**布尔值Boolean**是SELinux提供的一组开关用来在运行时调整策略中的某些规则不需要重新编译策略。比如httpd_can_network_connect这个布尔值控制httpd能否主动向外发起网络连接默认是关闭的。布尔值的操作命令getsebool -a # 查看所有布尔值 getsebool httpd_can_network_connect setsebool httpd_can_network_connect on # 临时开启 setsebool -P httpd_can_network_connect on # 永久开启**文件上下文File Context**是SELinux给文件打的标签。ls -Z可以查看文件的SELinux标签第一列就是用户、角色、类型等信息。文件移动到新位置后标签可能不匹配导致进程无法访问这时需要用restorecon或semanage fcontext来修复。这三个概念搞清楚了后面的实验就顺理成章。3. 策略配置实操全流程3.1 先复现一个访问失败场景实验一里我用的场景是把网站文件放到自定义目录/webdata然后配置httpd访问这个目录结果浏览器始终打不开页面。这个场景非常典型能同时触发文件上下文和布尔值两类问题。初始化操作如下# 安装httpd yum install -y httpd # 创建自定义目录并写入测试页面 mkdir /webdata echo h1SELinux Test Page/h1 /webdata/index.html # 修改httpd主配置 vim /etc/httpd/conf/httpd.conf # 找到 DocumentRoot /var/www/html改为 # DocumentRoot /webdata # 同时找到 Directory /var/www/html改为 # Directory /webdata # 启动服务 systemctl start httpd启动服务本身不会报错但用浏览器访问服务器IP会一直转圈或直接拒绝连接同时/var/log/httpd/error_log里会出现类似AH00132: file permissions deny server access: /webdata/index.html这个报错特别有迷惑性因为ls -l /webdata/index.html看权限明明没问题。实际上问题出在SELinux标签上——/webdata目录被打上了default_t类型而不是httpd_sys_content_thttpd进程自然无权访问。3.2 用semanage和restorecon修复文件上下文定位到问题后不要急着用chcon去改上下文。chcon只是临时修改系统重新打标签或者执行restorecon后就会被覆盖。正确做法是用semanage fcontext定义默认上下文规则然后执行restorecon让规则生效。先确认当前标签和应有的标签ls -Zd /webdata # 输出类似system_u:object_r:default_t:s0 /webdata ls -Zd /var/www/html # 输出类似system_u:object_r:httpd_sys_content_t:s0 /var/www/html然后执行# 安装semanage工具如果没装 yum install -y policycoreutils-python # 为/webdata目录添加默认上下文规则加上正则匹配所有子文件 semanage fcontext -a -t httpd_sys_content_t /webdata(/.*)? # 让规则立即生效 restorecon -Rv /webdata执行完再确认标签ls -Zd /webdata # 输出应该变为system_u:object_r:httpd_sys_content_t:s0 /webdata再次刷新浏览器页面就能正常访问了。这里有个细节值得注意/webdata(/.*)?这个正则写法既匹配/webdata目录本身也匹配下面所有子文件和子目录。如果只写/webdata那么子目录里的文件还是默认标签网页引用嵌套目录时依然会访问失败。实验指导书上经常不写这部分实际用的时候特别容易踩坑我专门补充一句。还有restorecon -Rv的-R是递归-v是显示过程习惯性加上这两个参数能看到哪些文件的标签被修正了方便确认结果。3.3 用布尔值解决httpd网络访问限制文件上下文修好以后页面能打开了。但如果你在这个服务器上部署了一个需要访问外部API的Web应用会发现curl外部地址一直超时。这不是网络不通而是SELinux布尔值httpd_can_network_connect默认为off拦住了httpd进程发起对外连接。查看和确认getsebool httpd_can_network_connect # 输出httpd_can_network_connect -- off验证确实是这个原因导致的可以临时打开再测setsebool httpd_can_network_connect on此时再执行curl就通了。确认无误后加上-P参数永久生效setsebool -P httpd_can_network_connect on这个案例完美说明了布尔值的作用它是SELinux策略预留给管理员的开关让你在不修改策略文件的前提下按需放行某些行为。重要提示在生产环境配布尔值建议先用setsebool不带-P测试确认业务正常后再加-P永久化。如果直接永久化万一引发安全问题回滚就多了一步。3.4 用audit2allow生成自定义策略模块布尔值能解决常见的开关类问题但有些场景布尔值没有对应选项比如某个程序需要访问一个自定义端口的网络数据。这时候就要用到audit2allow从审计日志里提取被拒绝的操作自动生成一个自定义策略模块。实验一里我用了一个相对简单的例子让httpd允许使用自定义端口监听。先将httpd配置监听8000端口然后启动服务会发现启动失败再看/var/log/audit/audit.log里有denied记录。把对应的AVC拒绝信息导入audit2allow# 查看最近的拒绝事件 grep denied /var/log/audit/audit.log | tail -20 # 将拒绝事件转换为自定义策略模块 grep denied /var/log/audit/audit.log | audit2allow -M httpd_custom执行后会在当前目录生成httpd_custom.pp和httpd_custom.te两个文件。其中.te是策略源码.pp是编译好的二进制模块。加载模块semodule -i httpd_custom.pp然后重启httpdsystemctl restart httpd服务就能正常启动了。audit2allow的原理是分析DENIED事件中的源域、目标类型和操作类型生成一条放行规则。用它可以快速解决问题但也要注意直接生成的规则往往比较宽泛比如可能会放行所有域对特定类型的访问。在实验环境没问题在真实生产环境里建议对生成的.te文件做进一步细化。4. 验证与回滚确认策略生效并可控4.1 场景复测与状态确认配置完成后需要系统性验证一次而不只是“页面能打开就完事”。我的验证清单如下# 1. 确认当前模式 getenforce # 期望输出Enforcing # 2. 确认布尔值状态 getsebool httpd_can_network_connect # 期望输出on # 3. 确认文件上下文 ls -Zd /webdata # 期望输出system_u:object_r:httpd_sys_content_t:s0 /webdata # 4. 确认自定义模块已加载 semodule -l | grep httpd_custom # 期望看到 httpd_custom 这一行 # 5. 实际访问测试 curl http://localhost # 期望输出h1SELinux Test Page/h1 # 6. 确认没有新的拒绝事件 grep denied /var/log/audit/audit.log | tail -5如果第6步还能看到关于/webdata的拒绝记录说明标签还有遗漏需要排查子目录或嵌套文件。另外还要梳理所有改过的配置项我习惯统一汇总记录配置项修改前修改后生效方式/etc/selinux/configSELINUXenforcing保持不变永久httpd_can_network_connectoffon永久-P参数/webdata 文件上下文default_thttpd_sys_content_t默认规则semanagehttpd_custom模块未加载已加载semodule -i这份记录后续撤掉实验或者排错的时候非常有用。4.2 策略回滚与模块卸载实验做完要恢复环境或者后续确认某个模块不再需要时回滚操作必须熟练掌握。布尔值回滚setsebool -P httpd_can_network_connect off文件上下文回滚# 删除自定义规则 semanage fcontext -d /webdata(/.*)? # 恢复默认标签 restorecon -Rv /webdata自定义模块卸载semodule -r httpd_custom回滚后同样要验证一遍服务状态是否回到实验前的表现。这里需要注意restorecon恢复的是SELinux默认规则下的标签如果/webdata本身就不在默认规则里那么恢复之后它会变成default_tHTTP服务自然就无法访问了——这才是符合预期的回滚结果。我在做实验的时候一开始图省事没有写回滚步骤结果后面做第二次实验时环境状态不对排查了很久才发现是上一次实验的残留策略没有清干净。从那次以后我每个实验结束都会完整回滚并验证这个习惯强烈推荐你也养成。5. 常见问题与排查技巧实录5.1 配置完成后依然被拒绝这是最常见的坑。文件上下文、布尔值都改了页面还是打不开或者服务还是起不来。我总结的排查顺序是这样的第一步先看SELinux模式是不是被临时切到了Enforcing以外。如果你之前用setenforce 0测试过可能忘了切回来。getenforce一眼就能确认。第二步看审计日志里有没有对应拒绝记录ausearch -m avc -ts recent这一步会列出最近的AVC拒绝事件里面有完整的源域、目标类型、操作信息比直接在audit.log里grep更好用。如果没有记录说明请求可能在到达SELinux之前就被其他机制拦截了比如防火墙、文件系统权限或TCP wrapper。第三步确认标签是否真正生效。很多新手用chcon改完标签以为就完了结果文件被某个进程改写了标签又被重置。用semanage fcontext restorecon的组合就不会有这个问题。5.2 重启后配置丢失配置重启后失效十有八九是没加持久化参数。setsebool不带-P重启就还原chcon改的标签执行restorecon就还原。解决办法参考3.2和3.3节用semanage fcontext和setsebool -P。还有一种情况是自定义模块加载了但执行semodule -i之后没有确认模块真的加载成功。使用semodule -l | grep 模块名检查一下最稳妥。5.3 日志刷屏和不当恢复实验过程中如果调用很频繁audit.log会被刷得很大。这时候不要用rm直接删掉日志文件应该用service auditd restart或者更稳妥的方式auditctl -e 0 # 临时暂停审计 # 清理或归档日志 auditctl -e 1 # 恢复审计另外提醒一句不要在生产环境直接删除audit.log那可能同时破坏了审计链。如果把SELinux设成了disabled又想恢复注意修改/etc/selinux/config后必须重启系统。重启后文件系统可能需要重新打标签启动过程会花一些时间这是正常现象耐心等即可。系统会自动在根目录生成.autorelabel标记文件来触发这个过程重启完成后该文件会被自动删除。5.4 快速排错速查表现象可能原因排查方法解决方案服务启动失败域无权限绑定特定端口ausearch -m avc -ts recentsemanage port -a -t http_port_t -p tcp 8000网页403/404文件上下文标签错误ls -Z对比标准目录semanage fcontextrestorecon程序无法访问网络布尔值未开启getsebool -a | grep networksetsebool -P 对应布尔值 on配置重启后消失未使用永久参数检查命令是否带-P重新用setsebool -P自定义模块不生效模块未加载semodule -lsemodule -i xxx.pp所有访问都被拒绝系统进入Enforcing但策略被误改seinfo -t查看类型恢复快照或重新编译策略6. 实操心得与下一步延伸这一个实验做下来最核心的感受是SELinux其实并不是故意跟管理员作对它的每一个拒绝背后都有明确规则关键是学会通过日志和标签去理解它的思路。就像新到一个城市导航还没普及的时候你会觉得红绿灯都是阻碍可一旦掌握了路网规律红绿灯反而成了保护你安全通行的工具。SELinux也是类似它的类型强制、布尔值和文件上下文本质上是在帮系统建立一套清晰的访问控制边界。实验一用的都是最基础的配置手段后续如果继续深入还有不少值得探索的方向。比如用semanage port管理端口上下文解决自定义端口监听问题用semanage boolean批量管理布尔值适合多台服务器统一策略有条件的话还可以试试用sepolicy generate生成应用的自定义策略模板。这些都是实验一基础上的自然延伸原理是一致的。最后再分享一个我在实际排障中养成的习惯每次做完SELinux相关操作都会随手执行一次ausearch -m avc -ts recent确认没有新的拒绝记录再继续干别的。看似多花几秒钟实际上能省下后面大量排查时间。希望这篇实验笔记能让你少走我走过的弯路把SELinux从“拦路虎”变成“守护者”。本文还有配套的精品资源点击获取