
简介面向 Ubuntu 服务器管理员的 OpenSSH 与 zlib 升级资源包主要解决系统自带 OpenSSH 版本陈旧、安全漏洞无法及时修复的问题。包内提供 9.5p1 版 OpenSSH 源码、1.3 版 zlib 源码以及一键升级脚本适用于需要高效更新远程连接组件的运维场景例如生产环境安全加固、等保合规整改或多台服务器统一升级尤其适合缺乏深度编译经验的中级管理员。压缩包共有三个文件包含两个源代码压缩包与一个自动执行脚本整体容量约 3.18MB结构紧凑便于快速部署。目前已有 705 人学习或下载说明该升级方案具备较强参考价值。脚本可自动串联解压、编译、安装和配置等关键环节显著降低手工操作带来的出错概率同时 zlib 库的更新还能优化 SSH 数据传输的压缩效率帮助管理员在短暂维护窗口内完成安全升级并保持系统稳定运行。 前阵子给一批生产服务器做安全基线检查扫描报告出来后OpenSSH 一栏赫然列着好几个中高危 CVE 编号点开一看版本还是 8.9p1。我本来想等等 Ubuntu 官方源里的更新结果发现无论 20.04 还是 22.04apt 源里的 OpenSSH 版本都徘徊在 8.9/9.2 左右很多安全修复迟迟没有跟进。与其干等不如自己动手编译升级。这篇文章记录的是我整理的一套 Ubuntu 一键升级 OpenSSH 9.5p1 的方案同时把 zlib-1.3 这个关键基础库一并升级保证新老软件在同一个干净环境里编译通过。适合负责服务器运维、安全合规或者自己管理云主机的朋友直接抄作业。1. 升级前的环境准备与方案选型1.1 为什么建议用源码编译而不是直接 apt upgrade很多人的第一反应是OpenSSH 不是可以 apt upgrade 吗但这里有个容易被忽略的事实Ubuntu 的 Main 软件源倾向于“稳定性优先”内部的 OpenSSH 版本在系统生命周期内基本不会做大版本跳跃而是以安全补丁backport的方式持续修复。听起来好像没毛病可实际操作中你会发现某些 CVE 的修复补丁并不会第一时间同步到所有 LTS 版本尤其是一些需要结构性调整的漏洞比如协议层面的算法变更、密钥交换流程调整光靠小补丁很难彻底解决。而 OpenSSH 本身又是一个直接暴露在公网的服务属于攻击面最大的系统组件之一。等官方源更新可能等上几个月生产环境的安全扫描可不会等你。源码编译升级的好处是版本可控、修复及时、编译参数可定制坏处是需要自己处理依赖和服务配置操作失误可能导致 sshd 起不来。所以我才把整个过程做成了一个带备份和自动回滚逻辑的一键脚本既保留源码编译的优势又降低操作风险。1.2 为什么选中 openssh-9.5p1 和 zlib-1.3 这两个版本选择 OpenSSH 9.5p1主要是基于安全和兼容性的平衡点。9.5p1 是 2023 年 10 月发布的便携版修复了包括 CVE-2023-51385ssh 命令中的操作系统命令注入风险在内的多个安全问题同时引入了 mack-sntrup761x25519-sha512 等新密钥交换算法还会在连接过程中检查口令认证是否被服务端禁用从协议层面规避弱算法被强行降级的问题。这个版本对系统自带的 OpenSSL 3.x 支持也很好Ubuntu 20.04/22.04 上都能顺利编译。zlib 则相对容易被忽略但它是 OpenSSH 压缩传输的基础依赖。zlib-1.3 在 2023 年 8 月发布修复了 CVE-2023-45853zlib 在 minigzip 等场景下的内存越界问题虽然影响程度没有 OpenSSH 本身那么直接但作为基础库搭建一套自洽的新版本环境会让后续排查更省心。在脚本里我会把 zlib 编译安装到 /usr/local 前缀下再用 --with-zlib/usr/local 让 OpenSSH 链接新库既不影响系统原有库又能确保最终二进制依赖的是新版本。1.3 一键脚本的整体设计思路设计这套脚本时我给自己定了三个原则可回滚、可重复执行、出错能定位。可回滚是指执行前自动备份旧的 ssh/sshd 二进制以及 /etc/ssh 整个配置目录安装过程中任何一步校验失败都能把旧文件拷回去恢复服务。可重复执行是指脚本中所有下载都带断点续传编译前也会清理临时目录这样重跑一遍不会产生冲突。出错能定位则是靠日志文件脚本执行时的全部输出都会同时写入升级目录下的 upgrade.log方便事后排查。脚本整体分四个阶段环境检查与依赖安装、zlib 编译、OpenSSH 编译、服务替换与验证。这样的分段方式让我在调试时可以逐步确认问题出在哪而不是一把梭。接下来我会把完整脚本放出来再逐段解释核心逻辑。2. 一键升级脚本从依赖安装到二进制替换2.1 完整脚本全文以下脚本我在 Ubuntu 20.04 和 22.04 上都跑过默认安装在 x86_64 架构的服务器上。如果你的机器是 ARM 架构理论也能编译但建议先在测试机上验证一遍。#!/bin/bash # # Ubuntu 一键升级 OpenSSH 9.5p1 zlib 1.3 # 适用环境Ubuntu 20.04 / 22.04 / 24.04x86_64 / aarch64 # 使用方式sudo bash upgrade_openssh.sh # set -Eeuo pipefail VERSION_SSH9.5p1 VERSION_ZLIB1.3 BACKUP_DIR/root/backup_openssh_$(date %Y%m%d_%H%M%S) mkdir -p ${BACKUP_DIR} LOG_FILE${BACKUP_DIR}/upgrade.log exec (tee -a ${LOG_FILE}) 21 echo OpenSSH ${VERSION_SSH} zlib ${VERSION_ZLIB} 升级开始 if [[ $EUID -ne 0 ]]; then echo [ERROR] 请使用 root 用户执行脚本。 exit 1 fi # 1. 备份现有文件 echo [1/9] 备份现有的 ssh / sshd 二进制与配置目录... if [ -f /usr/sbin/sshd ]; then cp -a /usr/sbin/sshd ${BACKUP_DIR}/sshd.bak; fi if [ -f /usr/bin/ssh ]; then cp -a /usr/bin/ssh ${BACKUP_DIR}/ssh.bak; fi cp -a /etc/ssh ${BACKUP_DIR}/ssh_config_dir.bak # 2. 安装编译依赖 echo [2/9] 安装编译依赖... export DEBIAN_FRONTENDnoninteractive apt-get update -y apt-get install -y build-essential wget gcc make libssl-dev libpam0g-dev \ libsystemd-dev pkg-config # 3. 下载并编译 zlib-1.3 echo [3/9] 编译安装 zlib-${VERSION_ZLIB}... cd /tmp rm -rf zlib-${VERSION_ZLIB} zlib-${VERSION_ZLIB}.tar.gz wget -4 -c --tries3 https://zlib.net/zlib-${VERSION_ZLIB}.tar.gz \ -O zlib-${VERSION_ZLIB}.tar.gz tar xzf zlib-${VERSION_ZLIB}.tar.gz cd zlib-${VERSION_ZLIB} ./configure --prefix/usr/local make -j$(nproc) make install echo /usr/local/lib /etc/ld.so.conf.d/zlib-1.3.conf ldconfig # 4. 下载并编译 OpenSSH 9.5p1 echo [4/9] 编译安装 OpenSSH-${VERSION_SSH}... cd /tmp rm -rf openssh-${VERSION_SSH} openssh-${VERSION_SSH}.tar.gz wget -4 -c --tries3 https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-${VERSION_SSH}.tar.gz \ -O openssh-${VERSION_SSH}.tar.gz tar xzf openssh-${VERSION_SSH}.tar.gz cd openssh-${VERSION_SSH} ./configure \ --prefix/usr \ --sysconfdir/etc/ssh \ --with-zlib/usr/local \ --with-ssl-dir/usr \ --with-pam \ --with-systemd \ --with-privsep-path/var/run/sshd \ --with-md5-passwords make -j$(nproc) # 5. 替换二进制 echo [5/9] 安装新编译产物到系统路径... install -d -o root -g root -m 0755 /var/run/sshd make install # 6. 测试新 sshd 配置 echo [6/9] 校验新 sshd 配置... if ! /usr/sbin/sshd -t; then echo [ERROR] sshd -t 校验失败正在自动回滚。 if [ -f ${BACKUP_DIR}/sshd.bak ]; then cp -a ${BACKUP_DIR}/sshd.bak /usr/sbin/sshd fi if [ -f ${BACKUP_DIR}/ssh.bak ]; then cp -a ${BACKUP_DIR}/ssh.bak /usr/bin/ssh fi systemctl restart ssh exit 1 fi # 7. 重启服务 echo [7/9] 重启 ssh 服务... systemctl restart ssh sleep 2 # 8. 输出验证信息 echo [8/9] 升级后版本信息 ssh -V /usr/sbin/sshd -V 21 || true ldd /usr/sbin/sshd | grep -E libz|libssl || true # 9. 完成 echo [9/9] 升级流程结束备份目录${BACKUP_DIR} echo 全部完成请新开一个终端确认可以正常登录再关闭当前会话 2.2 几个必须理解的编译参数这套脚本里最值得解释的就是 configure 阶段的那几个参数缺一个都可能在重启后连不上服务器。--with-pam 是重中之重。Ubuntu 的登录认证默认走 PAM 体系密码验证、sudo 联动都依赖 /etc/pam.d/sshd 这个配置。如果编译时不加这个参数新 sshd 将不读取 PAM 配置密码登录基本会失效。同样道理configure 阶段还需要系统里有 libpam0g-dev否则会直接报错。--with-systemd 也很关键。Ubuntu 的 ssh 服务由 systemd 管理加上这个参数后sshd 会在启动完成时向 systemd 发送就绪通知systemctl restart ssh 就不会出现“服务已启动但实际监听失败”这种错觉。--with-privsep-path/var/run/sshd 对应的是 sshd 权限分离功能的工作目录。我见过不少编译教程漏掉这个参数结果 sshd 启动时报 “Missing privilege separation directory” 的错误。Ubuntu 原本就使用 /var/run/sshd 这个路径脚本里提前创建目录并保持 0755 权限能避免这类问题。2.3 为什么把 zlib 装到 /usr/local而不是直接替换系统库这里必须提醒一下千万别图省事把新编译的 zlib 直接覆盖到 /usr/lib/x86_64-linux-gnu/ 下面。系统里很多核心工具如 apt、curl 的某些组件都依赖旧版 libz.so.1粗暴替换可能导致整个系统的动态库链接错乱。更安全的做法是装到 /usr/local/lib然后通过 ld.so.conf.d 下的配置文件让系统优先加载新库。脚本链接 OpenSSH 时用 --with-zlib/usr/local编译出来的 sshd 就会记录对 /usr/local/lib/libz.so.1 的依赖。同时脚本会执行 ldconfig 刷新动态库缓存这样运行时二进制才能正确找到新库。你可以用 ldd /usr/sbin/sshd 验证正常情况下输出里会出现 “libz.so.1 /usr/local/lib/libz.so.1” 这一行。3. 实操验证与常见问题排查3.1 执行升级前的三项准备工作在生产环境跑一键脚本之前强烈建议先确认三件事。第一确保你拥有 root 权限或者 sudo 权限且当前登录会话是通过 SSH 密钥认证而不是纯密码认证。因为升级过程中要重启 sshd一旦新配置有问题导致密码登录失效至少还能用密钥从另一条路径登录服务器。没有密钥的用户建议先找一个不依赖该服务器的带外管理终端比如云控制台的 VNC。第二提前确认防火墙规则。Ubuntu 上如果启用了 ufw需要确保 22 端口或者你自定义的 ssh 端口是放行的。脚本里虽然不会改防火墙规则但重启 sshd 的瞬间旧的连接可能被断开如果防火墙拦截了新端口再想登回来就很被动。第三下载源码包时尽量保证网络稳定。脚本里的 wget 用了 -4 参数强制走 IPv4并且加了 --tries3 重试。如果下载中断也没关系脚本开头会清理临时文件重新下载。不过对于处于网络隔离环境的内网机器最好提前把两个 tar 包放到 /root 目录再把脚本里的下载命令改成直接使用本地包。3.2 升级后的完整验证清单脚本执行到最后会输出 ssh -V 和 sshd -V但这只是第一步。我更建议手动跑一遍下面的验证清单# 查看版本信息 ssh -V sshd -V # 检查监听端口 ss -tlnp | grep :22 # 检查新版本是否链接新 zlib ldd /usr/sbin/sshd | grep zlib # 检查服务状态 systemctl status ssh --no-pager光看版本号和监听还不够真正重要的是“另开一个新会话测试登录”。我习惯在升级后用另一个终端重新 ssh 登录一次确认验证方式、终端交互、sudo 操作都正常然后再关闭原先的连接。这样即使当前会话被误杀你也不会被困在服务器外面。3.3 升级过程中最容易踩的 5 个坑我在折腾这套脚本的时候几乎把每个坑都踩了一遍整理成下表方便你对照排查。现象可能原因解决办法sshd -t 校验失败提示 bad permissions/etc/ssh/ 下某些密钥文件权限过宽执行 chmod 600 /etc/ssh/ssh_host_*_key公钥保持 644重启后密码登录失败编译时少了 --with-pam或 pam.d 配置损坏确认 configure 参数里有 --with-pam并保留原 /etc/pam.d/sshdsshd 启动报 Missing privilege separation directory--with-privsep-path 指向了不存在的目录执行 install -d -o root -g root -m 0755 /var/run/sshd新 sshd 链接到旧 libz.so.1没有执行 ldconfig 或 ld 配置缺失写入 /etc/ld.so.conf.d/zlib-1.3.conf 后执行 ldconfigapt 源下载慢或失败官方源在国外内网访问不稳定提前下载 tar 包到本地或配置内网镜像源3.4 一次 sshd 启动失败的排查记录这里分享一次真实排查经历。有一台机器执行升级后ssh -V 已经显示 9.5p1但 systemctl restart ssh 报失败。我第一反应是配置文件语法问题于是单独跑 /usr/sbin/sshd -t结果它输出 “Missing privilege separation directory: /var/run/sshd”。原因是我在一台刚初始化的服务器上执行脚本时/var/run/sshd 并没有默认创建而旧版 sshd 在某些条件下会自动处理新版对权限分离目录的要求更严格。排查之后我在脚本里加入了 install -d 创建目录的步骤顺手把目录权限固定为 root:root 0755问题解决。这也说明一个问题排查顺序先看 sshd -t 的明确报错再用 systemctl status 看 systemd 层面的日志最后才需要查 /var/log/auth.log。按这个顺序走基本能快速缩小范围。4. 回滚方案与升级后的加固建议4.1 出现问题如何一键回滚脚本本身已经带了一部分自动回滚逻辑即 sshd -t 校验失败时自动恢复备份。但如果升级完成后某个配置项不兼容导致服务无法启动就需要手动回滚备份目录里的二进制。回滚操作很简单找到脚本生成的备份目录执行如下命令BACKUP_DIR$(ls -d /root/backup_openssh_* | tail -n 1) systemctl stop ssh cp -a ${BACKUP_DIR}/sshd.bak /usr/sbin/sshd cp -a ${BACKUP_DIR}/ssh.bak /usr/bin/ssh systemctl start ssh ssh -V如果你在升级后又手动修改过配置回滚前最好把当前 /etc/ssh 目录再存一份备份方便对比差异。不要急着删除 backup_openssh_* 目录我通常会把最近三次的备份都留下确认线上稳定一周后再清理旧备份。4.2 升级后的安全加固建议OpenSSH 升级到 9.5p1 只是第一步接下来顺手做一轮基础的 ssh 加固会让收益翻倍。先检查 sshd_config 里的几个关键项PermitRootLogin 如果不需要 root 远程登录建议改成 prohibit-passwordPasswordAuthentication 在条件允许时关闭优先使用密钥登录X11Forwarding 默认建议设为 no减少不必要的转发通道。协议层面可以在 /etc/ssh/sshd_config 中追加 KexAlgorithms、Ciphers、MACs 的允许列表把弱算法禁掉配合 9.5 版本默认启用的新算法会很稳妥。还有一个小建议把 sshd_config 的日志级别调成 VERBOSE或者确保 LogLevel 不低于 INFO这样出现异常登录行为时/var/log/auth.log 里能看到更详细的指纹、来源 IP 和认证方式信息。升级到这个版本后日志里对公钥算法和密钥校验的打印也完整很多对日常巡检非常友好。完整跑完这套升级再到新终端验证登录成功的那一刻心里的石头才算落下。我在实际使用中的体会是OpenSSH 源码升级这件事最大的风险从来不是编译过程而是升级后对系统认证体系的影响。只要把 PAM、systemd、权限分离目录这三个点照顾到位再把备份和回滚做成默认动作这套流程完全可以复制到几十台机器上批量执行。最后再分享一个小技巧升级完成后把 backup_openssh_* 目录里的 upgrade.log 收集起来下一次做安全审计时直接对照日志就能说明升级时间和版本来源比口头解释可靠得多。本文还有配套的精品资源点击获取