
简介面向 Rocky Linux 9.5 环境的运维与安全加固人员这份方案包针对系统自带 OpenSSH 版本偏低、手工编译升级易出现依赖冲突与启动异常的问题而准备。包内提供已适配 el9 的 OpenSSH 10.0p1 与 OpenSSL 3.5.0 相关 RPM覆盖服务端、客户端以及 chkconfig、initscripts 等配套依赖并附一键升级加固脚本可在保留 SYSV 方式管理 sshd 的前提下完成版本替换减少升级后服务无法拉起、端口策略失效等常见风险。整包共 6 个文件以 5 个 rpm 安装包和 1 个 sh 升级脚本为主压缩后约 10.96MB体积轻量便于内网分发与离线部署。目前已有 210 人学习下载适合需要批量加固、快速验证或搭建测试环境的运维工程师参考也可作为版本回退与配置比对的实践素材。1. 一台跳板机引发的版本对齐一台 Rocky Linux 9.5 的跳板机扫描报告里 OpenSSH 8.7p1 那一串条目怎么都清不掉于是决定把 openssh 加固一次做到位直接上 OpenSSH 10.0p1连 OpenSSL 3.5.0 一起换最后打成 rpm 落到 x86_64 机器上。听起来是三步我第一次做的时候二十分钟就把自己关在门外——sshd 起不来老会话一断就再也连不上。原因很朴素10.0p1 编译时链的还是系统 3.0.7而我又用 make install 覆盖了 /usr/sbin/sshd包管理器一更新就打回原形。这套组合在漏洞清零、等保整改的场景里非常常见适合手里有 Rocky 9.x、又必须交付一个可回滚 RPM 的运维。下面按我实际落地的顺序写从依赖到编译从加固到翻车记录。2. 依赖、目录与基线动手前先留后悔药2.1 三个版本号先对齐别急着敲命令Rocky Linux 9.5 自带的 OpenSSH 是 8.7p1OpenSSL 是 3.0.7两者都在系统仓库里互相咬得很紧。这次要换的是 OpenSSH 10.0p1而它要求一个足够新的 OpenSSL所以 3.5.0 得一起编。真正要决策的地方在于OpenSSL 3.5.0 装到哪里。组件基线以 rpm -q 为准本次目标处理方式OpenSSH8.7p1-x.el910.0p1源码编译打成 RPM 替换系统包OpenSSL3.0.7-x.el93.5.0源码编译到 /opt绝不替换系统库zlib1.2.11沿用链接系统库PAM1.5.1沿用configure 带 --with-pamSELinux 策略系统自带沿用装完必须 restorecon为什么 OpenSSL 不直接替换 /usr/lib64 下的那套因为系统里几百个包都依赖 libcrypto.so.3把库换掉是整个系统级别的操作dnf、rpm、systemd 全在依赖链上出事就不是 sshd 连不上而是机器起不来。常见做法是给 OpenSSL 一个独立前缀 /opt/openssl-3.5.0让 sshd 用 rpath 指过去系统库一个字节都不动。还有一个容易被忽略的差异OpenSSH 10.0p1 把 DSA 算法彻底删了SHA-1 签名的 ssh-rsa 也不再是可选项老机器上如果还有 ssh_host_dsa_key 或者只认 diffie-hellman-group1-sha1 的客户端升级当天就会掉线。这一条在后面的配置迁移里会反复出现。2.2 依赖清单以及三个最容易漏的包编译 OpenSSH 的依赖不算多但缺一个就卡在 configure 阶段。我一般一次性装齐dnf -y install \ gcc gcc-c make \ perl perl-core perl-IPC-Cmd perl-FindBin \ zlib-devel pam-devel libselinux-devel audit-libs-devel krb5-devel \ rpm-build rpmdevtools systemd-rpm-macros openssl-devel这行命令里有三组东西值得单独说。第一组是perl-IPC-Cmd和perl-FindBinOpenSSL 3.x 的 Configure 脚本是用 Perl 写的缺了 IPC::Cmd 会直接抛Cant locate IPC/Cmd.pm in INC报错信息跟 OpenSSL 一点关系都没有新手很容易在这里怀疑人生。第二组是pam-devel、libselinux-devel、audit-libs-devel、krb5-devel它们分别对应 configure 里的--with-pam、--with-selinux、--with-audit、--with-kerberos5少装一个configure 会静默降级编出来的 sshd 少了 PAM 就等于把账号体系绕过去了非常隐蔽。第三组是rpm-build和rpmdevtools后面打包要用。rpmdev-setuptree ls ~/rpmbuildrpmdev-setuptree会在当前用户家目录下建出 BUILD、RPMS、SOURCES、SPECS、SRPMS 五个目录后面 spec 文件放 SPECS源码和预编译产物放 SOURCES。用普通用户跑别用 root 跑 rpmbuild否则 RPMS 目录属主会乱。2.3 目录规划与基线备份mkdir -p /opt/src cd /opt/src rpm -qa | grep -E ^(openssh|openssl) | sort /root/pkg-baseline.txt tar -czf /root/ssh-backup-$(date %F).tar.gz \ /etc/ssh /etc/pam.d/sshd /etc/sysconfig/sshd cp -a /usr/sbin/sshd /root/sshd.bak.8.7p1第一行是工作目录源码包统一放 /opt/src后面所有解压都在这里。第二行把当前的包版本落成文件出问题时要对比的就是这份基线。第三行备份三个关键路径/etc/ssh 里的配置和主机密钥、/etc/pam.d/sshd 里的认证栈、/etc/sysconfig/sshd 里的启动参数。第四行把旧 sshd 二进制单独留一份这是最后的后悔药——最坏情况下cp /root/sshd.bak.8.7p1 /usr/sbin/sshd再systemctl restart sshd机器就能恢复到能登录的状态。提示动手前先开一个 root 的 SSH 会话挂在 tmux 里不要关。sshd reload 不会掐断已有连接但配置写错之后新连接进不来这时候那根老会话就是唯一的救命通道。3. 编译 OpenSSL 3.5.0rpath 决定了 sshd 能不能活3.1 Configure 参数怎么取舍cd /opt/src tar -xzf openssl-3.5.0.tar.gz cd openssl-3.5.0 ./Configure \ --prefix/opt/openssl-3.5.0 \ --openssldir/opt/openssl-3.5.0/ssl \ --libdirlib64 \ shared \ zlib \ no-ssl3 no-weak-ssl-ciphers这里用的是大写./Configure而不是小写./config。小写那个会先猜平台再调大写脚本猜错了你都不知道大写版本参数原样落地适合写进文档复现。--prefix指向 /opt 下的独立目录这是整套方案的地基保证不碰系统库。--openssldir单独指到前缀内部存放 openssl 自己的配置和证书搜索路径这一项千万别写成/etc/pki/tls否则make install会把系统证书目录覆盖成 3.5.0 的格式dnf 立刻报错。--libdirlib64是为了跟系统 /usr/lib64 的命名习惯保持一致后面写 rpath 的时候不容易写错路径。shared生成动态库sshd 要动态链接 libcrypto 才能被 rpath 接管纯静态链接在 PAM 和 NSS 场景下会出各种奇怪的问题不建议。zlib打开压缩支持no-ssl3 no-weak-ssl-ciphers是顺手把弱算法关掉反正 sshd 用不到 SSLv3。3.2 编译与安装install_sw 和 install 的区别make -j$(nproc) # 可选跑一遍自测20~40 分钟赶时间可以跳过 make test HARNESS_JOBS4 make install_sw-j$(nproc)按核数并行8 核机器大概三到五分钟编完。make test我一般会跑尤其是第一次在新架构上编的时候它能提前暴露 CPU 指令集相关的坑但如果只是例行升级、时间又紧跳过也不影响 sshd 使用。安装用make install_sw而不是make install。install_sw只装软件本体库、头文件、可执行文件不装文档make install会额外把 HTML 文档和 man page 一起铺进去几百兆的文档对一台跳板机毫无意义。如果后面确实需要 openssl 的 man page 做排查单独补一个make install_docs就行。3.3 验证安装与那个必须知道的 SONAME 坑/opt/openssl-3.5.0/bin/openssl version -a readelf -d /opt/openssl-3.5.0/lib64/libssl.so.3 | grep SONAME ldd /opt/openssl-3.5.0/bin/openssl | grep -E ssl|crypto第一条输出里会带 OPENSSLDIR 和 built on 两行确认 OPENSSLDIR 是/opt/openssl-3.5.0/ssl说明前缀生效了。第二条是重点readelf -d查动态段SONAME 那一行会显示libssl.so.3。注意这里就是全套方案里最危险的地方——OpenSSL 3.5.0 的 SONAME 是libssl.so.3和libcrypto.so.3跟系统 3.0.7 完全一样。动态链接器只认名字不认版本。所以一旦有人图省事写一个/etc/ld.so.conf.d/openssl35.conf把/opt/openssl-3.5.0/lib64塞进去再ldconfig系统里所有依赖 libcrypto.so.3 的程序都会切到 3.5.0 上运气好相安无事运气不好 dnf 直接报符号缺失。正确做法是让 sshd 自己带 rpath只让自己找得到这套库# 反例不要这么干 # echo /opt/openssl-3.5.0/lib64 /etc/ld.so.conf.d/openssl35.conf ldconfig同样也别把LD_LIBRARY_PATH/opt/openssl-3.5.0/lib64写进 /etc/profile.d那等于给全系统所有进程都改了库搜索路径比改 ld.so.conf 还难排查。临时调试可以用用完就撤。4. 编译 OpenSSH 10.0p1从 configure 到 RPM 落地4.1 configure 的关键参数少一个都别往下走cd /opt/src tar -xzf openssh-10.0p1.tar.gz cd openssh-10.0p1 ./configure \ --prefix/usr \ --sysconfdir/etc/ssh \ --libexecdir/usr/libexec/openssh \ --with-privsep-path/var/lib/sshd \ --with-ssl-dir/opt/openssl-3.5.0 \ --with-pam \ --with-selinux \ --with-audit \ --with-kerberos5 \ --with-xauth/usr/bin/xauth \ --with-default-path/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ LDFLAGS-Wl,-rpath,/opt/openssl-3.5.0/lib64 \ CFLAGS-O2 -g -fstack-protector-strong -D_FORTIFY_SOURCE2 \ 21 | tee /tmp/ssh-configure.log--prefix/usr和--sysconfdir/etc/ssh是为了贴合系统原生目录结构编译出来直接顶替原来的二进制不改变 systemd 单元里写死的路径。--libexecdir指向 /usr/libexec/opensshsfp-server 之类的辅助程序会装在这里。--with-privsep-path/var/lib/sshd必须和系统原来的 privsep 目录保持一致因为这个目录需要 root 属主、711 权限变更路径等于多一个出错点。--with-ssl-dir是这次升级的核心指向刚编好的 /opt/openssl-3.5.0configure 会从这里找头文件和库。LDFLAGS里的-Wl,-rpath把运行期库路径烧进二进制sshd 启动时就不用依赖 ldconfig 了这也是前面拒绝改 ld.so.conf 的配套动作。--with-pam、--with-selinux、--with-audit三个开关分别决定认证栈、强制访问控制和审计日志生产环境一个都不能少少了 audit等保里的登录审计直接不达标。编完先看 configure 的输出grep -E checking for OpenSSL|PAM|SELinux|privilege /tmp/ssh-configure.log正常应该看到checking for OpenSSL... /opt/openssl-3.5.0。如果这一行显示的是/usr说明--with-ssl-dir没生效多半是路径写错或者那套库没装全这时候别往下 make编出来还是旧库。make -j$(nproc) make install DESTDIR/opt/src/stageDESTDIR/opt/src/stage是打包用的暂存目录把所有产物先装到 stage 下再由 spec 的%install段整体拷进 buildroot。这一步能避免make install直接写 /usr 带来的“装完了才发现要重来”的尴尬。4.2 老 sshd_config 里必须先删掉的行10.0p1 对老配置项的容忍度很低凡是已经被移除的指令sshd -t会直接报Bad configuration option并拒绝启动。上线前先扫一遍grep -nE ^(Protocol|RSAAuthentication|DSAAuthentication|UsePrivilegeSeparation|ServerKeyBits|KeyRegenerationInterval|RhostsRSAAuthentication|ChallengeResponseAuthentication) /etc/ssh/sshd_config旧写法10.0p1 现状处理方式Protocol 2已移除整行删掉RSAAuthentication yes已移除删掉用PubkeyAuthenticationDSAAuthentication yes已移除删掉DSA 算法本身也没了UsePrivilegeSeparation sandbox已移除删掉强制开启ServerKeyBits 1024已移除删掉ChallengeResponseAuthentication no改名换成KbdInteractiveAuthentication no除了配置项还得检查主机密钥。老机器上很可能躺着/etc/ssh/ssh_host_dsa_key10.0p1 加载时会报错。这套文件如果确认没有任何客户端在用直接删掉并把 sshd_config 里对应的HostKey行去掉ls -l /etc/ssh/ssh_host_* # 确认没有 DSA 客户端依赖后再删 rm -f /etc/ssh/ssh_host_dsa_key /etc/ssh/ssh_host_dsa_key.pub4.3 加固片段一份能过 sshd -t 的配置加固项我习惯单独放 drop-in不动主配置文件回滚的时候删一个文件就行# /etc/ssh/sshd_config.d/00-hardening.conf PermitRootLogin prohibit-password PasswordAuthentication no KbdInteractiveAuthentication no PubkeyAuthentication yes PermitEmptyPasswords no MaxAuthTries 3 MaxSessions 4 LoginGraceTime 30 ClientAliveInterval 300 ClientAliveCountMax 2 AllowTcpForwarding no AllowAgentForwarding no X11Forwarding no PermitTunnel no LogLevel VERBOSE KexAlgorithms sntrup761x25519-sha512openssh.com,curve25519-sha256,curve25519-sha256libssh.org,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305openssh.com,aes256-gcmopenssh.com,aes128-gcmopenssh.com,aes256-ctr MACs hmac-sha2-512-etmopenssh.com,hmac-sha2-256-etmopenssh.com HostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256 PubkeyAcceptedAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256几个参数值得说清楚。PermitRootLogin prohibit-password允许 root 用密钥登录但禁止密码比直接no更实用跳板机上通常需要 root 做运维。KexAlgorithms第一项sntrup761x25519-sha512openssh.com是抗量子混合密钥交换10.0p1 支持客户端版本太老会协商失败所以后面补了 curve25519 和 ecdh 作为兼容项。Ciphers只留 AEAD 系列和 aes256-ctr把 CBC 模式全部踢掉。PubkeyAcceptedAlgorithms限制了可接受的公钥签名算法rsa-sha2-512 保留是为了兼容还在用 RSA 2048 的老客户端纯 ed25519本文还有配套的精品资源点击获取