简介:这份资源面向在CentOS7环境下从事系统运维与安全加固的技术人员,聚焦OpenSSH升级至10.0p2、OpenSSL升级至3.0.16的完整实践,帮助解决旧版本存在的安全补丁缺失与加密能力不足问题。资源包共3个文件,以html操作指南为主体,辅以inscode工程配置与gitignore忽略规则,压缩包约6KB,轻量易取,适合按文档逐步对照执行。内容覆盖升级前的依赖准备、zlib与OpenSSL及OpenSSH的下载编译安装、旧版本备份、编译参数配置、动态库链接设置,以及版本校验和sshd服务启动异常的排查思路,并特别提示无网络或远程升级时先开启telnet保障登录通道。目前已有116人学习,适合需要远程完成系统组件升级、关注兼容性与回滚方案的中高级运维人员参考。
1. CentOS7 升级 OpenSSH:为什么老系统的这个操作总让人手心冒汗
在 CentOS7 上做 OpenSSH 升级,是很多运维和交付工程师绕不开的一件事。系统自带的 OpenSSH 版本往往停留在 7.4 附近,而安全扫描、等保测评、合规基线检查里,关于 SSH 的条目又特别多,于是「升级 OpenSSH」就成了一个高频需求。麻烦的地方在于:SSH 是你连上这台机器的唯一通道,升级过程一旦把 sshd 弄挂,或者把配置文件、密钥权限搞乱,你下一次就登不进去了。这不是危言耸听,我见过不止一次因为升级中途断开连接、又没留后手,最后只能走带外控制台救场的案例。
这篇笔记面向的是手上有 CentOS7 机器、需要把 OpenSSH 升到较新版本、又希望过程可控可回滚的从业者。核心思路只有一条:用 RPM 打包的方式升级,而不是直接 make install 覆盖系统文件。前者能进 yum 数据库、能回滚、能保留原有配置;后者装完一时爽,出问题时连卸载都找不到入口。下面从原理、打包、安装、避坑到验证,一步步拆开讲,命令和参数都给全,照着做基本能复现。
2. 升级前必须想清楚的三件事:版本、依赖与回滚
2.1 为什么优先选 RPM 打包而不是源码编译安装
源码编译安装 OpenSSH 看起来最直接:./configure && make && make install,几分钟搞定。但在 CentOS7 这种用 RPM 管理软件包的系统上,它有几个致命问题。第一,make install默认会把新文件写到/usr/local下,而系统 sshd 服务读的是/usr/sbin/sshd、/etc/ssh/sshd_config,两边对不上,你以为升级了,实际跑的还是老版本。第二,源码安装不会更新 RPM 数据库,rpm -q openssh查出来还是旧版本,安全扫描照样报红。第三,也是最要命的,源码安装没有卸载记录,想回退只能手动删文件,删漏一个就可能留下隐患。
RPM 打包的好处是把新版本做成一个标准包,用rpm -Uvh升级,旧版本的文件被替换、配置被备份、数据库被更新,出问题还能用备份的旧 RPM 降级回去。代价是打包过程稍微麻烦一点,需要准备 spec 文件或者用现成的打包脚本。常见做法是找一份可靠的 openssh.spec,改掉版本号和几个编译参数,然后用rpmbuild出包。我一般会先在测试机上把整条链路跑通,确认 sshd 能正常起、能正常登录,再上生产。
提示:无论用哪种方式,升级前务必确认你有带外管理手段(如云控制台的 VNC、物理机的 IPMI),这是最后的后悔药。
2.2 版本选择与依赖确认
版本不是越新越好。OpenSSH 从 8.x 开始逐步弃用了一些老算法(比如 ssh-rsa 的 SHA-1 签名),而 CentOS7 上很多老客户端、老设备还在用这些算法,升太新会导致它们连不上。比较稳妥的选择是升到 8.x 的一个中间版本,既能满足大部分合规要求,又不至于把兼容性一刀切死。具体选哪个小版本,要看你环境里客户端的情况,可以先在测试环境验证。
依赖方面,OpenSSH 编译需要 zlib、openssl 的开发包。CentOS7 自带的 openssl 是 1.0.2 系列,如果你要升的 OpenSSH 版本要求 openssl 1.1.1 以上,那就得连 openssl 一起升级,复杂度会明显上升。所以第一步是先确认目标 OpenSSH 版本对 openssl 的最低要求,能不动 openssl 就不动,动它牵扯面太大。
# 查看当前系统 OpenSSH 和 OpenSSL 版本 ssh -V openssl version # 查看已安装的 openssh 相关包 rpm -qa | grep -E 'openssh|openssl' # 确认开发依赖是否齐全 rpm -q zlib-devel openssl-devel gcc make rpm-build这几条命令的作用是摸清现状:ssh -V看客户端版本,openssl version看加密库版本,rpm -qa列出所有相关包,最后一条确认打包和编译需要的工具是否都在。如果rpm-build没装,后面rpmbuild会直接报错,提前装上省事。
2.3 回滚方案要提前落地,而不是出事再想
回滚的核心是两样东西:旧版本的 RPM 包,和一份完整的/etc/ssh备份。旧 RPM 包可以从系统镜像里找,也可以用rpm -qa配合yumdownloader把当前版本的包下载下来存好。/etc/ssh目录里有 sshd_config、ssh_config、主机密钥等,升级前整个目录打包备份。
# 备份当前 ssh 配置和主机密钥 tar czf /root/ssh_config_backup_$(date +%F).tar.gz /etc/ssh # 下载当前版本的 openssh RPM 包备用(需要先装 yum-utils) yum install -y yum-utils yumdownloader openssh openssh-server openssh-clients # 确认备份文件存在且非空 ls -lh /root/ssh_config_backup_*.tar.gztar czf把整个/etc/ssh打包,文件名带日期方便区分。yumdownloader把当前版本的三个核心包下载到当前目录,将来降级时直接rpm -Uvh这些包即可。最后ls -lh确认备份文件大小正常,别出现 0 字节的假备份。这三步做完,你才有底气往下走。
3. 用 rpmbuild 打出可升级的 OpenSSH 包
3.1 准备打包目录与源码
RPM 打包有一套固定的目录结构,rpmbuild默认在~/rpmbuild下工作,包含 BUILD、RPMS、SOURCES、SPECS、SRPMS 五个子目录。源码 tarball 放 SOURCES,spec 文件放 SPECS。OpenSSH 的源码可以从官方镜像获取,注意校验一下完整性。
# 创建打包目录结构 mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} # 把下载好的源码包放入 SOURCES(假设已下载 openssh-8.x.tar.gz) cp openssh-8.x.tar.gz ~/rpmbuild/SOURCES/ # 进入 SPECS 目录准备 spec 文件 cd ~/rpmbuild/SPECS目录结构建好后,源码包放对位置,rpmbuild才能找到它。这里假设你已经拿到了目标版本的源码 tarball,文件名里的版本号要和 spec 里写的保持一致,否则打包时会报「找不到源码」的错。这一步没有太多玄学,就是路径要对。
3.2 spec 文件里必须改的几个关键项
spec 文件是打包的核心,它告诉 rpmbuild 怎么编译、装哪些文件、依赖什么。如果你用的是现成的 openssh.spec,重点改这几处:Version改成目标版本,Release加个自定义后缀方便区分,%files段确认文件列表和实际安装路径一致。另外 CentOS7 的 spec 里通常有一些针对老版本的补丁(Patch),新版本可能不需要或者不兼容,要逐个确认。
# 查看 spec 文件中和版本、补丁相关的行 grep -nE '^(Version|Release|Patch|Source)' openssh.spec # 修改版本号(示例,实际按目标版本填) sed -i 's/^Version:.*/Version: 8.x/' openssh.spec sed -i 's/^Release:.*/Release: 1.el7/' openssh.specgrep先把版本、发布号、补丁、源码这几类关键行找出来,心里有数再改。sed两条命令分别替换版本号和发布号,1.el7表示这是给 el7 打的第一个包。改完建议再用grep复查一遍,确认没改错行。补丁部分要特别小心,如果某个 Patch 在新版本上已经合并进主线,就要把对应的%patch行注释掉,否则编译会失败。
3.3 执行打包并检查产物
spec 改好后就可以打包了。rpmbuild -ba会同时生成二进制包(RPMS 目录)和源码包(SRPMS 目录)。编译过程可能持续几分钟,中途如果报错,多半是依赖缺失或者补丁冲突,按报错信息逐个解决。
# 开始打包,-ba 表示构建 binary 和 source 包 rpmbuild -ba openssh.spec # 查看生成的 RPM 包 ls -lh ~/rpmbuild/RPMS/x86_64/ # 查看包信息,确认版本正确 rpm -qpi ~/rpmbuild/RPMS/x86_64/openssh-8.x-1.el7.x86_64.rpmrpmbuild -ba是主命令,跑完在RPMS/x86_64/下应该能看到 openssh、openssh-server、openssh-clients 等几个包。ls -lh看文件是否生成、大小是否合理。rpm -qpi查看包元信息,重点确认 Version 和 Release 和你设定的一致。如果这里版本不对,说明 spec 没改到位,别急着装,回去改。
注意:打包过程中如果提示缺少
%{_sysconfdir}/ssh/...之类的文件,通常是%files段列的文件和实际安装的不匹配,需要对照make install的实际路径调整。
4. 安装新包并让 sshd 平稳接管
4.1 升级顺序与 sshd 重启时机
安装顺序有讲究。一般先升 openssh(公共部分),再升 openssh-clients,最后升 openssh-server。因为 server 包升级时会触发 sshd 重启,放在最后能减少中间状态的影响。升级用rpm -Uvh,U 表示升级,如果已安装旧版会替换,没装则安装。
# 按顺序升级三个包 rpm -Uvh ~/rpmbuild/RPMS/x86_64/openssh-8.x-1.el7.x86_64.rpm rpm -Uvh ~/rpmbuild/RPMS/x86_64/openssh-clients-8.x-1.el7.x86_64.rpm rpm -Uvh ~/rpmbuild/RPMS/x86_64/openssh-server-8.x-1.el7.x86_64.rpm # 确认版本已更新 ssh -V rpm -q openssh-server三条rpm -Uvh按依赖顺序执行。升级 server 包时,rpm 的脚本(%post)通常会自动重启 sshd,但有时不会,需要手动确认。ssh -V和rpm -q用来验证版本是否真的变了。如果ssh -V还是旧版本,可能是 PATH 里有其他 ssh,用which ssh确认一下实际调用的路径。
4.2 配置文件兼容性处理
新版本 sshd 对配置文件的语法检查更严格,一些老版本能容忍的写法,新版本可能直接拒绝启动。升级后不要急着断开当前连接,先在一个新终端里测试登录。如果 sshd 起不来,用sshd -t检查配置语法。
# 检查 sshd 配置语法 /usr/sbin/sshd -t # 如果报错,查看具体是哪一行 /usr/sbin/sshd -t -f /etc/ssh/sshd_config # 手动重启 sshd 并查看状态 systemctl restart sshd systemctl status sshdsshd -t是配置语法检查,不实际启动服务,安全。如果它报错,会指出具体行号,照着改。systemctl restart sshd重启服务,status看是否 active。这里的关键是:在确认新连接能成功建立之前,不要关闭你当前的 SSH 会话。当前会话是旧进程维持的,即使 sshd 重启失败,你还能在这个会话里救火。
4.3 用新会话验证登录与算法兼容
配置没问题后,开一个新终端尝试登录。如果登录成功,说明基本 OK。然后检查一下算法协商情况,确认老客户端还能不能连。
# 新终端登录测试 ssh user@host # 查看服务端支持的算法列表 ssh -Q key ssh -Q cipher # 用详细模式看协商过程 ssh -vvv user@host 2>&1 | grep -i 'kex\|cipher\|host key'ssh -Q key和ssh -Q cipher列出当前支持的密钥和加密算法。ssh -vvv输出详细的协商日志,grep 出密钥交换、加密、主机密钥相关的行,能看出实际用了哪种算法。如果发现老设备连不上,多半是算法被禁用,需要在 sshd_config 里用HostKeyAlgorithms、KexAlgorithms等指令把老算法加回来,但这会降低安全性,要权衡。
5. 升级 OpenSSH 最容易翻车的五个坑
5.1 升级后当前会话断开,新会话又连不上
现象:执行升级命令后,当前 SSH 会话卡死或断开,重新连接提示连接被拒绝。原因通常是 sshd 重启失败,而当前会话又恰好被中断。解决:升级前一定保留一个活跃会话不动,在另一个会话里操作;同时确保有带外控制台。如果已经断连,通过控制台登录,用sshd -t查配置,用journalctl -u sshd看日志,修复后重启。
5.2 主机密钥被重新生成,客户端报指纹变更
现象:升级后客户端提示「REMOTE HOST IDENTIFICATION HAS CHANGED」,拒绝连接。原因是升级过程中/etc/ssh/ssh_host_*密钥被重新生成或权限被改。解决:升级前备份/etc/ssh,升级后如果密钥变了,从备份恢复,并确保权限是600、属主 root。恢复后重启 sshd。
5.3 老客户端因算法弃用无法连接
现象:新版本 sshd 起来后,一些老设备或老客户端连接时报「no matching key exchange method」或「no matching host key type」。原因是新版本默认禁用了 SHA-1 相关的老算法。解决:在/etc/ssh/sshd_config里显式加上KexAlgorithms +diffie-hellman-group14-sha1、HostKeyAlgorithms +ssh-rsa等,把需要的老算法追加回来,然后重启。注意这只应作为过渡,长期还是推动客户端升级。
5.4 rpm 升级报文件冲突或依赖错误
现象:rpm -Uvh时报「file /usr/bin/ssh from install of ... conflicts with file from package ...」或依赖不满足。原因是新旧包文件路径重叠,或者新包依赖的库版本不够。解决:文件冲突可以用--force强制覆盖,但要谨慎;依赖问题用rpm -qpR查看新包依赖,逐个补齐。更稳的做法是先用rpm -Uvh --test做一次演练,不实际安装,只看会不会报错。
5.5 升级后 sftp/scp 行为变化导致脚本失败
现象:升级后原本能用的 scp 脚本报错,或者 sftp 连不上。原因是 OpenSSH 9.0 之后 scp 默认改用 SFTP 协议传输,行为和老 scp 有差异。解决:如果脚本依赖老 scp 行为,可以在命令里加-O强制用旧协议,或者改用 sftp 重写脚本。这个坑比较隐蔽,升级前最好确认一下有哪些自动化脚本依赖 scp。
6. 升级后的验证清单与一个省心的小技巧
升级完成不等于万事大吉,得有一套验证动作把风险兜住。我一般会按下面这个清单过一遍,每项都确认了才敢说这机器没问题。
| 验证项 | 命令 | 预期结果 |
|---|---|---|
| 版本正确 | ssh -V | 显示目标版本号 |
| 包已入库 | rpm -q openssh-server | 显示新版本 |
| 配置语法 | /usr/sbin/sshd -t | 无输出即通过 |
| 服务状态 | systemctl status sshd | active (running) |
| 新会话登录 | ssh user@host | 正常登录 |
| 密钥权限 | ls -l /etc/ssh/ssh_host_* | 权限 600,属主 root |
| 算法协商 | ssh -vvv user@host | 协商成功,无报错 |
这张表建议存下来,每次升级后照着跑一遍。尤其是密钥权限那一项,很多人升级后忘了检查,结果 sshd 因为密钥权限过宽拒绝启动,日志里报「bad permissions」,排查半天。
再说一个省心的小技巧:用rpm -Uvh --test做预演。在真正安装前,先加--test参数跑一遍,rpm 会检查依赖、文件冲突、脚本执行条件,但不实际改动系统。这一步能提前暴露大部分问题,比如缺依赖、文件冲突,让你在不动系统的情况下就知道能不能装。我现在的习惯是,任何 rpm 升级操作,先--test,确认无报错再正式执行。
# 预演升级,不实际安装 rpm -Uvh --test ~/rpmbuild/RPMS/x86_64/openssh-8.x-1.el7.x86_64.rpm \ ~/rpmbuild/RPMS/x86_64/openssh-clients-8.x-1.el7.x86_64.rpm \ ~/rpmbuild/RPMS/x86_64/openssh-server-8.x-1.el7.x86_64.rpm # 预演无报错后,去掉 --test 正式执行--test是 rpm 自带的演练模式,三个包一起传进去,能一次性检查所有依赖和冲突关系。如果预演通过,正式执行基本不会出意外。这个习惯帮我省过好几次事,尤其是依赖关系复杂的时候,预演能让你在动手前就心里有数。
最后说个我自己的教训:早年间升级 OpenSSH,图省事直接源码编译覆盖,结果 sshd 起不来,又没有带外控制台,最后只能让机房的人帮忙接显示器。从那以后,我升级任何远程服务前,第一件事就是确认带外通道可用,第二件事是备份,第三件事才是动手。顺序错了,代价可能就是一趟机房。希望帮到你。
本文还有配套的精品资源,点击获取