1. 项目概述与漏洞背景
最近在运维圈子里,CVE-2024-6387 这个漏洞编号被讨论得沸沸扬扬。它有个更形象的名字叫“regreSSHion”,直译过来就是“SSH 回归”,指的是一个在 OpenSSH 服务器中沉寂了近二十年、最近又被重新引入的严重安全漏洞。简单来说,它能让攻击者在特定条件下,远程获取到服务器的最高权限(root)。对于任何使用 Rocky Linux 9 或其他 RedHat 系发行版作为生产环境的团队来说,这都不是一个可以忽视的“小补丁”。我管理的几十台服务器里,大部分都跑着 Rocky Linux 9,所以第一时间就着手处理了。这篇文章,我就把从漏洞原理分析、影响范围判断,到具体的修复步骤、修复后的验证,以及一些在复杂生产环境中可能遇到的“坑”和应对策略,完整地梳理一遍。无论你是刚接触 Linux 运维的新手,还是经验丰富的系统管理员,都能在这找到可直接操作的方案和背后的思考逻辑。
这个漏洞的核心在于 OpenSSH 服务器(sshd)处理信号的一个竞态条件(race condition)。在特定版本的 glibc 库和 32 位 Linux 系统上,攻击者可以通过维持大量并发的、长时间存活的 SSH 连接,最终触发这个条件,导致 sshd 进程崩溃并可能执行任意代码。虽然目前公开的利用证明主要针对 32 位系统,并且平均需要 6-8 小时才能成功,但安全界普遍认为,在 64 位系统上实现利用只是时间问题,而且攻击手法很可能会被优化。因此,对于所有运行受影响 OpenSSH 版本(8.5p1 到 9.7p1)的系统,及时修复是必须的。对于 Rocky Linux 9 用户,好消息是 Rocky 社区和上游 RedHat 已经迅速响应,提供了修复后的安全更新包。
2. 漏洞影响分析与环境确认
在动手修复之前,盲目操作是大忌。我们必须先搞清楚两个问题:我的系统到底受不受影响?如果受影响,当前处于什么状态?这一步的排查,能避免我们误操作健康的系统,或者漏掉真正有风险的机器。
2.1 确认操作系统与 OpenSSH 版本
首先,我们需要登录到目标 Rocky Linux 9 服务器。通常通过现有的、未受影响的 SSH 连接或者控制台进行操作。
第一步,确认系统版本。虽然我们知道是 Rocky Linux 9,但最好还是用命令核实一下,避免误操作到其他版本的系统(比如 Rocky Linux 8 不受此漏洞影响)。
cat /etc/redhat-release或者
hostnamectl | grep -i "operating system"对于 Rocky Linux 9,你会看到类似Rocky Linux release 9.x (Blue Onyx)的输出。
接下来,检查当前安装的 OpenSSH 服务器版本,这是判断是否受影响的关键。
rpm -qa | grep openssh-server或者更精确地查询 openssh 主包:
rpm -q openssh关键版本比对:如果输出的版本号在openssh-8.5p1到openssh-9.7p1之间(包含两端),那么你的系统就存在潜在风险,需要修复。在 Rocky Linux 9 的默认仓库中,通常安装的是openssh-8.7p1系列版本。例如,你可能会看到openssh-8.7p1-38.el9.x86_64这样的输出。这里的38.el9是发行版打包版本号,我们需要关注的是主版本8.7p1,它正好落在受影响范围内。
注意:仅仅检查
sshd -V命令的输出有时不够准确,因为它显示的是 sshd 二进制文件的版本,而 RPM 查询才是判断系统已安装软件包版本的权威方法。在修复前后,我们都应该以 RPM 查询结果为准。
2.2 理解漏洞利用条件与风险评估
知道了版本号在受影响范围,我们还需要评估实际风险等级,这有助于安排修复的优先级。根据公开信息,CVE-2024-6387 的利用有几个关键限制:
- 架构依赖:已被证实的利用发生在32位(i686/x86)的 Linux 系统上。虽然理论上 64 位(x86_64)系统也可能存在风险,但截至目前,没有公开的、稳定的利用方式。不过,安全原则是“假定有风险”,所以 64 位系统同样需要修复。
- 环境要求:需要系统启用地址空间布局随机化(ASLR)。这是现代 Linux 发行版的默认安全特性,Rocky Linux 9 默认就是开启的。你可以通过
cat /proc/sys/kernel/randomize_va_space来确认,输出2表示完全启用。 - 攻击成本:在实验室环境下,成功利用平均需要维持6-8 小时的持续连接。这意味着它不是一个可以瞬间得手的“秒杀”漏洞,攻击者需要长时间、高频率地撞击服务器,通常会被IDS/IPS或异常连接监控发现。
- 服务状态:只有运行中的
sshd服务受影响。如果你的服务器虽然安装了 openssh-server 但并未启用(systemctl is-active sshd返回inactive),那么风险极低,但你仍然应该在启用前更新。
基于以上分析,我们可以制定修复策略:
- 面向公网、业务重要的 64 位服务器:高优先级。虽然利用难度大,但一旦被攻破后果严重。
- 内网服务器、开发测试环境:中优先级。可以安排在业务低峰期进行。
- 纯 32 位架构的系统:最高优先级。需要立即安排修复窗口。
- 未运行 sshd 的服务:低优先级,但应在下次启用前完成更新。
2.3 修复前的必要准备工作
“磨刀不误砍柴工”,在生产环境上动关键服务,准备工作必须做足。以下是修复前必须完成的检查清单:
备份现有 SSH 配置:这是最重要的步骤,防止更新过程中配置被意外重置或覆盖。
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)同时,也建议备份一下
.ssh/authorized_keys文件(对于root用户是/root/.ssh/authorized_keys,对于普通用户在各自家目录下)。确保你有替代的访问方式:在更新和重启 sshd 服务的过程中,如果配置有误或服务启动失败,你可能会失去 SSH 连接。对于物理服务器或云主机,请确保你拥有:
- 物理控制台访问(如 iDRAC, iLO, IPMI)。
- 云服务商提供的 VNC 或串口控制台(如 AWS EC2 的 Instance Connect, 阿里云/腾讯云的 VNC)。
- 通过跳板机(Bastion Host)或其他管理网络的访问途径。绝对不要在只有一条 SSH 通道的情况下,贸然重启关键生产服务器的 sshd 服务。
检查系统更新源:确保你的 Rocky Linux 9 系统能够正常访问官方更新仓库。执行
sudo dnf makecache测试一下。如果系统在内网,需要配置好内部镜像源。通知相关方:如果这是台业务服务器,务必提前通知业务负责人或团队成员,告知维护窗口和可能出现的短暂连接中断。
3. 修复方案详解与分步操作
对于 Rocky Linux 9 用户来说,修复这个漏洞非常直接,因为修复包已经进入了稳定仓库。我们不需要手动编译源码,也不需要添加额外的第三方仓库(在漏洞刚披露的短暂窗口期,可能需要通过security-common仓库获取,但现在已整合进主仓库)。下面是完整的、一步到位的修复流程。
3.1 标准修复流程(通过默认仓库)
这是最推荐、最简洁的修复方法。Rocky Linux 的更新机制会确保你获取到经过充分测试的稳定版本。
更新系统仓库元数据:首先,让 dnf 获取最新的软件包列表信息。
sudo dnf makecache检查可用的 openssh 更新:在正式更新前,可以先查看一下有哪些 openssh 相关的包可以升级。
sudo dnf check-update openssh\*这个命令会列出所有可更新的 openssh 相关包(openssh, openssh-server, openssh-clients 等),但不会执行任何更改。你应该能看到版本号至少升级到了
8.7p1-38.el9_4.1或更高。执行更新操作:使用
dnf upgrade命令来升级 openssh 及其相关组件。sudo dnf upgrade openssh openssh-server openssh-clients你也可以使用通配符来升级所有相关包,这更省事:
sudo dnf upgrade openssh\*执行命令后,dnf 会解析依赖关系,并显示将要升级的软件包列表和需要下载的大小。请仔细核对版本号,确认是升级到修复版本(如
8.7p1-38.el9_4.1)。输入y并回车确认。观察更新过程:更新过程中,dnf 会自动处理旧包的卸载和新包的安装。关键点来了:在安装
openssh-server新包时,安装脚本(%postscriptlet)通常会尝试重启 sshd 服务。你会看到类似Running scriptlet: openssh-server-...的输出。这意味着,在更新完成的瞬间,你的当前 SSH 会话可能会因为服务重启而短暂卡顿或断开。但别担心,因为 SSH 客户端具有连接保持和重连机制,绝大多数情况下你的当前连接会恢复。不过,正如之前强调的,有备用访问渠道至关重要。验证安装版本:更新完成后,立即验证安装的版本。
rpm -q openssh openssh-server openssh-clients预期的输出应该是:
openssh-8.7p1-38.el9_4.1.x86_64 openssh-server-8.7p1-38.el9_4.1.x86_64 openssh-clients-8.7p1-38.el9_4.1.x86_64只要版本号中的发布版本(
el9_4.1)等于或高于此版本,即说明漏洞已修复。确认服务状态:最后,检查 sshd 服务是否正常运行。
sudo systemctl status sshd你应该看到
Active: active (running)的状态,并且启动时间应该是刚刚更新之后。
3.2 修复方案原理解析:为什么直接dnf upgrade就够了?
很多朋友可能会问,网上有些教程提到要添加rocky-release-security仓库或者启用security-common仓库,为什么这里不需要?这里涉及到 Linux 发行版安全更新的发布流程。
- 安全更新的分级发布:当一个严重漏洞(如 CVE-2024-6387)被披露后,上游(RedHat)会迅速制作修复补丁。最初,这个补丁可能会先放在一个专门的安全测试仓库(如
security-common)中,供早期采用者和测试者使用。这时,如果你非常紧急,可以按照早期教程,手动启用这个仓库来获取更新。 - 进入稳定仓库:经过短暂的测试和验证,确认修复包与系统其他组件兼容良好后,这个安全更新就会被推送到默认的稳定仓库(如
baseos和appstream)。对于 Rocky Linux 9,在漏洞披露后不久,修复包openssh-8.7p1-38.el9_4.1就已经进入了稳定仓库。 dnf upgrade的工作机制:dnf upgrade命令默认会检查所有已启用的仓库(主要是baseos和appstream),并安装其中最新的版本。因此,当修复包进入稳定仓库后,最简单的sudo dnf upgrade openssh\*就能完成任务,无需任何额外配置。这也是最安全、最推荐的方式,因为它确保你获取的是经过完整质量保证的版本。
所以,如果你现在(距离漏洞披露已有一段时间)按照本文操作,直接更新即可。那些需要添加特殊仓库的步骤,是漏洞刚爆发时的“应急方案”,现在可以看作是过时了。
3.3 针对特殊环境的修复调整
虽然标准流程适用于99%的场景,但总有一些特殊情况需要考虑。
场景一:系统无法连接外网(离线环境)对于内网隔离的服务器,你需要搭建一个本地镜像仓库,或者手动下载 RPM 包进行离线安装。
在有网络的环境中下载 RPM 包:
# 在一个能联网的、同版本的 Rocky Linux 9 系统上 mkdir openssh_update cd openssh_update sudo dnf download openssh openssh-server openssh-clients --resolve这会将所有需要的包下载到当前目录。你需要将这些
.rpm文件拷贝到离线服务器。在离线服务器上安装:
# 在离线服务器上,进入存放 RPM 包的目录 sudo rpm -Uvh openssh-*.rpm-Uvh参数代表升级、显示详细信息、显示进度。注意,离线安装可能需要手动解决依赖关系,dnf download --resolve已经帮你下载了依赖包,所以一起安装即可。
场景二:使用了自定义编译的 OpenSSH极少数情况下,有的管理员可能卸载了发行版的 openssh,自己编译安装了新版。这时,你需要:
- 评估自定义版本的版本号是否在受影响范围(8.5p1 - 9.7p1)。
- 如果受影响,建议优先考虑回退到发行版提供的安全包,因为自行维护安全补丁风险很高。可以备份你的自定义配置和二进制文件,然后使用
sudo dnf install openssh openssh-server openssh-clients重新安装发行版包。 - 如果必须坚持自定义版本,则需要关注 OpenSSH 上游的补丁(到 9.8p1 版本已修复),并自行编译更新。这超出了本文范围,且不推荐在生产环境使用。
场景三:大规模服务器批量修复如果你管理着成百上千台 Rocky Linux 9 服务器,手动登录每一台操作是不现实的。这时需要借助自动化工具:
- Ansible:编写一个简单的 playbook。
- name: Patch CVE-2024-6387 on Rocky Linux 9 hosts: all become: yes tasks: - name: Upgrade OpenSSH packages dnf: name: "{{ item }}" state: latest loop: - openssh - openssh-server - openssh-clients notify: restart sshd handlers: - name: restart sshd systemd: name: sshd state: restarted enabled: yes - SaltStack / Puppet / Chef:使用对应的模块或 recipe 来确保
openssh包为最新版本。 - 脚本化批量执行:通过像
pssh、clustershell这样的工具,将sudo dnf upgrade openssh\* -y命令分发到所有主机。
无论用哪种方式,务必先在小范围测试环境中验证,确认更新不会导致业务中断或兼容性问题后,再分批推送到生产环境。
4. 修复后验证与安全加固建议
更新完软件包,服务也重启了,这就算完成了吗?远远不够。作为一个负责任的运维,我们必须进行闭环验证,并思考如何借此机会提升整体的 SSH 安全水位。
4.1 多维度验证修复是否生效
仅仅版本号对了还不够,我们需要从多个角度确认漏洞确实被堵上了。
版本号验证(再次确认):这是最基本的。
rpm -qa | grep ^openssh服务进程验证:检查正在运行的
sshd进程,其对应的二进制文件版本是否已更新。# 获取 sshd 主进程的 PID pidof sshd # 查看该 PID 对应可执行文件的路径和版本信息 sudo strings /proc/$(pidof sshd)/exe | grep -i openssh或者更直接地,使用
sshd自带的版本查询(注意,这可能显示的是编译时的版本,但也能佐证):sudo sshd -V 2>&1 | head -1漏洞扫描工具验证(可选但推荐):如果公司有 Nessus, OpenVAS, Qualys 等漏洞扫描器,可以在修复后对该服务器发起一次新的扫描,确认 CVE-2024-6387 的风险等级已从“高危”降为“已修复”或“低风险”。这是向安全团队和审计部门证明工作已完成的强有力证据。
功能性测试:更新后,务必测试 SSH 连接是否一切正常。
- 从不同的客户端(如 Linux 的 ssh 命令、Windows 的 PuTTY、VS Code Remote-SSH 等)进行连接测试。
- 测试各种认证方式:密码认证、公钥认证。
- 测试 SSH 隧道、端口转发等高级功能(如果业务用到的话)。
- 检查相关的自动化脚本或 CI/CD 流水线,确保它们使用的 SSH 连接仍然工作。
4.2 借此机会进行 SSH 安全加固
修复一个漏洞是“治标”,建立更稳固的安全配置才是“治本”。趁着这次更新,强烈建议你审查并加固服务器的 SSH 配置。
打开 SSH 服务器配置文件/etc/ssh/sshd_config,考虑以下加固选项(修改前请备份!):
sudo vi /etc/ssh/sshd_config关键加固项:
禁用密码登录,强制使用公钥认证:这是防止暴力破解最有效的一招。
PasswordAuthentication no PubkeyAuthentication yes注意:在关闭密码认证前,请确保所有需要登录的用户都已将其公钥添加到服务器的
~/.ssh/authorized_keys文件中,并且你自己有可用的私钥进行连接测试。否则会被锁在服务器外面!禁止 root 用户直接登录:即使使用密钥,也不建议直接用 root 登录。先以普通用户登录,再
su或sudo。PermitRootLogin no限制监听接口:如果服务器有多个网卡,但 SSH 只服务于内网,可以将其绑定到内网 IP,减少暴露面。
ListenAddress 192.168.1.100 # 替换为你的内网IP修改默认端口:将端口从 22 改为一个非标准端口,可以显著减少自动化扫描和攻击脚本的滋扰。
Port 2222 # 示例端口,请使用1024-65535之间的端口重要提示:修改端口后,必须在防火墙(firewalld/iptables)中开放新端口,并记得在连接时指定端口
ssh -p 2222 user@host。使用更强的密钥交换算法和加密算法:禁用已知不安全的旧算法。
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com使用 Fail2ban 阻止暴力破解:Fail2ban 可以监控 SSH 日志,短时间内多次失败尝试后,自动将攻击者 IP 加入防火墙黑名单。
sudo dnf install -y fail2ban sudo systemctl enable --now fail2ban配置通常位于
/etc/fail2ban/jail.local,你可以启用[sshd]部分。
每次修改sshd_config后,都需要重载配置或重启服务,并务必在另一个终端窗口保持一个有效的 SSH 连接,以防配置错误导致无法登录。
sudo systemctl reload sshd # 或者 sudo systemctl restart sshd sudo systemctl status sshd # 检查服务状态4.3 建立长期的安全更新机制
一次修复不能一劳永逸。我们应该建立机制,确保系统能持续、及时地获取安全更新。
启用自动安全更新(谨慎评估):对于开发测试环境或不那么关键的系统,可以考虑启用自动安全更新。
sudo dnf install -y dnf-automatic sudo systemctl enable --now dnf-automatic.timer生产环境警告:对于核心生产系统,不建议完全自动更新。安全更新虽然重要,但仍有极低概率引入兼容性问题。生产环境更佳实践是:自动下载但不安装,然后由运维人员在经过测试的维护窗口内手动安装。
定期手动更新与检查:建立例行工作,比如每周或每两周,手动检查并应用安全更新。
sudo dnf check-update --security # 仅检查安全更新 sudo dnf update --security # 仅安装安全更新订阅安全通告:关注 Rocky Linux 或上游 RedHat 的安全邮件列表、博客或 RSS,及时获取漏洞情报。
5. 常见问题排查与实操心得
在实际操作中,尤其是在复杂或老旧的生产环境里,你可能会遇到一些预料之外的问题。下面是我和同事们踩过的一些“坑”,以及对应的解决方案。
5.1 更新失败:依赖包冲突或损坏
问题现象:执行sudo dnf upgrade openssh\*时,报错提示依赖关系不满足、文件冲突,或者某个包损坏。
排查与解决:
清理 DNF 缓存并重建:有时元数据损坏会导致问题。
sudo dnf clean all sudo dnf makecache检查并修复 RPM 数据库:
sudo rpm --rebuilddb使用
dnf的疑难解答模式:dnf提供了更详细的错误信息。sudo dnf upgrade openssh\* -v --nobest-v显示详细信息,--nobest有时能绕过一些苛刻的版本依赖检查。手动强制安装(最后手段):如果确认是新包本身的问题,可以尝试从官方镜像站手动下载对应版本的 RPM 包,强制安装。但这种方法可能破坏依赖关系,需极其谨慎。
# 假设包已下载到本地 sudo rpm -Uvh --force openssh-8.7p1-38.el9_4.1.x86_64.rpm openssh-server-... openssh-clients-...
5.2 更新后 SSH 服务无法启动
问题现象:更新完成,但sudo systemctl status sshd显示服务失败,日志sudo journalctl -u sshd -xe中有错误信息。
常见原因与解决:
sshd_config语法错误:这是最常见的原因。可能在更新前后不小心修改了配置文件,或者更新包自带的默认配置与你的自定义配置冲突。- 解决方案:使用
sshd自带的语法检查工具。
这个命令会检查sudo sshd -t/etc/ssh/sshd_config的语法,并指出错误所在行。根据提示修复即可。如果之前有备份,可以快速回滚。
- 解决方案:使用
SELinux 上下文问题:在极少数情况下,更新后 SSH 相关的二进制文件或库文件的 SELinux 安全上下文可能不正确。
- 解决方案:恢复默认上下文。
sudo restorecon -Rv /etc/ssh /usr/sbin/sshd /usr/libexec/openssh
- 解决方案:恢复默认上下文。
端口被占用:如果你修改了 SSH 端口,而新端口已被其他程序占用。
- 解决方案:检查端口占用。
停止占用端口的进程,或为 SSH 选择另一个端口。sudo ss -tlnp | grep :2222 # 替换为你的端口号
- 解决方案:检查端口占用。
5.3 更新后连接速度变慢或出现超时
问题现象:更新后 SSH 连接建立变慢,或者偶尔超时。
排查思路:
检查 DNS 反向解析:OpenSSH 默认会尝试对客户端 IP 进行反向 DNS 解析。如果 DNS 服务器响应慢或不可达,就会导致连接延迟。
- 解决方案:在
sshd_config中禁用反向 DNS 解析。
修改后重启 sshd 服务。UseDNS no
- 解决方案:在
检查 GSSAPI 认证:如果客户端或服务器配置了 GSSAPI (Kerberos) 认证,且配置不当,也会在认证阶段引入延迟。
- 解决方案:如果不需要,可以禁用它。
GSSAPIAuthentication no
- 解决方案:如果不需要,可以禁用它。
防火墙规则:确认更新操作没有误删或影响防火墙规则。特别是如果你修改了 SSH 端口,必须确保新端口在防火墙(firewalld/iptables)中是放行的。
sudo firewall-cmd --list-all # 查看 firewalld 当前规则 sudo firewall-cmd --add-port=2222/tcp --permanent # 添加新端口(如果修改了) sudo firewall-cmd --reload
5.4 关于“自动重启服务”的深度理解
在更新openssh-server包时,RPM 的%post脚本会尝试重启服务。但这个“重启”行为可能因系统配置而异:
- 如果
sshd服务正在运行:脚本会执行systemctl try-restart sshd或类似命令,这通常会成功,导致你的会话短暂中断后恢复。 - 如果
sshd服务被systemctl mask屏蔽了:或者服务处于非活跃状态,RPM 脚本可能无法重启它。更新后你需要手动启动。 - 最佳实践:无论脚本是否成功,在更新完成后,手动检查并确认一次服务状态总是一个好习惯。
sudo systemctl is-active sshd # 应为 active sudo systemctl is-enabled sshd # 应为 enabled (开机自启)
5.5 个人实操心得与建议
- 变更窗口选择:对于在线业务,务必选择流量最低的维护窗口(例如深夜)。即使更新很快,也要预留出回滚和故障排查的时间。
- “先测试,后生产”铁律:永远先在非生产环境(开发、测试、预发布)验证更新流程和兼容性。可以用虚拟机克隆一份生产环境来做测试。
- 文档化操作步骤:像本文这样的操作指南,不仅可以帮助他人,更是你下次执行类似操作的检查清单。将验证命令(如
rpm -q openssh)也写入你的运维手册或自动化脚本中。 - 监控与告警:更新后,除了手动测试,还应该观察一段时间内的服务器监控指标(CPU、内存、网络连接数)和业务日志,确保没有异常。可以设置一个针对
sshd服务状态的简单告警。 - 保持敬畏之心:安全更新是运维的日常工作,但每一次操作都涉及风险。即使是一个简单的
dnf update,也可能因为仓库镜像不同步、网络问题或罕见的包冲突而出错。耐心、细致和充分的备份,是运维人员最好的朋友。
通过以上步骤,你不仅能够安全、彻底地修复 CVE-2024-6387 漏洞,更能将一次被动的漏洞响应,转化为一次主动的安全配置审计和加固机会,从而全面提升服务器的安全基线。