
简介本资源面向 Rocky Linux 9.5 系统运维人员与安全加固实践者针对旧版 OpenSSH 与 OpenSSL 存在的安全风险提供一套可直接落地的升级加固方案帮助读者在 x86_64 环境下完成 SSH 服务的高版本替换与安全配置。压缩包共 6 个文件包含 5 个 rpm 安装包与 1 个 sh 脚本涵盖 openssh、openssh-clients、openssh-server 等核心组件及 chkconfig、initscripts 依赖包整体约 10.96MB脚本负责串联升级流程rpm 包则用于替换系统自带旧版本。资源描述中展示了升级后 ssh -V 输出 OpenSSH_10.0p2 与 OpenSSL 3.5.0 的验证结果并附有 sshd 服务运行状态说明方案已在 Rocky Linux 9.5 上完成实测。目前已有 199 人学习适合需要快速完成 SSH 版本升级、减少手工编译排错成本的中高级运维人员参考也可作为内网安全加固的脚本模板。1. 从一次 SSH 升级翻车说起这套 RPM 脚本到底解决什么问题上个月帮一个朋友处理一台 Rocky Linux 9.5 的服务器OpenSSH 还停在系统自带的 8.7 版本扫描报告里一堆中危项全指着它。他之前自己手动编译升级过一次结果第二天 SSH 直接连不上只能跑机房挂 KVM 救回来。这种血泪经验在运维圈太常见了——源码编译 OpenSSH 看着简单但 PAM 模块路径、sshd_config 权限、SELinux 上下文、systemd 单元文件任何一个环节对不上就是把自己关在门外的节奏。这套rockylinux9.5-ssh10.0p1-ssl3.5.0-rpm-x86-64升级加固脚本就是冲着这个场景来的。它把 OpenSSH 10.0p1 和 OpenSSL 3.5.0 打包成 RPM在 Rocky Linux 9.5 x86_64 上做原地升级同时附带一套加固配置。适合两类人一是手里有 Rocky 9.5 机器、被合规扫描追着跑的运维二是想学 RPM 打包和 SSH 加固联动逻辑的工程师。它不解决“从零编译”的教学需求解决的是“别把自己锁在门外”的落地问题。2. 拆开 RPM 包看门道OpenSSH 10.0p1 与 OpenSSL 3.5.0 的依赖链2.1 为什么选 RPM 而不是源码编译源码编译 OpenSSH 的经典翻车点在于./configure时--with-ssl-dir指向的 OpenSSL 路径和运行时ldd /usr/sbin/sshd实际加载的库路径经常不一致。你编译时用的是/usr/local/ssl/lib64但 sshd 启动时LD_LIBRARY_PATH没带上它就去/lib64找系统自带的 OpenSSL 1.1版本对不上直接段错误。更隐蔽的是 PAM编译时--with-pam开了但pam.d/sshd文件没同步更新认证阶段静默失败日志里只留一句PAM: Authentication failure排查半天。RPM 方案的核心优势是把依赖关系写死在 spec 文件的Requires和Provides里。安装时rpm -ivh或dnf localinstall会自动校验 OpenSSL 版本、glibc 版本、PAM 库版本不满足直接拒绝安装不会出现“装完了才发现跑不起来”的情况。而且 RPM 的%post脚本可以自动处理sshd_config权限、生成 host key、重载 systemd这些手工步骤全被固化下来。2.2 包内文件布局与关键路径拿到 RPM 包后先别急着装。用rpm -qlp看一眼文件清单心里有数再动手# 查看 RPM 包内所有文件路径不实际安装 rpm -qlp openssh-10.0p1-ssl3.5.0.el9.x86_64.rpm | head -40 # 查看包的依赖声明确认 OpenSSL 版本要求 rpm -qRp openssh-10.0p1-ssl3.5.0.el9.x86_64.rpm | grep -i ssl # 查看包的元信息版本、构建时间、签名 rpm -qip openssh-10.0p1-ssl3.5.0.el9.x86_64.rpm这里有个细节rpm -qRp输出的依赖里如果出现libcrypto.so.3()(64bit)这种 soname 依赖说明包是动态链接到 OpenSSL 3.x 的。如果系统里还残留 OpenSSL 1.1 的 compat 包dnf可能会尝试同时满足两个版本导致冲突。常见做法是先dnf remove openssl-compat清理旧库再装新包。关键路径对照表路径作用升级后注意事项/usr/sbin/sshd主程序确认ldd指向新 OpenSSL/etc/ssh/sshd_config服务端配置权限必须 600属主 root/etc/ssh/ssh_config客户端配置一般不动除非要禁弱算法/etc/pam.d/sshdPAM 认证配置升级后检查是否被覆盖/usr/lib/systemd/system/sshd.servicesystemd 单元确认ExecStart路径正确/etc/ssh/ssh_host_*_key主机密钥升级不会自动重建除非手动删2.3 升级前的快照与回滚准备RPM 升级虽然比源码编译可控但也不是没有后悔药。动手前先做三件事# 1. 备份当前 sshd 配置和二进制 cp -a /etc/ssh /etc/ssh.bak.$(date %Y%m%d) cp -a /usr/sbin/sshd /usr/sbin/sshd.bak # 2. 记录当前版本和依赖关系 rpm -qa | grep -E openssh|openssl /root/pkg-before.txt ldd /usr/sbin/sshd /root/ldd-before.txt # 3. 确认当前 SSH 会话不会被中断关键 # 不要在生产环境直接重启 sshd先用新端口起一个测试实例 /usr/sbin/sshd -f /etc/ssh/sshd_config -p 2222 -t第三步的-t是语法检查-p 2222是临时端口。如果语法检查通过再用-p 2222实际启动一个测试实例从另一个终端连上去验证确认没问题再替换主服务。这个习惯我每次升级 SSH 都强制走一遍能挡掉八成“改完连不上”的事故。3. 加固配置落地从 sshd_config 到 PAM 的逐项调优3.1 sshd_config 核心加固项与参数含义OpenSSH 10.0p1 的默认配置比 8.x 严格了不少但离合规要求还有距离。下面这份配置是我在多个 Rocky 9.5 环境里验证过的直接抄# /etc/ssh/sshd_config 关键加固段 Protocol 2 Port 22 AddressFamily inet ListenAddress 0.0.0.0 # 认证策略 PermitRootLogin no PubkeyAuthentication yes PasswordAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no UsePAM yes # 算法限制只保留强加密套件 KexAlgorithms curve25519-sha256,curve25519-sha256libssh.org,diffie-hellman-group16-sha512 Ciphers chacha20-poly1305openssh.com,aes256-gcmopenssh.com,aes128-gcmopenssh.com MACs hmac-sha2-512-etmopenssh.com,hmac-sha2-256-etmopenssh.com # 会话限制 LoginGraceTime 30 MaxAuthTries 3 MaxSessions 5 ClientAliveInterval 300 ClientAliveCountMax 2 # 日志与转发 SyslogFacility AUTH LogLevel VERBOSE X11Forwarding no AllowAgentForwarding no AllowTcpForwarding no逐项说明几个容易踩坑的PermitRootLogin no是硬要求但改之前确认你有普通用户能 sudo否则重启后 root 登不上、普通用户也没配就真进不去了。PasswordAuthentication no意味着必须提前把公钥塞进~/.ssh/authorized_keys而且权限必须是 700目录和 600文件属主是用户自己否则 sshd 会静默拒绝。KexAlgorithms里我保留了diffie-hellman-group16-sha512因为有些老旧的网络设备只支持这个。如果你的环境全是新客户端可以只留 curve25519。MACs里的-etm后缀是 encrypt-then-MAC比传统 MAC 更安全但极老的客户端可能不支持。3.2 PAM 与 SELinux 的联动检查改完sshd_config别急着重启先过一遍 PAM 和 SELinux# 检查 PAM 配置是否引用了正确的模块路径 grep -E pam_unix|pam_sss|pam_faillock /etc/pam.d/sshd # 确认 SELinux 上下文正确 ls -Z /usr/sbin/sshd /etc/ssh/sshd_config # 期望输出类似system_u:object_r:sshd_exec_t:s0 /usr/sbin/sshd # 如果上下文不对手动修复 restorecon -Rv /etc/ssh /usr/sbin/sshd # 检查 SELinux 是否阻止了 sshd 绑定端口 ausearch -m avc -ts recent | grep sshdRocky 9.5 默认开 SELinux enforcing。RPM 安装时%post脚本通常会调restorecon但如果你之前手动改过/etc/ssh下的文件上下文可能被破坏。ls -Z看到default_t而不是sshd_exec_tsshd 启动就会被拒。ausearch那条命令是排查 SELinux 拒绝的万能钥匙任何“配置都对但就是起不来”的情况先看这里。3.3 用 sshd -T 做配置有效性验证OpenSSH 10.0p1 的sshd -T比老版本输出更详细能直接看到生效的最终配置# 以测试模式输出最终生效配置不实际启动服务 /usr/sbin/sshd -T -f /etc/ssh/sshd_config | grep -E permitrootlogin|passwordauth|kexalgorithms|ciphers|macs # 如果配置文件有语法错误-t 会直接报错并指出行号 /usr/sbin/sshd -t -f /etc/ssh/sshd_config-T的好处是它会把 include 的文件、默认值全部展开你看到的就是 sshd 实际用的。有时候你在sshd_config里写了PasswordAuthentication no但/etc/ssh/sshd_config.d/下有个 50-cloud-init.conf 又把它改回 yes-T一跑就露馅。Rocky 9.5 默认会加载sshd_config.d/*.conf这个目录里的文件优先级比主配置高升级后务必检查。4. 避坑排查升级 SSH 时最容易翻车的五个点4.1 现象重启 sshd 后当前会话断开新连接被拒原因sshd_config里ListenAddress或Port改了但防火墙没放行新端口或者AllowUsers/AllowGroups限制了来源而当前用户不在列表里。解决永远不要直接systemctl restart sshd。先用sshd -p 2222 -t测试再sshd -p 2222起临时实例从另一个终端连 2222 验证。确认无误后用systemctl reload sshd不是 restart平滑加载。如果已经锁死只能通过 KVM 或串口进单用户模式改回来。4.2 现象公钥认证失败日志显示 “Authentication refused: bad ownership or modes”原因~/.ssh或authorized_keys权限不对。sshd 对权限极其敏感目录必须是 700文件必须是 600且属主必须是登录用户本人不能是 root 或其他用户。解决chmod 700 /home/username/.ssh chmod 600 /home/username/.ssh/authorized_keys chown -R username:username /home/username/.ssh # 同时检查家目录本身不能是 group-writable chmod g-w /home/username4.3 现象升级后 root 无法登录普通用户 sudo 也报错原因PermitRootLogin no生效了但普通用户的 sudo 权限没配好或者 PAM 的pam_faillock模块因为多次失败把账户锁了。解决升级前务必确认至少有一个普通用户能sudo su -。如果已经被锁进单用户模式后faillock --user username --reset解锁。PAM 配置里pam_faillock的deny3和unlock_time900是默认值可以根据需要调整。4.4 现象sshd 启动报 “error while loading shared libraries: libcrypto.so.3”原因OpenSSL 3.5.0 的 RPM 没装或者装了但ldconfig缓存没更新sshd 找不到新库。解决# 确认 OpenSSL 3.5.0 已安装 rpm -qa | grep openssl # 更新动态链接器缓存 ldconfig -v | grep libcrypto # 如果还是找不到手动指定库路径测试 LD_LIBRARY_PATH/usr/local/ssl/lib64 ldd /usr/sbin/sshd | grep crypto4.5 现象SELinux 导致 sshd 无法绑定端口或读取 host key原因RPM 安装时%post脚本没执行restorecon或者手动拷贝文件时丢了上下文。解决# 查看拒绝日志 ausearch -m avc -ts today | grep sshd # 恢复默认上下文 restorecon -Rv /etc/ssh /usr/sbin/sshd /var/empty/sshd # 如果还不行临时设为 permissive 确认是否是 SELinux 问题 setenforce 0 # 确认后记得改回 enforcing setenforce 15. 进阶技巧用 RPM 脚本做批量加固与版本回滚5.1 把加固配置写进 RPM 的 %post 脚本如果你要在多台机器上批量部署手动改sshd_config太慢。可以把加固逻辑写进 RPM 的%post段安装时自动执行# 在 spec 文件的 %post 段中加入 %post # 备份原配置 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.rpmsave # 用 sed 批量替换关键项 sed -i s/^#*PermitRootLogin.*/PermitRootLogin no/ /etc/ssh/sshd_config sed -i s/^#*PasswordAuthentication.*/PasswordAuthentication no/ /etc/ssh/sshd_config sed -i s/^#*MaxAuthTries.*/MaxAuthTries 3/ /etc/ssh/sshd_config # 确保权限正确 chmod 600 /etc/ssh/sshd_config chown root:root /etc/ssh/sshd_config # 语法检查失败则回滚 if ! /usr/sbin/sshd -t -f /etc/ssh/sshd_config; then cp /etc/ssh/sshd_config.rpmsave /etc/ssh/sshd_config echo sshd_config syntax error, rolled back 2 exit 1 fi # 平滑重载 systemctl reload sshd || systemctl restart sshd这段脚本的关键在于sshd -t失败时自动回滚。很多批量升级事故就是因为配置写错了但没人发现直到重启后所有机器都连不上。加上这个判断至少能保证配置语法层面不出问题。5.2 版本回滚用 dnf history 撤销升级RPM 体系最大的好处就是有后悔药。如果升级后发现兼容性问题可以回滚# 查看 dnf 操作历史找到升级那一步的 ID dnf history list | head -20 # 假设升级操作 ID 是 15回滚到之前的状态 dnf history undo 15 # 如果 dnf history 不够用直接降级 RPM 包 rpm -Uvh --oldpackage openssh-8.7p1-38.el9.x86_64.rpm # 恢复备份的配置 cp -a /etc/ssh.bak.20250101/* /etc/ssh/ systemctl restart sshddnf history undo会自动处理依赖关系比手动rpm -Uvh --oldpackage更干净。但注意如果升级后已经改了配置文件undo 不会恢复配置需要手动从备份还原。5.3 验证加固效果的三个命令升级加固完别只看systemctl status显示 running 就完事。用这三个命令做最终验证# 1. 确认实际生效的算法列表 ssh -vvv localhost 21 | grep -E kex: algorithm|ciphers: |mac: # 2. 确认版本号 ssh -V # 3. 用 nmap 从外部扫描确认没有弱算法暴露 nmap --script ssh2-enum-algos -p 22 target_ip第一条命令的-vvv会打印握手细节你能看到实际协商的 kex、cipher、mac 是不是你配置里指定的那些。如果出现了diffie-hellman-group14-sha1这种弱算法说明配置没生效大概率是sshd_config.d/下有文件覆盖了。第三条用 nmap 从外部视角看更接近扫描器的判断逻辑。从那以后我每次升级 SSH都强制走一遍“备份 → 临时端口测试 → sshd -T 验证 → 外部扫描确认”的流程再也没被锁在门外过。希望帮到你。本文还有配套的精品资源点击获取