首页 / 资讯中心 / 文章详情

OpenSSH 10.0p1 RPM打包升级实践:等保合规下的安全加固

OpenSSH 10.0p1 RPM打包升级实践:等保合规下的安全加固 ★ FEATURED ARTICLE
简介在Rocky Linux 9.5Blue Onyxx86_64正式环境下这份OpenSSH/OpenSSL升级加固资源包面向系统运维与安全管理人员用于解决默认SSH组件版本偏低、被扫描出安全漏洞以及手动编译升级依赖复杂等痛点目标是将服务快速升级到OpenSSH 10.0p1和OpenSSL 3.5.0并对sshd服务完成基础加固。资源压缩包内共包含6个文件由5个RPM安装包和1个Shell脚本组成整体压缩包体积仅约10.96MBRPM包覆盖openssh服务端、客户端以及chkconfig、initscripts等关键依赖脚本则按照正确顺序自动安装RPM、更新启动方式并接入systemd管理省去了源码编译时匹配编译器和库版本的大量工作。目前已有205人学习下载特别适合Rocky Linux 9.5服务器批量升级加固场景。使用者仅需将资源上传至目标机器后执行脚本即可获得稳定运行的SSH服务并保持开机自启后续可通过systemctl status sshd确认运行状态对于等保整改、漏洞修复后需快速收敛风险的运维团队而言这是一条低成本、低难度的升级路径。1. 升级 OpenSSH 不只是换版本等保复查把我逼成了 RPM 流水线某次等保复测扫描器把系统自带的 OpenSSH 8.7p1 翻了个底朝天光高危 CVE 就列了好几页评审意见很直接升级到已修复版本。可生产机不是测试机直接在源码目录 make install 会让 rpm 数据库再也管不住 ssh下回安全加固又要重新折腾一遍。最后我把 OpenSSH 10.0p1 配着 OpenSSL 3.5.0 一起打成 rpm做成一套 openssh 加固升级脚本让版本、依赖、加固项全部变成可重复执行的产物。这篇文章就是整套流程的拆解笔记适合正在做等保整改、又不想被源码编译坑第二次的运维和交付工程师。2. 升级前环境摸底与依赖排雷三个命令看清现状再动手2.1 版本摸底看系统、看 OpenSSL、看 SELinux动手之前先把家底盘清楚。我一般会在目标机器上依次跑下面这组命令输出结果存到临时文件里作为升级前的快照。cat /etc/redhat-release ssh -V 21 openssl version getenforce systemctl is-active sshd ss -lntp | grep :22ssh -V和openssl version分别确认当前 SSH 与服务端依赖的 OpenSSL 版本getenforce看 SELinux 是 Enforcing 还是 Disabled这个状态决定了后面要不要做上下文恢复systemctl is-active sshd确认服务当前是正常的避免升级过程中带着一个半死不活的进程操作最后ss检查 22 号端口实际监听情况。这套命令的价值在于给升级画一条基线。如果原环境里 sshd 的配置已经被前人改得面目全非或者防火墙规则本身就没放行升级后再排查就没法判断是升级引入的问题还是历史遗留问题。我见过有人跳过这一步直接上生产结果升级完才发现是旧版本身就起不来白忙一晚上。2.2 安装编译依赖缺 dev 包会让你在 90% 时报错尤其是 pam-develOpenSSH 的 RPM 打包依赖一堆开发库缺哪个都在编译中段才报错非常消耗耐心。我在 Rocky Linux 9.5 上通常一次性装齐。dnf groupinstall -y Development Tools dnf install -y rpm-build rpmdevtools \ pam-devel zlib-devel libselinux-devel \ krb5-devel ncurses-devel gcc make perl这里重点说说几个包的用途。pam-devel是给--with-pam用的少了它就算 configure 能过make 也会在 pam 相关文件上报错而且报错信息很容易让人误以为是代码问题。libselinux-devel对应--with-selinux在 Enforcing 模式下编译时如果缺少这个包生成的二进制会对 SELinux 策略支持不完整。rpm-build与rpmdevtools提供 rpmbuild 和目录初始化命令krb5-devel用于 GSSAPI 认证支持如果公司内部有基于 Kerberos 的认证体系这个包必须装。装依赖有个习惯性问题不要图快把* -devel全部装上。全量安装虽然能少报错但会引入大量无关库RPM 打包时%files列表会变得很难控制最后打出来的 rpm 可能带着一堆本不需要的.so依赖。2.3 备份与回滚预案主机密钥和原版 RPM 就是你的后悔药升级 OpenSSH 最怕的不是编译失败而是升级后连不上机器。所以在编译之前我必须先把三样东西备份好原版 RPM 包、配置文件、主机密钥。mkdir -p /root/backup-ssh-$(date %Y%m%d) cd /root/backup-ssh-$(date %Y%m%d) rpm -qa | grep -E ^(openssh|openssl) rpm-list.txt cp -a /etc/ssh /root/backup-ssh-$(date %Y%m%d)/etc-ssh cp -a /etc/pam.d/sshd /root/backup-ssh-$(date %Y%m%d)/ tar czf ssh-host-keys.tar.gz /etc/ssh/ssh_host_*rpm -qa导出的清单专门用于回滚时对照原版本号。有些厂内镜像源保留了旧版本 rpm回滚时直接dnf install旧版本号即可如果源里没有就要靠rpm -Uvh强制装回备份的 rpm 文件。/etc/ssh整个目录复制保存因为里面除了配置文件还有ssh_host_*密钥和moduli文件。主机密钥尤其重要不备份的话升级后重启 sshd 会重新生成新密钥客户端会出现 host key 变更告警逼着用户去核对指纹。备份完我会顺手tar tzf ssh-host-keys.tar.gz看一眼包内文件是否完整这一步花十秒钟却能避免回滚时才发现在备份环节就翻车的尴尬。3. 编译 OpenSSL 3.5.0 并打入 RPM这个前置步骤不做好后面全白搭3.1 为什么不能直接让 OpenSSH 10.0p1 链系统自带的 OpenSSLRocky Linux 9.5 自带的 OpenSSL 版本通常是 3.0.x理论上 OpenSSH 10.0p1 可以链接它编译通过。但实际生产中我们要考虑两件事一是新版 OpenSSH 对某些密码学算法有更强的偏好依赖新版本库的特性二是直接升级系统 OpenSSL 会牵连 Nginx、Apache、PostgreSQL 等大量服务风险不可控。我采用的方案是给 OpenSSL 3.5.0 指定独立安装路径/opt/openssl让 OpenSSH 单独链接这套新库。这样系统自带的 OpenSSL 保持不动其他服务继续走旧库互不影响。代价是编译 OpenSSH 时要明确指定--with-ssl-dir/opt/openssl并且处理运行时动态库搜索路径。很多人会在这一步图省事直接 ./configure 然后 make install 把 OpenSSL 装到/usr/local就完事。这个做法不是不行但后续维护时/usr/local/lib64会被各种手动编译的库塞满而且 rpm 数据库里完全没有记录想彻底卸载只能手动清文件。所以我坚持把 OpenSSL 也打成 rpm至少卸载和升级是有据可查的。3.2 Configure 参数拆解与 RPM 化打包先看编译 OpenSSL 3.5.0 的 Configure 命令。这里我选了linux-x86_64平台配置这是 OpenSSL 官方提供的最贴近 Rocky Linux 9.5 的 x86_64 配置。cd /root/rpmbuild/BUILD/openssl-3.5.0 ./Configure linux-x86_64 \ --prefix/opt/openssl \ --openssldir/opt/openssl \ enable-fips \ no-ssl2 no-ssl3 no-sctp \ shared make -j$(nproc) make install_sw install_ssldirs DESTDIR/root/rpmbuild/BUILDROOT/openssl-3.5.0--prefix/opt/openssl指定了安装根目录所有头文件、库和二进制都落在这个目录下。enable-fips是很多等保单位和金融机构的硬性要求开启后系统里会有openssl fipsinstall可用来做 FIPS 模式校验。no-ssl2 no-ssl3是安全基线直接禁用这两个已经淘汰的协议版本避免后续扫描又报 CVE。注意最后一行我用了DESTDIR指定了打包用的 buildroot 路径。RPM 打包时不会直接往系统写入文件而是先装进这个临时目录再由 rpmbuild 从这里取文件打入包内。这是规范做法少了这一步rpmbuild 只能去系统路径里找文件就会出现编译成功但打包空壳的怪象。打包对应的 spec 文件我一般新建一个openssl-3.5.0.spec%files段直接引用/opt/openssl下的实际文件即可。Release 号我习惯设为自定义值比如1.rocky9方便和官方源里的包区分。3.3 ldconfig 与 PATH装错位置比不装更吓人OpenSSL 装完后第一件事是把新库的路径写进动态链接器配置。echo /opt/openssl/lib64 /etc/ld.so.conf.d/openssl-3.5.0.conf ldconfig ldconfig -p | grep libcryptoldconfig会刷新系统的动态链接器缓存让运行在默认环境下的程序也能根据libcrypto.so.3这样的名字找到/opt/openssl/lib64下的库文件。最后一行 grep 是为了确认新库已被加载如果输出里同时出现多个路径下的libcrypto.so.3就要留意链接顺序问题。有一个很容易踩的坑不要为了验证就把/opt/openssl/bin加进/etc/profile的 PATH或者直接替换/usr/bin/openssl。系统里很多脚本和程序依赖/usr/bin/openssl的特定输出格式你切到 3.5.0 后某些命令的输出格式变了可能导致上层应用判断异常。要验证新版本直接调用全路径/opt/openssl/bin/openssl version即可这才是最安全的方式。/opt/openssl/bin/openssl version OpenSSL 3.5.0 1 Jan 2025 (Library: OpenSSL 3.5.0)如果输出里的版本号和编译时一致说明安装链路是通的。另外建议顺手跑一遍make testOpenSSL 的测试套件覆盖很全虽然耗时大概十几分钟但能提前暴露 FIPS 模块没装好、某些算法在 x86_64 上行为异常这类问题。编译 OpenSSH 前先让 OpenSSL 通过测试后面少熬夜。4. 打包 OpenSSH 10.0p1 的 RPM从 spec 修改到生产上线4.1 准备 rpmbuild 目录结构官方 spec 需要大改OpenSSH 源码包里自带一份openssh.spec但它默认针对的是 OpenSSH 的通用环境很多参数没适配 Rocky Linux 9.5。我一般这样初始化目录并放置源码。rpmdev-setuptree cp openssh-10.0p1.tar.gz /root/rpmbuild/SOURCES/ cp openssh.spec /root/rpmbuild/SPECS/rpmdev-setuptree会自动创建BUILD、BUILDROOT、RPMS、SOURCES、SPECS五个目录。源码包放进SOURCESspec 放进SPECS。注意源码包文件名必须和 spec 里的Source0一致否则 rpmbuild 直接报错找不到文件。官方 spec 里可能还会引用openssh-10.0p1.tar.gz之外的补丁文件例如 PAM 相关的补丁。如果源码包里没有单独提供这些补丁我建议直接把 spec 里的Patch0、Patch1等对应的行注释掉然后基于系统自带的 openssh 配置逻辑重新补 PAM 设置。不要试图把一个给其他发行版用的补丁强行打在 Rocky Linux 上会打出一堆语义冲突。4.2 修改 spec 文件configure 段是整份文件的心脏spec 文件里最关键的是%configure段。官方默认可能是直接./configure我需要显式指定新 OpenSSL 路径、PAM、SELinux 支持。%build ./configure \ --prefix/usr \ --sysconfdir/etc/ssh \ --with-ssl-dir/opt/openssl \ --with-pam \ --with-selinux \ --with-md5-passwords \ --with-privsep-path/var/empty/sshd \ --with-systemd make -j$(nproc)--prefix/usr让 ssh 命令、sshd 服务都装在标准位置这样systemctl能找到服务文件/usr/bin/ssh也能被现有调用脚本找到。--sysconfdir/etc/ssh保证配置文件路径和旧版一致不会出现配置漂移。--with-ssl-dir/opt/openssl是这次升级的核心参数直接指定头部和库的搜索路径。--with-pam保留系统 PAM 认证流程--with-selinux配合 Enforcing 模式。--with-privsep-path/var/empty/sshd指定特权分离目录。/var/empty/sshd这个目录是 OpenSSH 运行时的降权目录它的属主必须是 root权限必须是 755。打包安装脚本里我会顺手加上目录创建和权限修正mkdir -p /var/empty/sshd chmod 755 /var/empty/sshd chown root:root /var/empty/sshd如果这个目录的属主或权限不对sshd 启动时会提示权限太开放或目录不存在属于很隐蔽的坑日志里只会出现一句含糊的privilege separation directory报错。4.3 rpmbuild 到上线永远是 rpm -Uvh不是 rpm -espec 改好后开始编译这一步会调用编译器把 OpenSSH 源码打成二进制 rpm。rpmbuild -ba /root/rpmbuild/SPECS/openssh.spec ls /root/rpmbuild/RPMS/x86_64/-ba参数表示同时构建二进制包和源码包。如果编译过程中报错优先查看BUILD目录下的 config.log里面是 configure 阶段输出的详细日志比终端里的报错信息完整得多。编译产物一般会包含openssh、openssh-server、openssh-clients、openssh-askpass等几个 rpm。安装时我要强调一个反直觉的点不要写rpm -e openssh-server再rpm -ivh新包。删除再装会让/etc/ssh/sshd_config从系统里消失新包安装时如果检测不到旧配置会选择使用默认配置你的历史加固项全部失效。正确做法是直接升级rpm -Uvh /root/rpmbuild/RPMS/x86_64/openssh-*.rpm systemctl daemon-reload systemctl restart sshd ssh -Vrpm -Uvh是升级模式会保留原配置文件并在必要时生成.rpmnew文件存放新版的配置差异。systemctl daemon-reload强制 systemd 重新加载服务文件避免新安装的服务单元没被识别。重启后立刻ssh -V确认版本这是最直接的验收。5. 避坑清单编译之后、重启之前最容易翻车的五个位置5.1 起不来libcrypto.so.1.1 加载失败现象rpm 安装完成后执行systemctl restart sshd终端报错/usr/sbin/sshd: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file。原因sshd 二进制在编译时链接到了系统原有的 OpenSSL 3.0 库运行时却找不到对应的libcrypto.so.1.1版本号。这通常是因为 spec 里的--with-ssl-dir没生效或者 rpath 没写入二进制。解决先用ldd /usr/sbin/sshd | grep -E crypto|ssl看实际链接路径。如果指向/usr/lib64而不是/opt/openssl/lib64说明编译时没找对新 OpenSSL。一个临时补救办法是用 chrpath 修改二进制的 rpathchrpath -r /opt/openssl/lib64 /usr/sbin/sshd systemctl restart sshd但这不是长久之计rpath 会被 RPM 升级覆盖。彻底方案是回到 spec 里确认 configure 确实带上了--with-ssl-dir/opt/openssl并检查编译日志里有没有显式提示找到了新版本头文件然后重新 rpmbuild。5.2 SELinux 上下文端口在听防火墙放行你依旧连不上现象sshd 进程正常监听 22 端口firewalld 也放行了 ssh 服务但客户端连接始终卡在认证阶段日志里没有明显报错只有 SELinux 的avc: denied记录。原因OpenSSH 用 RPM 升级后/etc/ssh下部分文件或/usr/sbin/sshd本身的安全上下文是usr_t或etc_t而不是 SSHD 需要的sshd_exec_t、sshd_etc_t。SELinux 在 Enforcing 模式下直接拦截。解决对关键路径做一次递归恢复上下文。restorecon -Rv /etc/ssh /usr/sbin/sshd /var/empty/sshd ls -Z /usr/sbin/sshdrestorecon会从 SELinux 策略数据库里读取正确标签并应用。ls -Z验证结果正常时 sshd 的标签应该是system_u:object_r:sshd_exec_t:s0。这一步应该在 rpm 安装完、重启服务前就做否则就会出现端口通了却连不进去的尴尬局面。5.3 PAM 认证锁人密码正确也被拒现象升级完成后用户输入正确的密码也登录不进去journalctl -u sshd显示类似pam_unix(sshd:auth): authentication failure。原因编译时没加--with-pam导致 sshd 编译的 PAM 支持不完整或者/etc/pam.d/sshd文件里引用了新版本不存在的模块。Rocky Linux 9.5 默认的 PAM 配置里包含pam_unix.so和pam_systemd.so如果编译时没有把 systemd 相关支持链进去就会出现认证通过但会话建立失败的情况。解决先确认/etc/pam.d/sshd存在权限 644属主 root。然后查看编译时是否带了--with-pam和--with-systemd。如果没带重新配置再打包。临时应急可以先把系统原有 PAM 配置恢复备份再重启服务cp /etc/pam.d/sshd.rpmnew /etc/pam.d/sshd 2/dev/null systemctl restart sshd把.rpmnew覆盖回主配置是快速让 PAM 恢复可用的手段但覆盖前建议 diff 对比一下新旧配置的差异别把新版本特意加固的 PAM 逻辑又覆盖掉了。5.4 把自己锁门外回滚窗口这样开现象远程操作时执行完rpm -Uvh和systemctl restart sshd连接突然断开之后再连就报错或超时整个人被锁在机房外面。原因新配置里PasswordAuthentication no直接生效而你的公钥没写进 authorized_keys或者主机密钥变了导致客户端拒绝连接。解决升级前先开一个不依赖 ssh 的带外会话比如机房控制台或云厂商的 VNC。同时在远程会话里设置一个延迟回滚的定时任务给自己留 120 秒后悔药。(sleep 120 rpm -Uvh /root/backup-ssh-$(date %Y%m%d)/openssh-*.rpm systemctl restart sshd) 这条命令会在 120 秒后自动降级回原版本并重启服务。如果这条命令执行前你就发现新环境有问题在它触发前手动连接另一个会话敲kill %1取消回滚即可。注意这行命令应该在升级操作前就挂起来不是升级失败后才写。5.5 firewalld 没放行服务起来了却出不了门现象升级后ss -lntp显示 sshd 在 22 端口正常监听但客户端连接直接超时防火墙运维检查也没看到明显拦截。原因原环境 firewalld 一直开着但之前 sshd 是通过旧版本 RPM 安装时自动注册的 service 规则放行。升级后新 RPM 的服务文件路径变了firewalld 里虽然写着 ssh 服务实际匹配的端口服务上下文没有刷新。解决不要依赖 firewalld 的自动集成手动放行并验证。firewall-cmd --permanent --add-servicessh firewall-cmd --reload firewall-cmd --list-all--add-servicessh会添加基于服务名的放行规则--reload使规则生效。最后--list-all检查输出里是否同时存在ssh服务。如果公司安全策略要求限定来源 IP可以改成firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.0/24 service namessh accept比全量放行更稳妥。6. 最后的落地把验证做成脚本把回滚变成习惯6.1 十分钟一键巡检脚本升级加固完成不等于结束等保复查时对方要的是可验证的审计结果。我习惯把版本、端口、加固项、SELinux、防火墙这些检查点写成一个脚本每次维护后跑一遍输出贴在变更单里即可。#!/bin/bash # sshd 升级加固巡检脚本 echo SSH 版本 ssh -V 21 echo 监听端口 ss -lntp | grep sshd echo 关键加固项 grep -E ^(PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|MaxAuthTries|ClientAliveInterval|X11Forwarding) /etc/ssh/sshd_config echo SELinux 上下文 ls -Z /usr/sbin/sshd echo 防火墙放行 firewall-cmd --list-all | grep services脚本里的grep -E只匹配形如PermitRootLogin no这类没有被注释掉的配置项。加固项预期值应该是PermitRootLogin no、PasswordAuthentication no、PubkeyAuthentication yes、MaxAuthTries 4、ClientAliveInterval 300、X11Forwarding no。如果输出里某一项没出现说明它被注释了当前生效的是编译默认值需要手动打开。在脚本开头先跑版本检查是因为 ssh 版本偶发回退并不显而易见——比如某个后续 yum 操作把旧版拉回来。把这组检查脚本放进 cron 每周跑一次输出追加到/var/log/ssh-audit.log比临时抱佛脚靠谱得多。6.2 回滚的肌肉记忆我第一次做 OpenSSH 升级时也翻过车在没开带外会话的情况下直接远程重启了 sshd结果断连后只能在机房门口吹冷风。从那以后我每次做 ssh 升级都强制自己先走一遍固定流程备份三件套、开带外通道、挂延迟回滚、验证巡检脚本全部就绪才碰rpm -Uvh。这套流程现在基本成了肌肉记忆哪怕只有一台测试机也照走一遍。另外有个细节值得一提升级后第一次测试登录时尽量用一个新的本地会话窗口不要复用升级前那个连接。旧连接经过 sshd 重启后状态本身就不可靠复用它会让你误判新服务是否正常。用新窗口重连能连上就说明整条链路通了。这个习惯救过我好几回希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站