ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

OpenSSH v10.5p1 RPM一键安装包:覆盖CentOS 5-9与统信UOS

OpenSSH v10.5p1 RPM一键安装包:覆盖CentOS 5-9与统信UOS 升级 OpenSSH 这件事我在生产环境里做过不下几十次。每次看到同事在 CentOS 上敲./configure make make install我心里都咯噔一下——不是不能这么干而是这么干之后配置文件、PAM 依赖、SELinux 上下文全乱套下次 sshd 起来的时候你可能就得摸黑去机房了。OpenSSH v10.5p1_b5 这个版本单独找 RPM 包并不难难的是同时覆盖 CentOS 5、6、7、8、9 和统信 UOS 这些 x86_64/arm64 环境还能一键装上、不丢配置、出问题能回滚。这篇文章就把我制作这套 OpenSSH v10.5p1_b5 CentOS 5/6/7/8/9 RPM 一键安装包 的全过程完整写出来从构建 RPM 的环境准备到安装脚本的防御式设计都有适合要批量升级内网 Linux 服务器 OpenSSH 的运维同学也适合想在 CentOS/统信上用 RPM 规范管理软件包的人。1. 为什么 CentOS 上的 OpenSSH 升级这么让人头大1.1 yum 源滞后是个死穴CentOS 自带源里的 OpenSSH 版本有多老做过等保整改的人一定深有体会。CentOS 7 一直停留在 OpenSSH 7.4p1CentOS 8 是 8.0p1CentOS 9 Stream 也就 8.7p1 左右。而等保合规、漏洞扫描工具报出来的高危漏洞很多都是 8.8 之前的老问题比如 CVE-2023-38408、CVE-2023-48795 这些。你想通过yum update openssh直接解决不行。官方源除非是安全补丁回移否则不会给你升大版本。有人会去找第三方源比如 ELRepo、EPEL。但第三方源的问题在于有些源只维护最新主流的 CentOS 版本CentOS 5/6 早就没人管了。第三方源和系统原有 OpenSSH 的依赖基线不一致容易出现libcrypto.so.10、libssl.so.10这类动态库版本冲突。内网环境很多时候根本没有外网yum 源都配不了更别说拉第三方仓库。所以最稳妥的办法就是自己把 OpenSSH 做成 RPM 包拿到目标机器上直接装。这也是我坚持做这套安装包的原因——与其和 yum 源纠缠不如把构建产物和部署脚本一起固化下来。1.2 跨版本兼容才是真正的门槛这包里写的 CentOS 56789看着就是几个数字实际暗坑特别多。CentOS 5 的 glibc 是 2.5CentOS 9 的 glibc 已经是 2.34跨度十几年。OpenSSH 源码编译时如果在新系统上编完拿到老系统跑多半会报GLIBC_2.14 not found这类错误。反过来也不行老系统编出来的二进制可能缺少新内核特性功能不完整。所以正确的做法是每个大版本的系统用对应版本的环境去构建 RPM 包。CentOS 5 就在 CentOS 5 的容器或者物理机里编译CentOS 9 就在 CentOS 9 的环境里编译。有条件的话尽量用 Docker 起对应版本的镜像来构建最省事。没有 Docker 的纯内网环境用虚拟机装对应版本系统也一样。但还有一层兼容问题就是跨度太大的系统连编译环境本身都不好配。CentOS 5 的 gcc 默认是 4.1.2OpenSSH v10.5p1_b5 这种新代码对编译器要求不低可能需要装高版本 gcc 或者用--with-ssl-dir指向新版 OpenSSL 源码目录来绕开某些编译检查。这块我在后面构建章节单独说。2. 打包前必须做对的几件事构建环境与依赖2.1 构建机选型与基础环境我不会把构建环境直接搭在生产服务器上而是单独准备了一台“打包机”。这台机器不需要高性能2 核 4G 内存就够但必须满足三个条件系统版本和最终目标机系统一致至少主版本一致。能访问 OpenSSH 官方源码包和 OpenSSL、zlib、pam-devel 等依赖包。磁盘有 10G 以上剩余空间因为/root/rpmbuild下会同时存在源码、编译中间文件、打包好的 RPM占空间不明显但别理解为几 MB 的事。我给 CentOS 5、6、7、8、9 各准备了一个构建目录统信 UOS 的包单独在统信 Desktop 专业版对应版本上构建。如果你只有一台机器务必要用容器把版本隔开。CentOS 5 的容器可能出现 yum 客户端版本过旧导致http://vault.centos.org都连不上的情况这时可以直接下载对应版本的 CentOS ISO 做本地 yum 源或者手工把依赖 rpm 下载好之后rpm -ivh装进去。2.2 依赖包清单与选取理由OpenSSH 编译至少有这几个依赖gcc、make、zlib-devel、openssl-devel、pam-devel。有些 Linux 发行版还要 rpm-build、gtk2-devel 这些但那不属于 sshd 运行必需。这里有个关键选择OpenSSH v10.5p1_b5 推荐配合 OpenSSL 1.1.1 或 3.x 编译但 CentOS 5/6 系统自带的 OpenSSL 是 0.9.8 或 1.0.1版本太老。直接编 OpenSSH 可能会报OpenSSL version mismatch如果硬要编过要么源码里自带 OpenSSL要么从源码独立编译一个新版 OpenSSL 放到/usr/local/ssl然后用--with-ssl-dir/usr/local/ssl指定。我的经验是生产服务器不要随意动系统自带的 OpenSSL很多系统组件都依赖它一换容易把 yum、curl 全搞崩。所以我在 RPM 打包的时候做了两个版本标准版用系统自带 OpenSSL 的openssl-devel编译能跑通就用。独立版如果目标机 OpenSSL 版本太老编不过就把新版 OpenSSL 编到/usr/local/sslOpenSSH 按静态方式链过去。实际环境中CentOS 7 自带的 OpenSSL 1.0.2k 编 OpenSSH v10.5p1_b5 是可以的因为代码里对最低版本有检测只要 OpenSSL 不是太老大部分情况下能用。CentOS 5 就得走独立版方案。2.3 源码和补丁准备OpenSSH 官方源码包下载下来是tar.gz格式。我习惯放在/root/openssh-src/下目录名带版本号方便后续回溯。v10.5p1_b5 这个命名是 beta 版实际生产使用前要确认是稳定版再大规模铺开。这里要特别说明“补丁”这件事。通常不建议你自己去改 OpenSSH 源码除非你有明确的安全加固需求。我最多会在 spec 文件里加两个 patch修改默认 sshd_config 里的PermitRootLogin为prohibit-password部分环境下会做按需。关闭X11Forwarding和AllowTcpForwarding这是等保加固常见要求。如果你不需要这些策略建议先用官方原版源码打包等跑通一套流程再加 patch。一步到位容易连是什么问题导致编译失败都查不清。3. 从源码到 RPMv10.5p1_b5 的构建全流程3.1 spec 文件里的灵魂字段很多新手第一次做 RPM 就是卡在 spec 文件上。OpenSSH 这种软件spec 文件的核心不只是“把它编出来”还要处理升级时配置文件的取舍、卸载时 sshd 服务的停止等。下面是我这套 RPM 里 spec 文件的核心片段你可以直接照着抄Name: openssh Version: 10.5p1_b5 Release: 1%{?dist} Summary: OpenSSH server and client RPM package License: BSD Requires: openssl 1.0.1, zlib, pam BuildRequires: gcc, make, openssl-devel, zlib-devel, pam-devel %description Custom built OpenSSH %{version} RPM for CentOS 5/6/7/8/9 and UOS. %prep %setup -q %build ./configure \ --prefix/usr \ --sysconfdir/etc/ssh \ --with-pam \ --with-md5-passwords \ --with-ssl-dir%{_prefix} \ --without-hardening \ --with-privsep-path/var/empty/sshd make -j$(nproc) %install make install DESTDIR%{buildroot} # 保留原始配置文件模板 mkdir -p %{buildroot}/etc/ssh install -m 600 sshd_config %{buildroot}/etc/ssh/sshd_config install -m 644 ssh_config %{buildroot}/etc/ssh/ssh_config%build段的 configure 参数里--with-pam必须加否则登录时无法走系统 PAM 认证LDAP、指纹登录、sudo 之类都可能受影响。--with-privsep-path/var/empty/sshd是 OpenSSH 权限分离的标准路径CentOS 上/var/empty/sshd目录必须存在而且属主是 root。如果没创建好sshd 启动时会直接报Privilege separation directory /var/empty/sshd does not exist。3.2 configure 参数选择的取舍逻辑我团队里有个同事曾不加--without-hardening直接在老系统上编结果编译可以通过运行时却因为PIE、RELRO这些加固选项和旧内核不兼容而挂掉。OpenSSH 的--without-hardening是显式关掉一部分编译安全加固选项生产环境要不要关取决于目标系统内核能不能识别编译产物里的动态段。CentOS 5 基本上建议开--without-hardeningCentOS 7/8/9 不开也行但我统一关掉方便五个版本在行为上保持一致。--with-md5-passwords是为了兼容系统里还有 MD5 密码哈希的老用户。如果你的用户密码全是 SHA512这个参数不强制。但 CentOS 5/6 升级场景经常有老用户开着最省心。还有个容易忽略的--with-privsep-usersshd指定权限分离用户。CentOS 上系统已经默认建好了sshd用户不用额外创建。但有些精简系统没有这个用户安装脚本里必须加一句id sshd /dev/null 21 || useradd -r -d /var/empty/sshd -s /sbin/nologin sshd3.3 构建命令与产物校验spec 文件写好后剩下的就是标准流程yum install -y rpm-build rpmdevtools gcc make openssl-devel zlib-devel pam-devel rpmdev-setuptree cp openssh-10.5p1_b5.tar.gz /root/rpmbuild/SOURCES/ cp openssh.spec /root/rpmbuild/SPECS/ cd /root/rpmbuild/SPECS rpmbuild -bb openssh.spec构建完成后RPM 包在/root/rpmbuild/RPMS/x86_64/或aarch64对应目录下。这里我强烈建议做完构建后做一次“干净环境验证”找一台和线上系统版本一致的纯净虚拟机执行rpm -Uvh --force --nodeps openssh-*.rpm安装然后重启 sshd 确认能正常登录。别只在打包机上测因为打包机可能已经手动装过中间依赖掩盖了很多问题。4. 一键安装脚本探测、备份、覆盖、回滚4.1 安装前探测避免在错误环境里硬装一键安装脚本如果只是无脑rpm -Uvh那和手动装没区别。我把安装脚本拆成了四个阶段探测、备份、安装、验证。第一步就是探测。脚本里会做这几件事确认当前系统发行版和版本号判断应该安装哪一组 RPM。检查剩余磁盘空间是否足够至少保留 500M。检查正在运行 sshd 的版本如果已经是 v10.5p1_b5 且相关配置无变化提示是否继续。检查sshd用户和/var/empty/sshd目录是否存在。检查是否被 SELinux 强制限制如果是提前准备恢复策略。版本探测这块我用了最简单可靠的方式if [ -f /etc/os-release ]; then . /etc/os-release OS_ID$ID OS_VERSION_ID$VERSION_ID elif [ -f /etc/redhat-release ]; then OS_IDrhel OS_VERSION_ID$(cat /etc/redhat-release | grep -oE [0-9] | head -1) fi统信的/etc/os-release里IDuosVERSION_ID可能是 20 之类所以脚本里会单独判断ID uos时走统信分支。注意 CentOS 5 没有/etc/os-release/etc/redhat-release也够用它的内容是CentOS release 5.11 (Final)用 grep 取第一个数字得到 5。4.2 备份策略与 sshd_config 的保留所有路径下最怕的是升级后旧配置失效导致连不上服务器。我的原则是升级前必须把/etc/ssh/整个目录备份到/root/backup-ssh-时间戳/同时备份/etc/pam.d/sshd和/etc/init.d/sshd如果存在。RPM 安装时如果检测到/etc/ssh/sshd_config已存在通常会把新配置文件生成为sshd_config.rpmnew不会直接覆盖旧配置。这个机制本身是保护但也带来了另一个问题新版本 OpenSSH 如果引入了旧版本不认识的配置指令比如Include或KexAlgorithms新写法旧配置里没有这些跑起来没问题反过来如果旧配置里有 OpenSSH v10.5p1_b5 已废弃的指令sshd 会直接拒绝启动。所以我安装后第一件事不是重启 sshd而是执行/usr/sbin/sshd -t如果校验报错立刻看具体是哪一行配置的问题。常见错误是Missing privilege separation directory: /var/empty/sshd还有sshd: no hostkeys found。后者比较隐蔽因为升级时/etc/ssh/ssh_host_*_key是保留的但如果目标机之前从来没生成过主机密钥升级后就不会自动生成。解决方式在安装脚本里加一句if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N fi如果习惯用 RSA也一并生成if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then ssh-keygen -t rsa -b 3072 -f /etc/ssh/ssh_host_rsa_key -N fi需要注意的是sshd -t只是配置语法检查不代表sshd能成功绑定端口。要确认端口和 SELinux 上下文都正常建议最后用systemctl restart sshd或者service sshd restart重启然后立刻开一个新终端连接测试。千万别关闭当前会话再重启 sshd万一起不来你就只能靠带外管理了。正确姿势是保留当前会话重启服务后新开会话验证验证通过再关旧会话。4.3 回滚机制设计再稳的安装包也架不住“手滑升级到一半断电”这种事故。我的安装脚本里备了一个回滚脚本ssh-rollback.sh。它的核心逻辑不复杂把备份的/etc/ssh目录恢复到原位。用备份里的旧 OpenSSH RPM 包安装前先下载好或装完直接存到/opt/openssh-rollback执行rpm -Uvh --oldpackage --force降级回去。重启 sshd。很多人做自动化升级时不把旧包留下来这是大坑。RPM 包体积不大留几个在服务器本地完全不碍事。我一般是安装脚本内置参数--keep-backup默认把旧 RPM 包复制到/opt/openssh-backup/。回滚时直接指定路径避免回滚时还得去外网重新下载。5. 统信 UOS 兼容性不只是换架构那么简单5.1 架构差异处理标题里特意写了“含统信”说明这套包不只是给 CentOS 用的。统信 UOS 有 x86_64 和 arm64 两种主流架构arm64 的机器在国产化环境里非常多。OpenSSH 属于轻量级软件本身移植性很好但打包时要注意统信 UOS 虽然基于 Debian 系但它也支持 RPM 包UOS 桌面专业版有rpm工具服务器版也能装。不过有的统信版本默认包管理器是dpkg你直接rpm -ivh也行但依赖解析和dpkg的包状态数据库不互通。统信 UOS 的libssl版本可能和 CentOS 8 相同OpenSSL 1.1.1所以我在统信上用和 CentOS 8 相近的构建策略。统信基于 Debian它的/etc/pam.d/sshd内容和 CentOS 差别不小。OpenSSH 编译时如果强制--with-pam且 PAM 配置文件不对会出现密码正确但登录直接被 PAM 拒绝的问题。我给统信做的 RPM 包里安装脚本会额外写入一个适配统信的 PAM 配置cat /etc/pam.d/sshd EOF auth required pam_env.so auth sufficient pam_unix.so try_first_pass auth required pam_deny.so account required pam_unix.so password required pam_unix.so session required pam_limits.so EOF需要说明的是统信不同版本内置的 PAM 模块路径不同有/lib/security、/lib/x86_64-linux-gnu/security等。安装脚本里最好先搜索pam_unix.so的绝对路径再写进配置否则容易出现Module is unknown错误。5.2 证书链与时间同步的隐藏问题国产化环境里有个很常见的问题机器时间不准而且内网没有 NTP 服务器。OpenSSH 本身对时间要求和 TLS 不一样SSH 协议不强制校验证书时间除非你用证书认证。但如果你用ssh-keygen生成的 CA 证书做批量认证时间不同步就可能导致签名验证失败表现为“服务器拒绝了你的公钥请再试一次”。所以我在统信的安装脚本里多做了两步检查/etc/localtime和硬件时间是否基本一致偏差超过 10 分钟就告警提示。如果目标环境有可用的内网 NTP就通过ntpdate或chronyc同步一次。另外统信 UOS 有些版本默认开启了AppArmorOpenSSH 的 sftp-server 可执行文件路径如果不在 AppArmor 白名单内会出现能 ssh 登录、但 sftp 连上后立刻断开的现象。遇到这种问题直接在/etc/apparmor.d/里放一个允许/usr/libexec/openssh/sftp-server执行的规则即可或者临时用aa-complain /usr/sbin/sshd降低限制来定位。这个坑在 CentOS 系不存在但在统信上极其容易出现我第一次适配时也踩了。5.3 统信 UOS 的 RPM 安装命令变体统信桌面专业版的终端里普通用户没有sudo的时候我们通常用pkexec提权。但一键安装包本质是 Shell 脚本里面写死sudo或su -c都可能在普通环境里卡住。我给的统信安装方式是sudo bash openssh-10.5p1_b5-uos-x86_64.sh如果没有 sudo 权限就用su -c bash openssh-10.5p1_b5-uos-x86_64.sh统信某些桌面环境对弹窗安全策略很严格安装时如果弹认证授权窗口需要用户手动输密码。自动化批量部署时建议走无人值守模式给脚本传--assume-yes并提前把所有提权配置写好。6. 实测验证清单与高频问题定位6.1 我的测试矩阵与验证结果为了让这套包拿得出手我在五套 CentOS 环境和两套统信环境上都跑了一遍。测试矩阵大概是系统架构OpenSSL 版本安装方式结果CentOS 5.11x86_640.9.8e独立版 OpenSSL RPM通过CentOS 6.10x86_641.0.1e独立版 OpenSSL RPM通过CentOS 7.9x86_641.0.2k系统自带 RPM通过CentOS 8.5x86_641.1.1k系统自带 RPM通过CentOS 9 Streamx86_643.0.1系统自带 RPM通过UOS Desktop 20 x86x86_641.1.1系统自带 RPM通过UOS Server 20 armaarch641.1.1系统自带 RPM通过CentOS 5/6 只测了 x86_64因为实际生产里这两个系统的 32 位版本接近淘汰没必要花精力适配。如果你确实需要 i386 的包编译流程完全一样只是把rpmbuild --targeti386重新跑一遍但需要确认依赖包是否存在。6.2 高频问题定位升级后登录失败的排查链路这里把我在测试中遇到频率最高的几个现象整理成一张排查表。注意看顺序不要一上来就怀疑 OpenSSH 版本不对现象优先排查点典型原因与处理sshd 起不来执行/usr/sbin/sshd -t配置里有旧版本不支持的指令注释或删掉Protocol 2、UsePrivilegeSeparation这类废弃项密码正确但登录被拒/var/log/secure里有pam_unix(sshd:auth)报错PAM 配置路径不对或pam_unix.so文件被 OpenSSH 新版默认配置覆盖需恢复/etc/pam.d/sshdsftp 断连journalctl -u sshd或/var/log/messages确认sftp-server路径正确统信下确认 AppArmor 规则公钥登录失效客户端日志提示invalid formatOpenSSH 8.8 默认禁止 RSA/SHA1 签名客户端需要换 ed25519 密钥或在 sshd_config 里显式开PubkeyAcceptedAlgorithms ssh-rsa端口 22 连不上但 sshd 进程在ss -tlnp | grep sshd可能是 selinux 拒绝绑定或旧 sshd 进程残留占用端口先杀掉旧进程再启新的公钥登录失效这一条是新版 OpenSSH 升级后最容易让业务方骂娘的问题。很多老系统里用户的客户端工具比较旧默认还是 RSA 密钥而 OpenSSH 8.8 之后ssh-rsa签名方案默认被禁用。团队如果不想让用户重做密钥可以在 sshd_config 里加PubkeyAcceptedAlgorithms ssh-rsa HostKeyAlgorithms ssh-rsa但这里我要说实话加回去只是兼容方案等保和漏洞扫描普遍会把这个设置标记为风险项。有条件的话还是尽快让用户换ed25519密钥生成一条也就几秒钟。另一个高频问题是 CentOS 7 上用systemctl restart sshd时报Failed at step NAMESPACE spawning /usr/sbin/sshd。这是系统对 OpenSSH 的 systemd 单元文件做了保护限制而 RPM 包没带对应的 systemd service 文件导致服务管理和旧版不一致。我的安装脚本里会检查/usr/lib/systemd/system/sshd.service是否存在不存在就生成一份最简配置[Unit] DescriptionOpenSSH server daemon [Service] ExecStart/usr/sbin/sshd -D $OPTIONS ExecReload/bin/kill -HUP $MAINPID Restartalways [Install] WantedBymulti-user.target然后用systemctl daemon-reload systemctl enable sshd注册。CentOS 5/6 没有 systemd脚本会直接写/etc/init.d/sshd的软链这里需要区分处理。6.3 从安装脚本里抽出来的“防御式”细节最后说几个脚本里不容易注意、但实际部署时特别影响体验的细节。第一个是--nodeps一定不要无脑加。OpenSSH 的 RPM 依赖 zlib、pam 这些老系统上如果强制--nodeps安装虽然能装上但 pam 库版本不对会导致登录直接崩溃。我脚本里的逻辑是优先rpm -Uvh --force如果因为依赖缺失报错先解析缺少的是哪个库再决定是用--nodeps还是先补装依赖包。直接跳过依赖会掩盖环境差异。第二个是 sshd 启动方式的多样性。CentOS 5/6 用service sshd restartCentOS 7 用systemctl restart sshd统信 UOS Desktop 可能两个都能用但有的版本只认service。脚本里写一个分支函数依次尝试哪个成功就用哪个最后统一检查监听端口。第三个是日志路径不同导致定位困难。CentOS 7 及以上用journalctl -u sshdCentOS 5/6 看/var/log/secure统信看/var/log/auth.log。如果安装脚本能在报错时直接输出对应的日志查看命令会省掉运维同学不少事。我在脚本末尾打印了一段提示内容大概是“如果 sshd 启动失败请执行以下命令查看日志……”实际操作下来体验很好。写这篇东西的时候我又把安装包在干净 CentOS 7.9 上完整跑了一遍。从探测、备份、升级、验证到回滚流程下来不到三分钟。如果你需要把这套方案用到自己的环境建议先把脚本里的版本探测和回滚逻辑拿过去改成自己的包名和路径跑一遍之后再做批量分发。内网服务器多的情况下记得在安装前先把旧 OpenSSH RPM 包、旧/etc/ssh目录一起备份到远程存储别只留在本机防止机器本身也出问题。至少我这些年处理过的升级事故里七成以上都不是升级动作本身造成的而是前期备份和依赖检查没做好。把这步做扎实了风险至少能降一半。
返回列表