☰
OpenSSH 10.0p1 与 OpenSSL 3.5.0 编译加固实战
2026/11/2 6:41:49 网站建设 项目流程

简介:面向 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.7p1,OpenSSL 是 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-pam
SELinux 策略系统自带沿用装完必须 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-FindBin,OpenSSL 3.x 的 Configure 脚本是用 Perl 写的,缺了 IPC::Cmd 会直接抛Can't 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 ~/rpmbuild

rpmdev-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.0:rpath 决定了 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 \ --libdir=lib64 \ shared \ zlib \ no-ssl3 no-weak-ssl-ciphers

这里用的是大写./Configure而不是小写./config。小写那个会先猜平台再调大写脚本,猜错了你都不知道;大写版本参数原样落地,适合写进文档复现。

--prefix指向 /opt 下的独立目录,这是整套方案的地基,保证不碰系统库。--openssldir单独指到前缀内部,存放 openssl 自己的配置和证书搜索路径;这一项千万别写成/etc/pki/tls,否则make install会把系统证书目录覆盖成 3.5.0 的格式,dnf 立刻报错。--libdir=lib64是为了跟系统 /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_JOBS=4 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_SOURCE=2" \ 2>&1 | tee /tmp/ssh-configure.log

--prefix=/usr和--sysconfdir=/etc/ssh是为了贴合系统原生目录结构,编译出来直接顶替原来的二进制,不改变 systemd 单元里写死的路径。--libexecdir指向 /usr/libexec/openssh,sfp-server 之类的辅助程序会装在这里。--with-privsep-path=/var/lib/sshd必须和系统原来的 privsep 目录保持一致,因为这个目录需要 root 属主、711 权限,变更路径等于多一个出错点。

--with-ssl-dir是这次升级的核心,指向刚编好的 /opt/openssl-3.5.0,configure 会从这里找头文件和库。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/stage

DESTDIR=/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已移除删掉,用PubkeyAuthentication
DSAAuthentication yes已移除删掉,DSA 算法本身也没了
UsePrivilegeSeparation sandbox已移除删掉,强制开启
ServerKeyBits 1024已移除删掉
ChallengeResponseAuthentication no改名换成KbdInteractiveAuthentication no

除了配置项,还得检查主机密钥。老机器上很可能躺着/etc/ssh/ssh_host_dsa_key,10.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.pub

4.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-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.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-sha512@openssh.com是抗量子混合密钥交换,10.0p1 支持,客户端版本太老会协商失败,所以后面补了 curve25519 和 ecdh 作为兼容项。Ciphers只留 AEAD 系列和 aes256-ctr,把 CBC 模式全部踢掉。PubkeyAcceptedAlgorithms限制了可接受的公钥签名算法,rsa-sha2-512 保留是为了兼容还在用 RSA 2048 的老客户端,纯 ed25519

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询