OpenSSH升级最核心限制是无法保证当前远程会话不中断,因新旧sshd进程无法共享TCP连接状态;必须提前部署telnet或带外管理作为备用通道,并严格备份旧版二进制与配置。

不能保证不丢失当前远程连接会话——这是 OpenSSH 升级最核心的限制。任何直接替换 sshd 二进制、重启 sshd 服务、或修改 /etc/ssh/sshd_config 后 reload 的操作,都可能在毫秒级内切断你正在使用的 SSH 连接。这不是配置问题,而是协议和进程模型决定的:新旧 sshd 进程无法共享已建立的 TCP 连接状态。
为什么 reload 或 restart 会断连
很多人以为 systemctl reload sshd 是“热重载”,其实它只是向主 sshd 进程发 SIGHUP,让其重新读取配置并 fork 新子进程处理后续连接;但已有连接仍由旧 worker 进程维持。问题在于:如果你升级的是 sshd 本身(比如替换了 /usr/sbin/sshd),那 reload 实际触发的是新二进制加载,而旧进程仍在运行——此时系统处于混合状态,极易因 ABI 不兼容、PAM 模块错位或 SELinux 上下文缺失导致新连接失败,甚至旧连接被意外终止。
常见错误现象包括:
-
Connection reset by peer(客户端突然断开) -
Write failed: Broken pipe(执行命令中途掉线) - reload 后新连接报
Permission denied (publickey),但旧连接还能用
真正能保活当前会话的升级路径只有两条
必须提前部署一条独立于 SSH 的备用通道,否则一切“在线升级”都是赌运气。
-
启用 telnet(仅限内网/测试环境):安装
telnet-server,配置/etc/xinetd.d/telnet并启动xinetd。注意 telnet 无加密,切勿在公网开启。 -
确认带外管理可用:如 iDRAC、iLO、IPMI、云平台 VNC 控制台。登录后验证能否执行
systemctl status sshd和手动启停服务。
这两条路不是“可选”,是硬性前提。没做就动手,等于把服务器锁进黑盒。
升级时必须保留旧版 sshd 二进制和配置备份
即使走 RPM 安装或源码编译,也绝不能直接覆盖 /usr/sbin/sshd。正确做法是:
- 升级前执行:
cp -a /usr/sbin/sshd /usr/sbin/sshd.bak.$(date +%s) - 备份完整配置目录:
cp -rp /etc/ssh /etc/ssh.bak.$(date +%F) - RPM 升级用
--replacepkgs而非--force,避免误删配置文件 - 源码编译时指定
--prefix=/opt/openssh-10.2p1,不触碰/usr下原有文件
关键点:备份的 sshd.bak.* 必须能立即执行并监听非 22 端口(例如 /usr/sbin/sshd.bak.1727869620 -p 2222),这是断连后最快恢复的手段。
升级后验证不能只看 ssh -V
ssh -V 查的是客户端版本,完全不能代表服务端。必须验证三件事:
- 新
sshd进程是否真在跑:ps aux | grep [s]shd看路径和参数 - 监听端口是否为预期:
ss -ltnp | grep :22确认绑定的是新二进制 - 新连接是否可用:
ssh -o ConnectTimeout=5 -p 22 user@localhost(从本机测,绕过网络层干扰)
最容易被忽略的是 PAM 配置迁移——新版 OpenSSH 可能要求 /etc/pam.d/sshd 中新增模块(如 pam_systemd.so),漏掉会导致所有密码登录失败,但密钥登录仍正常,这种半失效状态极难排查。











