CentOS服务器在公网环境下面临的入侵风险,很大一部分来自内核模块层面的攻击。攻击者一旦获取低权限shell,往往会尝试加载自定义的恶意内核模块(LKM)来隐藏进程、提权或植入rootkit。与其等到入侵发生后再去排查,不如直接在系统层面禁止危险内核模块的加载,从源头切断这类攻击路径。下面直接讲具体的加固方法和操作步骤。

理解内核模块加载机制与风险点

Linux内核模块通过modprobe、insmod等工具加载,内核在接收到加载请求时会校验模块签名(如果开启)、检查模块依赖,然后调用内核加载器执行。CentOS默认没有强制要求内核模块签名,这意味着任何有root权限的进程都可以加载任意编译好的.ko文件。攻击者常用的手法包括:编译一个针对当前内核版本的恶意模块,通过insmod加载后hook系统调用表,实现隐藏文件、进程和网络连接。因此,限制模块加载的核心思路是:只允许已知安全的模块,禁止一切未明确允许的模块。

通过sysctl禁用模块自动加载

CentOS系统中有两个关键的sysctl参数控制模块自动加载行为。第一个是kernel.modules_disabled,将其设置为1后,系统将完全禁止任何模块的加载和卸载操作,包括root用户。这个参数一旦设置,只有重启才能恢复,所以适合在确认所有必要驱动已经加载完毕后启用。操作命令如下:

# 立即禁止模块加载
sysctl -w kernel.modules_disabled=1

# 写入配置文件永久生效
echo "kernel.modules_disabled=1" >> /etc/sysctl.conf
sysctl -p

第二个参数是kernel.kexec_load_disabled,用于禁止kexec系统调用。kexec允许不经过BIOS直接加载新内核,攻击者可以利用它绕过安全启动和模块签名验证,加载一个被篡改的内核。建议同样设置为1:

sysctl -w kernel.kexec_load_disabled=1
echo "kernel.kexec_load_disabled=1" >> /etc/sysctl.conf

需要注意的是,kernel.modules_disabled=1是终极手段,设置后所有模块都无法加载,包括后续可能需要的硬件驱动或安全补丁模块。在生产环境中,建议先评估当前系统已加载的模块是否满足长期运行需求,确认无误后再启用。

使用modprobe黑名单机制精准拦截

如果不想一刀切地禁用所有模块,可以使用modprobe的黑名单功能,精准阻止特定危险模块加载。CentOS的模块黑名单配置文件位于/etc/modprobe.d/目录下,通常创建一个blacklist.conf文件,内容格式如下:

# 禁止加载常见的危险文件系统模块
blacklist cramfs
blacklist freevxfs
blacklist jffs2
blacklist hfs
blacklist hfsplus
blacklist squashfs
blacklist udf

# 禁止加载USB存储相关模块(如果服务器不需要USB存储)
blacklist usb-storage
blacklist uas

# 禁止加载FireWire模块
blacklist firewire-core
blacklist firewire-ohci
blacklist firewire-sbp2

写入黑名单后,需要更新initramfs使配置在启动阶段就生效。CentOS 7使用dracut命令:

dracut --force

CentOS 8及后续版本同样使用dracut,但需要注意模块名称可能因内核版本不同而有差异。黑名单机制的原理是让modprobe在解析模块加载请求时直接拒绝,但有一个局限:如果攻击者使用insmod直接指定模块文件的完整路径,黑名单不会生效。因此黑名单只能作为辅助手段,不能替代其他防护措施。

内核模块签名强制验证

CentOS 7和8的内核默认编译了模块签名支持,但通常没有强制开启。可以通过内核启动参数强制要求模块签名验证。编辑/etc/default/grub文件,在GRUB_CMDLINE_LINUX行添加module.sig_enforce=1参数:

GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet module.sig_enforce=1"

然后重新生成GRUB配置:

# CentOS 7 使用BIOS启动
grub2-mkconfig -o /boot/grub2/grub.cfg

# CentOS 7 使用UEFI启动
grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg

# CentOS 8 同样使用grub2-mkconfig,但路径可能不同
grub2-mkconfig -o /boot/grub2/grub.cfg

启用module.sig_enforce=1后,内核只加载经过可信密钥签名的模块。CentOS官方仓库提供的模块都带有Red Hat的签名,可以正常加载。但第三方编译的模块(如某些商业软件、自行编译的驱动)如果没有正确签名,将无法加载。在启用前必须确认所有必要的第三方模块都已签名或不再需要。

