OpenSSH 升级文档
统一版本:zlib-1.3.2、openssl-3.5.8、openssh-10.5p1
适用场景:第一台机器按详细步骤走通,后续机器直接复制粘贴
OpenSSL、OpenSSH 和 zlib 介绍
三个组件是层层依赖的关系,升级顺序必须由底层往上层走:zlib → openssl → openssh。
zlib
- 通用的数据压缩/解压缩库,提供 DEFLATE 算法实现,产出
libz.so。 - 自身不涉及任何加密,是最底层的依赖。
- 在 OpenSSH 中的作用:负责 SSH 传输层的压缩 (
Compression yes)。SSH 协商出的zlib@openssh.com等压缩算法就是调用它;如果编译时缺少 zlib,OpenSSH 会失去压缩能力甚至编译失败。
OpenSSL
- 密码学与 TLS/SSL 协议库,产出
libssl.so、libcrypto.so(以及命令行工具openssl)。 - 提供 SSH 所需的全部密码学能力:
- 加密算法(AES、ChaCha20 等)
- 哈希/摘要(SHA-2 等)
- 密钥交换(ECDH、DH、Curve25519 等)
- 非对称算法与密钥/证书处理(RSA、ECDSA、Ed25519)
- 安全随机数(
/dev/urandom封装)
- 与 zlib 的关系:OpenSSL 会把 zlib 作为可选依赖,用于 TLS 压缩(现代版本中 TLS 压缩默认禁用),所以二者不是强绑定。
- /usr/bin/openssl 是一个命令行工具,可以用于生成秘钥对,生成证书等
- 同时提供tls ssl相关的协议库,比如https 底层就是使用tls ssl协议库,同时使用zlib的库来压缩函数
OpenSSH
- 应用层程序集:
sshd(服务端)、ssh(客户端)、scp、sftp、ssh-keygen等,是最上层。 - 它不自己实现密码学,而是调用 OpenSSL 完成加密、密钥交换和密钥/证书解析,调用 zlib 完成压缩。
- 因此它是被升级的目标:升级 OpenSSH 往往是因为它依赖的 OpenSSL 存在漏洞或版本过旧,所以要连带把底层两个组件一起升级。
依赖关系
OpenSSH (sshd / ssh / scp / sftp)
├── 加密、密钥交换、证书 ──▶ OpenSSL (libssl.so / libcrypto.so)
│ └── 可选压缩 ──▶ zlib (libz.so)
└── 传输层压缩 ──▶ zlib (libz.so)
- 三者版本必须成对匹配:OpenSSH 编译时会把 OpenSSL 的路径和版本编译进程序,升级了 OpenSSL 却不重新编译 OpenSSH,或者运行时加载到旧版库,都会导致
sshd起不来。 - 这正是文档中要做两件事的原因:
- 编译时用
--with-zlib=/usr/local/zlib-1.3.2 --with-ssl-dir=/usr/local/openssl-3.5.8指定新库路径; - 运行时用
/usr/lib64/libssl.so.3、libcrypto.so.3软链接和 service 里的LD_LIBRARY_PATH保证sshd加载到新编译的库,而不是系统自带的旧版 OpenSSL 1.1.1。
- 编译时用
整体思路
- 启用 telnet 连接服务器,防止操作 ssh 失误导致无法连接到服务器。
- 编译 zlib、openssl、openssh 到 /usr/local 目录【不要和系统原本的openssl openssh等冲突,不要覆盖老的】。(要先升级zlib、然后是penssl、最后是openssh)
- 为 openssl 编译出来的库创建符号链接。
- 停止系统自带 openssh。
- 为新编译的 ssh 创建 service 文件,启动并设置开机自启。
- 在其他服务器验证当前服务器 ssh 版本。
- 停用 telnet,恢复防火墙与 SELinux。
*** 可以通过 ***
ldconfig 加载动态链接库的配置文件,下面是老版本的
root# ldconfig -p | grep -E 'libssl|libcrypto'
libssl3.so (libc6,AArch64) => /usr/lib64/libssl3.so
libssl.so.1.1 (libc6,AArch64) => /usr/lib64/libssl.so.1.1
libssl.so (libc6,AArch64) => /usr/lib64/libssl.so
libcrypto.so.1.1 (libc6,AArch64) => /usr/lib64/libcrypto.so.1.1
libcrypto.so (libc6,AArch64) => /usr/lib64/libcrypto.so
root@Web ld.so.conf.d#
1. 下载源码
| 组件 | 版本 | 下载地址 |
|---|---|---|
| zlib | 1.3.2 | https://zlib.net/zlib-1.3.2.tar.gz |
| OpenSSL | 3.5.8(LTS) | https://github.com/openssl/openssl/releases/download/openssl-3.5.8/openssl-3.5.8.tar.gz |
| OpenSSH | 10.5p1 | https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/openssh-10.5p1.tar.gz |
备用地址与校验:
- OpenSSH 官方 CDN:https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-10.5p1.tar.gz
- OpenSSH SHA256 =
1E0oqDnqna+WnMaRUP3lmRCys5Nh2tgaO9bL0ZIY2xE=(base64,非 hex) - zlib 签名:https://zlib.net/zlib-1.3.2.tar.gz.asc
- OpenSSL 校验:https://github.com/openssl/openssl/releases/download/openssl-3.5.8/openssl-3.5.8.tar.gz.sha256
- 各组件官方页面:OpenSSH https://www.openssh.com/portable.html 、OpenSSL https://openssl-library.org/source/ 、zlib https://zlib.net/
源码上传到 /opt/source 并解压。
2. 启用 telnet
2.1 在有网的服务器下载(可选)
sh
yum install telnet xinetd --downloadonly --downloaddir=/root/telnet
cd /root/telnet
rpm -ivh *.rpm
# 如果服务器已安装,用 reinstall
2.2 如果没网,用离线包安装
sh
rpm -q xxx
rpm -e xxx
rpm -ivh *.rpm
2.3 启动 telnet
sh
systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
sestatus
sh
systemctl start telnet.socket
systemctl start xinetd
systemctl status telnet.socket
systemctl status xinetd
systemctl enable telnet.socket
systemctl enable xinetd
2.4 添加终端允许,不然远程会被拦截(可选)
sh
# 这里可信终端可以多添加一些
echo 'pts/0' >>/etc/securetty
echo 'pts/1' >>/etc/securetty
echo 'pts/20' >>/etc/securetty
# 重启服务
systemctl restart telnet.socket
systemctl restart xinetd
systemctl status telnet.socket
systemctl status xinetd
3. 记录原openssh/ssl/zlib版本
sh
[root@ecs ~]# ssh -V
OpenSSH_8.2p1, OpenSSL 1.1.1f 31 Mar 2020
[root@ecs ~]# openssl version
OpenSSL 1.1.1f 31 Mar 2020
[root@ecs source]# zlib -v
-bash: zlib:未找到命令
[root@Web ~]# whereis ssh
ssh: /usr/bin/ssh /etc/ssh /usr/share/man/man1/ssh.1.gz
[root@Web ~]# whereis openssl
openssl: /usr/bin/openssl /usr/include/openssl /usr/share/man/man1/openssl.1_openssl.gz
[root@Web ~]# whereis zlib
zlib: /usr/include/zlib.h
4. 升级
4.1 停止 sshd
sh
systemctl stop sshd
systemctl disable sshd
4.2 编译
sh
cd /opt/source/zlib-1.3.2
./configure --prefix=/usr/local/zlib-1.3.2
make && make install
cd /opt/source/openssl-3.5.8
./Configure --prefix=/usr/local/openssl-3.5.8
make && make install
[root@ecs---0002 lib64]# ls -al /usr/lib64/libssl.so.1.1
lrwxrwxrwx 1 root root 16 7月 7 2022 /usr/lib64/libssl.so.1.1 -> libssl.so.1.1.1f
[root@ecs---0002 lib64]# ls -al /usr/lib64/libcrypto.so.1.1
lrwxrwxrwx 1 root root 19 7月 7 2022 /usr/lib64/libcrypto.so.1.1 -> libcrypto.so.1.1.1f
# 版新安装额这个openssl动态库的地址 写入到系统动态库查找配置文件中,这样相关依赖这个库的程序就可以通过ld动态连接器找到这个版本
echo '/usr/local/openssl-3.5.8/lib' >> /etc/ld.so.conf
# 备份老的,再建新的符号链接
# mv /usr/bin/openssl /usr/bin/openssl.old
# ln -s /usr/local/openssl-3.5.8/bin/openssl /usr/bin/openssl
ln -s /usr/local/openssl-3.5.8/lib/libssl.so.3 /usr/lib64/libssl.so.3
ln -s /usr/local/openssl-3.5.8/lib/libcrypto.so.3 /usr/lib64/libcrypto.so.3
# 如果符号链接已存在:unlink /usr/lib64/libssl.so.3 && unlink /usr/lib64/libcrypto.so.3 后再建
# 注意 rm 时最后边不要带 /
### 安装之后查看
[root]# ldconfig -p | grep -E 'libssl|libcrypto'
cd /opt/source/openssh-10.5p1
./configure --prefix=/usr/local/openssh-10.5p1 --with-zlib=/usr/local/zlib-1.3.2 --with-ssl-dir=/usr/local/openssl-3.5.8
make && make install
4.3 配置与生成 host key
- 修改配置
sh
vim /usr/local/openssh-10.5p1/etc/sshd_config
#root 用户能否直接登录
PermitRootLogin yes
#是否启用公钥认证
PubkeyAuthentication yes
#是否启用密码认证
PasswordAuthentication yes
# 重新生成主机密钥
rm -f /usr/local/openssh-10.5p1/etc/ssh_host_*_key*
/usr/local/openssh-10.5p1/bin/ssh-keygen -A
4.4 创建 service 文件【新版本的ssd服务,指定新版本的动态库地址】
通过环境变量: LD_LIBRARY_PATH 来指定动态库地址
sh
tee /etc/systemd/system/sshd-custom.service<<-'eof'
[Unit]
Description=OpenSSH Server (Custom)
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
# Set library path for custom OpenSSL and Zlib
Environment="LD_LIBRARY_PATH=/usr/local/openssl-3.5.8/lib:/usr/local/zlib-1.3.2/lib"
ExecStartPre=/usr/local/openssh-10.5p1/sbin/sshd -t
ExecStart=/usr/local/openssh-10.5p1/sbin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
[Install]
WantedBy=multi-user.target
eof
4.5 启动并验证
sh
echo 'export PATH=/usr/local/openssh-10.5p1/bin:/usr/local/openssh-10.5p1/sbin:$PATH' >> ~/.bashrc
chmod 600 /usr/local/openssh-10.5p1/etc/ssh_host_*_key
chmod 644 /usr/local/openssh-10.5p1/etc/ssh_host_*_key.pub
chmod 644 /usr/local/openssh-10.5p1/etc/sshd_config
systemctl daemon-reload
systemctl start sshd-custom
systemctl status sshd-custom
systemctl enable sshd-custom
sh
# 扫描 22 端口 验证是否启动服务
nmap -sV -p 22 xxx.x.x.x
5. 恢复 telnet、防火墙
升级验证通过后执行(第一台机器与后续机器均适用)。
sh
systemctl start firewalld.service
systemctl enable firewalld.service
setenforce 1
sed -i 's/SELINUX=disabled/SELINUX=enforcing/g' /etc/sysconfig/selinux
sed -i 's/SELINUX=disabled/SELINUX=enforcing/g' /etc/selinux/config
sestatus
sh
systemctl stop telnet.socket
systemctl stop xinetd
systemctl status telnet.socket
systemctl status xinetd