简介面向 Rocky Linux 9.5Blue Onyx服务器的 OpenSSH 升级与安全加固方案适合运维工程师、系统管理员在旧版 sshd 整改、等保合规加固等场景中直接使用。整套材料围绕 OpenSSH 10.0p1 与 OpenSSL 3.5.0 的替换链路组织附带升级前后的版本核对、服务状态确认等实操依据可帮助读者规避升级中常见的依赖断裂、服务无法启动等问题。压缩包共 6 个文件、约 10.96MB含 5 个 rpm 与 1 个 sh 脚本rpm 覆盖 openssh 服务端、客户端及 chkconfig、initscripts 等配套依赖脚本负责串联升级与加固动作降低手工逐条执行的出错概率。目前已有 210 人学习下载。读者可据此掌握版本升级的完整流程、依赖处理顺序与加固项配置思路并对照自身环境完成 sshd 的平滑替换与验证。1. 重启 sshd 之后那三分钟我为什么坚持把升级做成 RPM把 Rocky Linux 9.5 上自带的 openssh-8.7p1 换成自己编的 openssh-10.0p1、再链上 OpenSSL 3.5.0打成 x86_64 的 rpm最后用脚本做 OpenSSH 加固——这套流程我做了三遍才敢上带业务的机器。第一遍是最土的./configure make install跑通了也埋了雷三个月后想回退系统里已经找不回原来那份二进制只能翻 shell history 猜当时改过什么。第二遍我开始写 spec把 OpenSSL 3.5.0 关进 /opt把升级和回滚都塞进脚本。第三遍补上加固基线和验证闭环才敢一次推给二十几台机器。这篇写的就是这条路上的判断依据和能直接抄的片段三条升级路线怎么选、3.5.0 为什么不能覆盖系统那份 libssl.so.3、spec 里哪几行是保命的、加固清单怎么定、以及五个我亲身踩过、能让你少熬一宿的坑。写给准备做版本跨越的运维和安全同学也写给已经被 sshd 重启坑过一次、想要一套可复现流程的人。2. 三条路摆在一起比源码编译、等仓库、自建 RPM 该选谁2.1 先明确一个前提版本号低不等于不安全很多人做 OpenSSH 加固的起点是一张漏洞扫描报告上面写着 openssh 版本过低。这里有个常被忽略的事实发行版维护方会把上游的安全补丁回移到旧版本号上8.7p1 后面跟着一长串.el9_5之类的 release 号其中相当一部分就是回移的修复。所以判断要不要升的依据不是版本号大小而是三件事扫描器能不能认、功能上有没有必须要新版本的特性、以及你们的安全基线是不是硬性要求上游版本号。把这三件事想清楚路线选择才有意义。如果只是为了让扫描器闭嘴回移补丁的 8.7p1 其实够用如果确实需要 10.0p1 这条线上的东西比如默认启用抗量子的密钥交换、彻底移除 DSA 支持、以及新的算法默认值那就得自己动手。我当时属于后者加固基线里明确要求禁用 SHA-1 系签名、DSA 主机密钥不进配置文件同时希望密钥交换首选走混合后量子算法。2.2 三条路线的逐项对比我把三条路线按实际会遇到的维度摊开比了一遍结论在表后面。维度源码 make install等发行版仓库自建 RPM 升级脚本版本可控性想装哪个装哪个被仓库版本锁死想装哪个装哪个回滚成本基本靠重装或手工还原dnf history undo一条命令rpm -Uvh --oldpackage一条命令批量下发每台手敲或写一堆 ssh仓库统一推送一个 rpm 推过去配置文件归属无记录容易被覆盖由 rpm 管理自己用%config(noreplace)定规则审计留痕只有 shell historyrpm -q可查rpm -q 包签名可查SELinux 处理经常要手工 restorecon策略自带需要写进%post首次投入半小时零两三小时出问题概率高低中出事后代价高低低表格里最扎眼的是最后两行。源码编译不是装不上的风险高而是装上了以后出问题没法查的风险高/usr/local/etc/sshd_config和/etc/ssh/sshd_config同时存在、/usr/local/sbin/sshd和/usr/sbin/sshd同时存在systemd 起的是哪个、PAM 读的是哪个、SELinux 认的是哪个全靠记忆。这种状态在单机上无所谓在二十台机器上就是血泪经验。等仓库这条路最稳代价是版本天花板。而且 Rocky Linux 9.5 自带的 OpenSSL 是 3.2 分支想上 3.5.0 这条 LTS 线光换 OpenSSH 是不够的最终还是得自己编。所以真正要选的是编完怎么落地直接覆盖安装还是打成包。2.3 自建 RPM 到底买到了什么多花两三个小时买到的是四样东西。第一是可回滚。rpm -Uvh --oldpackage能把整包退回上一个版本配置文件的 rpmnew/rpmsave 机制还会把改过的配置单独留一份。这一点在 sshd 这种改错就进不去的服务上价值极高。第二是可审计。rpm -q openssh --qf %{VERSION}-%{RELEASE}.%{ARCH}\n能直接回答这台机器现在跑的是哪个版本、什么时候装的、包有没有被篡改。源码编译给不了这个答案。第三是可批量。包推到内网源剩下的交给配置管理工具每台机器执行的动作完全一致不存在这台当时多打了个参数的玄学差异。第四是能跟 SELinux 和 PAM 对上。自建包在%post里跑一次restorecon、把/etc/pam.d/sshd一起打进包里就避免了编译装完 SELinux 拒绝、PAM 找不到配置这类只在源码安装时出现的毛病。注意自建包不等于自建 OpenSSL 系统包。把系统的 openssl-libs 换掉是另一回事dnf、python3、curl一大串东西都挂在它上面那条路我不建议碰。3. 构建环境与 OpenSSL 3.5.0让它待在 /opt 别碰系统的 libssl.so.33.1 构建机该装什么、刻意不装什么构建机用一台和线上同版本的 Rocky Linux 9.5 最小化安装就够先补构建工具链和几个开发包。# 基础工具链与打包工具 dnf groupinstall -y Development Tools dnf install -y rpm-build rpmdevtools systemd-rpm-macros perl-interpreter wget tar # 对应 OpenSSH 的几个可选特性缺一个就少一个功能 dnf install -y pam-devel zlib-devel libselinux-devel krb5-devel audit-libs-devel libfido2-devel每个包都对应 configure 的一个开关不是随手装的pam-devel对应--with-pam没有它编出来的 sshd 根本不走 PAM密码和二次验证会一起失效libselinux-devel对应--with-selinux没有它 SELinux 下的上下文切换会出问题audit-libs-devel对应--with-auditlinux登录事件才会进 audit 日志krb5-devel对应--with-kerberos5libfido2-devel是给 FIDO/U2F 硬件密钥认证用的如果你的环境用 sk-ssh-ed25519 这类密钥这个必须有。刻意不装的是openssl-devel。装了它以后configure 有可能通过 pkg-config 找到系统那份 3.2 的头文件和库你以为链上了 3.5.0实际上ssh -V一看还是旧的。这种以为改了其实没改的翻车最难查因为编译过程一句报错都没有。3.2 OpenSSL 3.5.0 装到 /opt为什么不能覆盖系统那份OpenSSL 3.5 是 LTS 分支soname 依然是libcrypto.so.3/libssl.so.3也就是说直接覆盖系统的/usr/lib64/libssl.so.3不会立刻炸——它会以某天 dnf 突然报错、某个 python 模块导入失败的方式延迟爆炸排查成本极高。先看一眼系统上到底有多少东西依赖它# 看看谁在用系统的 openssl-libs输出会很长 rpm -q --whatrequires openssl-libs | head -30所以正确姿势是隔离安装wget https://www.openssl.org/source/openssl-3.5.0.tar.gz tar xf openssl-3.5.0.tar.gz cd openssl-3.5.0 # --prefix 决定安装位置--openssldir 决定 openssl.cnf 的位置 # --libdirlib64 保证 64 位库落在 lib64 下跟 rpath 对得上 ./Configure --prefix/opt/openssl-3.5.0 \ --openssldir/opt/openssl-3.5.0/ssl \ --libdirlib64 \ shared zlib -fPIC make -j$(nproc) # 只装库和头文件不装 man 和文档减少体积也减少冲突面 make install_sw几个参数值得单独说。shared是必须的我们要的是动态库静态链进去以后 OpenSSL 发安全更新就得重编 OpenSSH等于把两个东西绑死了。zlib打开压缩支持。--openssldir指向 /opt 下面是为了让这份 OpenSSL 有自己独立的配置文件不去读系统的/etc/pki/tls/openssl.cnf。关键的一条不要把/opt/openssl-3.5.0/lib64写进/etc/ld.so.conf.d/再跑ldconfig。那样做等于让全系统所有程序优先加载 3.5跟直接覆盖只差一个看起来没那么暴力。我们只在 OpenSSH 这套二进制上通过 rpath 指定路径其他程序不受影响。3.3 configure 参数一条一条对着看OpenSSH 这步的坑主要在路径上。整个 configure 我按下面这样写LDFLAGS一定要在./configure之前 export 出去不能当成 configure 的参数传。cd openssh-10.0p1 # rpath 把 3.5.0 的库路径写死进二进制relro/now 顺手加上加固 export LDFLAGS-Wl,-rpath,/opt/openssl-3.5.0/lib64 -Wl,-z,relro -Wl,-z,now ./configure \ --prefix/usr \ --sysconfdir/etc/ssh \ --libdir/usr/lib64 \ --with-ssl-dir/opt/openssl-3.5.0 \ --with-pam \ --with-selinux \ --with-auditlinux \ --with-kerberos5 \ --with-privsep-path/var/empty/sshd \ --with-privsep-usersshd \ --with-pid-dir/run \ --with-xauth/usr/bin/xauth \ --with-default-path/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ --disable-strip--prefix/usr是为了让二进制落到/usr/sbin、配置落到/etc/ssh跟发行版原来的布局一致systemd 的 unit 文件不用改。--with-ssl-dir同时影响头文件和库的搜索路径。--with-privsep-path/var/empty/sshd这个目录必须存在、属主 root、权限 0755缺了它 sshd 启动直接失败后面打包时要显式创建。--with-pid-dir/run跟 Rocky 9 的 systemd unit 对得上。--disable-strip是给自己留调试符号的余地出问题时gdb还能看出点东西。还有一点值得提前说清楚Rocky Linux 9.5 的sshd.service里写的是Typenotify和KillModeprocess。KillModeprocess意味着systemctl restart sshd只杀主进程已经建立的连接各自有独立的子进程不会被一起干掉——这是重启 sshd 不会踢掉当前会话的底层原因也是敢在业务机上重启的底气。但这个保护只对已建立的连接有效新连接能不能进来取决于你改完的配置对不对。3.4 用 ldd 和 objdump 验链接关系编完先别急着打包把链接关系验一遍这一步能省掉后面 80% 的为什么版本没变。# 看 sshd 实际加载的是哪份 libssl / libcrypto ldd /usr/sbin/sshd | grep -E libssl|libcrypto # 看 rpath 有没有真的写进去 objdump -p /usr/sbin/sshd | grep -E RPATH|RUNPATH # 最直接的一条sshd -V 会把 OpenSSL 版本打出来 /usr/sbin/sshd -V判定标准很明确ldd输出必须是libssl.so.3 /opt/openssl-3.5.0/lib64/libssl.so.3如果指向/lib64/libssl.so.3就说明链错了八成是LDFLAGS没生效或者系统上装了 openssl-devel 导致路径被抢。objdump的 RUNPATH 里必须能看到/opt/openssl-3.5.0/lib64。最后sshd -V那行输出形如OpenSSH_10.0p1, OpenSSL 3.5.0两个版本号都对上才算过关。注意ssh -V和sshd -V都要看客户端和服务端是两套二进制有时候只编对了一半。4. spec 与升级脚本能一键回滚的 OpenSSH 加固才算升级4.1 spec 骨架%prep 到 %install 逐段拆spec 不用从零写rpmdev-newspec生成骨架再改就行。真正有判断的是下面这几段。Name: openssh Version: 10.0p1 Release: 1%{?dist} Summary: OpenSSH 10.0p1 built against OpenSSL 3.5.0 License: BSD-ISC URL: https://www.openssh.com/ Source0: https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz # 顶替仓库里的三个子包让 dnf 安装时自动替换而不是报冲突 Provides: openssh-server %{version}-%{release} Provides: openssh-clients %{version}-%{release} Obsoletes: openssh-server %{version}-%{release} Obsoletes: openssh-clients %{version}-%{release} BuildRequires: gcc make pam-devel zlib-devel libselinux-devel BuildRequires: krb5-devel audit-libs-devel libfido2-devel Requires: pam, zlib %description OpenSSH portable release built in-tree against a private OpenSSL 3.5.0. %prep %setup -q -n openssh-%{version} %build export LDFLAGS-Wl,-rpath,/opt/openssl-3.5.0/lib64 -Wl,-z,relro -Wl,-z,now %configure \ --prefix/usr --sysconfdir/etc/ssh --libdir/usr/lib64 \ --with-ssl-dir/opt/openssl-3.5.0 \ --with-pam --with-selinux --with-auditlinux --with-kerberos5 \ --with-privsep-path/var/empty/sshd --with-privsep-usersshd \ --with-pid-dir/run --disable-strip make %{?_smp_mflags} %install rm -rf %{buildroot} make DESTDIR%{buildroot} install # 这两个目录 make install 不会建缺了 sshd 起不来 install -d -m 0755 %{buildroot}/var/empty/sshd install -d -m 0755 %{buildroot}/etc/ssh/sshd_config.dProvides/Obsoletes这两组是整个 spec 里最容易漏、后果又最直接的部分。发行版把 OpenSSH 拆成了 openssh、openssh-clients、openssh-server 三个包你自建一个单包直接装dnf 会因为文件冲突和依赖冲突拒绝加上这三行安装时它会自动把仓库版本替换掉dnf install ./openssh-10.0p1-1.el9.x本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?