CentOS系统的安全控制台和串口登录限制,核心就是通过修改/etc/securetty文件、调整/etc/login.defs配置、禁用不必要的串口服务以及设置GRUB引导参数来实现。具体来说,你需要把除了tty1到tty6之外的所有虚拟终端从安全登录列表中剔除,同时在systemd层面禁用serial-getty服务,最后通过GRUB给内核传递console=tty0参数来彻底关闭串口控制台输出。这套组合拳打下来,基本上就能把物理串口和虚拟控制台的登录入口锁死,只保留你真正需要的访问通道。
很多运维人员在部署CentOS服务器时,往往忽略了串口和控制台登录的安全隐患。默认情况下,CentOS 7和CentOS 8都允许通过串口(/dev/ttyS0)和所有虚拟终端(tty1-tty63)进行root登录,这在生产环境中是非常危险的。一旦有人物理接触到服务器的串口接口,或者通过带外管理卡(如iLO、iDRAC、IPMI)访问,就可能绕过网络层面的防火墙直接获得系统权限。所以,做好这两个层面的限制是服务器加固的基本功。
一、理解CentOS控制台登录的底层机制CentOS的控制台登录涉及两个核心概念:虚拟控制台(Virtual Console)和串行控制台(Serial Console)。虚拟控制台就是你在物理机上按Ctrl+Alt+F1到F6切换的那些终端界面,对应/dev/tty1到/dev/tty6。串行控制台则是通过COM口(串口)连接的终端,通常对应/dev/ttyS0或/dev/ttyS1。
系统判断哪些终端允许root登录,依赖的是/etc/securetty文件。这个文件里列出了所有被认为是"安全"的终端设备。只有在这个列表中的终端,login程序才允许root用户登录。如果某个终端不在列表里,即使你有root密码,也登不进去。这就是我们做限制的第一个切入点。
另外,串口登录的启用与否,取决于systemd的serial-getty服务。在CentOS 7中,这个服务叫serial-getty@ttyS0.service;在CentOS 8中,叫serial-getty@ttyS0.service,本质一样。只要这个服务在运行,串口就能登录。所以禁用它就是第二个切入点。
二、修改/etc/securetty限制虚拟控制台登录打开/etc/securetty文件,你会看到类似下面的内容:
# /etc/securetty console vc/1 vc/2 vc/3 vc/4 vc/5 vc/6 tty1 tty2 tty3 tty4 tty5 tty6
这个文件里列出了所有允许root登录的终端。如果你的服务器只需要通过tty1到tty6进行本地管理,那就把vc/1到vc/6以及tty1到tty6保留,其他的全部删掉。如果你连本地虚拟控制台都不想让root登录(推荐做法),那就只保留console和vc/1,甚至只保留console。
具体操作步骤如下:
# 备份原文件 cp /etc/securetty /etc/securetty.bak # 编辑文件 vi /etc/securetty # 删除不需要的行,只保留你允许的终端 # 例如只保留 tty1 tty1
修改完成后保存退出。这样一来,除了tty1之外,其他所有虚拟终端都无法进行root登录了。普通用户登录不受这个文件限制,但生产环境中通常也不建议开放普通用户的控制台登录权限。
这里有个细节要注意:/etc/securetty只影响root登录,不影响普通用户。如果你想彻底禁止某个终端上的所有登录,需要在/etc/security/access.conf中配置,或者直接禁用对应的getty服务。不过大多数场景下,限制root就够了。
三、禁用串口登录服务串口登录是通过systemd的serial-getty服务实现的。要禁用它,执行以下命令:
# CentOS 7 systemctl stop serial-getty@ttyS0.service systemctl disable serial-getty@ttyS0.service # CentOS 8 systemctl stop serial-getty@ttyS0.service systemctl disable serial-getty@ttyS0.service # 如果有多个串口,比如ttyS1,同样处理 systemctl stop serial-getty@ttyS1.service systemctl disable serial-getty@ttyS1.service
执行完之后,用systemctl status serial-getty@ttyS0.service确认状态是inactive (dead),说明已经彻底关闭了。
如果你的服务器有多个串口(比如ttyS0和ttyS1),建议全部禁用。有些服务器主板自带两个串口,带外管理卡也可能占用一个,都要检查到。可以用以下命令查看所有串口设备:
dmesg | grep ttyS ls -l /dev/ttyS*
另外,如果你的服务器使用的是IPMI或BMC带外管理,通常它会通过串口重定向来提供控制台访问。这种情况下,你需要在BMC/IPMI的Web管理界面中关闭"Serial over LAN"或"Serial Redirection"功能,而不仅仅是在操作系统层面禁用。两层都要关,才算真正堵住。
四、通过GRUB禁用内核串口控制台输出前面两步是在用户空间做限制,但Linux内核本身也可能把控制台输出到串口。这意味着即使你禁用了serial-getty服务,内核的启动信息、崩溃日志还是会往串口发。要从内核层面彻底关闭串口控制台,需要修改GRUB配置。
编辑/etc/default/grub文件,找到GRUB_CMDLINE_LINUX这一行:
# 修改前(可能的样子) GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet console=tty0 console=ttyS0,115200n8" # 修改后 GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet console=tty0"
关键操作就是把console=ttyS0,115200n8这段删掉,只保留console=tty0。console=tty0表示内核只往第一个虚拟终端输出,不往串口输出。
修改完成后,需要重新生成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 (BIOS启动) grub2-mkconfig -o /boot/grub2/grub.cfg # CentOS 8 (UEFI启动) grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
然后重启服务器验证:reboot。重启后,串口应该完全没有任何输出了。你可以用串口线连接另一台机器来确认,如果没有任何字符出现,说明配置成功。
五、额外加固:限制tty数量和PAM配置除了上面的核心操作,还有几个加固措施值得做。首先是限制系统允许的虚拟终端数量。CentOS默认可能开了63个虚拟终端(tty1到tty63),这完全没必要。修改/etc/systemd/logind.conf:
[Login] NAutoVTs=6 ReserveVT=6
NAutoVTs=6表示只自动创建tty1到tty6,ReserveVT=6表示预留6个终端给紧急使用。这样系统就不会创建tty7到tty63了,减少了攻击面。
其次,检查PAM配置。编辑/etc/pam.d/login文件,确保有以下内容:
# /etc/pam.d/login auth required pam_securetty.so
pam_securetty.so这个模块就是用来检查/etc/securetty的。如果这个模块没有被调用,那你改了securetty也没用。所以一定要确认它存在并且没有被注释掉。
还有一个容易被忽略的点:/etc/init/serial.conf(CentOS 7)或/etc/systemd/system/serial-getty@.service.d/override.conf(CentOS 8)。这些文件可能会覆盖你的禁用设置,特别是在系统更新后。建议定期检查这些文件是否被重新生成。
六、验证和监控所有配置完成并重启后,你需要做几项验证:
第一,用root账号在tty1上尝试登录,应该正常。在tty2或更高编号的终端上尝试root登录,应该被拒绝,提示"Login incorrect"。
第二,用串口线连接服务器,不应该有任何输出。如果有,说明内核参数没改对,或者BMC层面还在重定向。
第三,检查服务状态:
systemctl status serial-getty@ttyS0.service # 应该显示 inactive (dead) systemctl status serial-getty@ttyS1.service # 如果存在,也应该是 inactive (dead)
第四,建议把这些配置纳入自动化运维脚本。用Ansible或Shell脚本批量部署到所有服务器,确保一致性。可以写一个检测脚本定期巡检:
#!/bin/bash
# check_console_security.sh
echo "=== Checking /etc/securetty ==="
if grep -q "^tty[0-9]" /etc/securetty; then
echo "WARNING: Multiple tty entries found in securetty"
else
echo "OK: securetty looks restricted"
fi
echo "=== Checking serial-getty services ==="
for svc in serial-getty@ttyS0 serial-getty@ttyS1; do
if systemctl is-active --quiet $svc 2>/dev/null; then
echo "WARNING: $svc is still running!"
else
echo "OK: $svc is disabled"
fi
done
echo "=== Checking GRUB console parameter ==="
if grep -q "console=ttyS" /etc/default/grub; then
echo "WARNING: Serial console still in GRUB config"
else
echo "OK: No serial console in GRUB"
fi
这个脚本可以加入cron定期执行,或者集成到监控系统中报警。
七、常见问题和注意事项有几个常见坑需要提醒。第一,如果你的服务器使用了kdump,crashkernel参数会占用一个控制台,可能导致你设置console=tty0后kdump不工作。这种情况下需要调整kdump的配置,或者保留console=ttyS0给kdump用,但同时在securetty中禁用ttyS0的root登录。
第二,CentOS 8 Stream已经停止维护,建议迁移到Rocky Linux或AlmaLinux。这些替代发行版的配置方法基本一致,但文件路径可能略有不同,比如GRUB配置路径在Rocky Linux上是/boot/grub2/grub.cfg。
第三,如果你是在云服务器上操作,串口通常不是物理串口而是云平台提供的虚拟串口。这种情况下,禁用系统层面的serial-getty可能不够,还需要在云平台的安全组或实例设置中关闭串口访问功能。
第四,做这些修改之前一定要备份。特别是GRUB配置改错了可能导致系统无法启动。保留原来的grub.cfg备份,必要时可以通过救援模式恢复。
总结一下,CentOS安全控制台和串口登录限制的核心思路就是三层防御:用户空间限制(securetty)、服务层禁用(serial-getty)、内核层关闭(GRUB console参数)。三层都做到位,才能真正把这两个入口封死。这不是什么高深的技术,但确实是很多企业在等保测评和安全审计中容易丢分的地方。