通过文件系统权限限制模块加载工具

即使内核层面没有完全禁止模块加载,也可以通过限制加载工具的使用权限来增加攻击难度。insmod、modprobe、rmmod等工具默认位于/sbin/目录下,普通用户无法执行。但攻击者获取root权限后这些限制就形同虚设。更有效的做法是移除或重命名这些工具,但需要注意系统更新可能会重新安装它们。一种折中方案是使用文件系统不可变属性:

# 将模块加载工具设置为不可变,防止被替换或修改
chattr +i /sbin/insmod
chattr +i /sbin/modprobe
chattr +i /sbin/rmmod

设置不可变属性后,即使是root用户也无法删除或修改这些文件,除非先移除不可变属性。这可以防止攻击者替换这些工具为恶意版本。但要注意,系统更新时如果尝试修改这些文件会失败,需要先chattr -i解除属性。

结合SELinux策略限制模块加载

CentOS默认启用SELinux,可以通过自定义SELinux策略进一步限制哪些进程可以加载模块。SELinux的module_load权限控制模块加载操作。默认策略中,只有init、modprobe等少数域拥有module_load权限。可以通过audit日志监控模块加载行为,然后根据实际需求收紧策略。具体操作是先开启auditd服务,然后监控/var/log/audit/audit.log中与module_load相关的记录:

# 查看模块加载相关的SELinux拒绝记录
ausearch -m avc -ts recent | grep module_load

如果发现异常进程尝试加载模块,可以创建自定义SELinux策略模块来阻止。不过SELinux策略编写较为复杂,适合有经验的运维人员使用。对于大多数服务器,保持SELinux处于Enforcing模式并定期审查audit日志已经能提供不错的防护。

监控与审计模块加载行为

无论采取哪种限制措施,都应该建立监控机制来检测异常模块加载尝试。Linux内核的审计子系统可以记录模块加载事件。通过配置auditd规则,可以追踪所有insmod、modprobe、delete_module系统调用:

# 添加审计规则监控模块加载和卸载
auditctl -a always,exit -F arch=b64 -S init_module -S finit_module -S delete_module -k kernel_modules

# 查看审计日志
ausearch -k kernel_modules

将这些审计日志接入集中日志系统,设置告警规则,一旦发现非预期的模块加载操作立即通知管理员。同时定期检查/proc/modules文件,对比已加载模块列表与已知安全基线,发现未知模块立即排查。

针对容器环境的额外考量

如果CentOS服务器上运行Docker或其他容器,需要注意容器内的模块加载行为。默认情况下,容器内的进程与宿主机共享内核,但容器通常没有CAP_SYS_MODULE能力,无法加载模块。可以通过Docker的安全配置确保容器不获得该能力:

# 运行容器时显式丢弃SYS_MODULE能力
docker run --cap-drop=SYS_MODULE --cap-drop=SYS_RAWIO your_image

同时检查所有运行中的容器,确保没有以privileged模式运行且不必要的容器。privileged容器拥有几乎所有宿主机的权限,包括加载内核模块,这是极其危险的。

实际操作建议与优先级排序

对于大多数CentOS服务器,建议按照以下优先级实施加固:第一,如果服务器硬件和业务允许,直接设置kernel.modules_disabled=1,这是最彻底的防护。第二,如果不适合完全禁用,启用module.sig_enforce=1强制签名验证,配合modprobe黑名单。第三,设置kernel.kexec_load_disabled=1,防止kexec绕过。第四,配置auditd监控模块加载事件。第五,定期审查已加载模块和audit日志,保持对系统状态的持续感知。

需要特别强调的是,任何内核层面的加固操作都有可能导致系统无法启动或某些功能异常。在生产环境实施前,务必在测试环境中验证,并确保有可用的回滚方案(如快照、备份)。修改GRUB配置和sysctl参数后,先不要重启,仔细检查配置语法,确认无误后再重启验证。

CentOS服务器安全是一个体系工程,禁止危险内核模块加载只是其中一环。配合最小化安装、及时更新补丁、严格的防火墙策略、SSH加固等措施,才能构建起有效的纵深防御体系。内核模块限制的核心价值在于,即使攻击者突破了应用层和系统层的防护,也难以在内核层面建立持久化控制,为检测和响应争取宝贵时间。