SSH 突然 Connection reset?不是密钥坏了,是 OpenSSL 把 sshd 干趴了

0 阅读4分钟

OpenSSH 起不来:OpenSSL 3.5 和旧版 sshd 对不上

现象:阿里云 ECS 的 22 端口直接 Connection reset,工作台里 systemctl restart sshd 失败。根因不是 sshd_config,而是 OpenSSL 已经升到 3.5,sshd 还停在按 3.0 编译的包。

现象

从外面连服务器:

kex_exchange_identification: read: Connection reset
Connection reset by x.x.x.x port 22

SSH 握手还没开始就被掐掉,多半是 sshd 根本没在听,而不是密钥、安全组或 PermitRootLogin。

进不了 SSH,只能走阿里云控制台的 工作台 / VNC。在机器里执行:

systemctl restart sshd

得到:

Job for sshd.service failed because the control process exited with error code.
See "systemctl status sshd.service" and "journalctl -xeu sshd.service" for details.

定位

不要先改配置。先看服务日志和配置自检:

systemctl status sshd.service --no-pager -l
journalctl -u sshd.service -n 80 --no-pager
sshd -t

日志里反复出现同一句:

OpenSSL version mismatch. Built against 30000070, you have 30500080
sshd.service: Main process exited, code=exited, status=255/EXCEPTION
Failed to start OpenSSH server daemon.

版本号可以拆开看:

十六进制含义
30000070sshd 编译时 用的 OpenSSL 3.0.7
30500080机器上 正在加载 的 OpenSSL 3.5.8

OpenSSH 会在启动时核对 OPENSSL_VERSION_NUMBER。库比编译时的新太多,进程直接退出,systemd 再自动拉起,于是日志里会出现一串 restart counter is at 2/3/4...。

再确认包和动态库:

openssl version
rpm -q openssl openssl-libs openssh-server
which sshd
ldd $(command -v sshd) | grep -E 'ssl|crypto'

当时机器上是:

OpenSSL 3.5.9 29 Sep 2026
package openssl is not installed
openssl-libs-3.5.9-1.el9.x86_64
openssh-server-8.7p1-32.el9.x86_64
/usr/sbin/sshd
libcrypto.so.3 => /lib64/libcrypto.so.3

结论很清楚:

  • 系统 libcrypto.so.3 已经是 3.5.x
  • openssh-server 还是 8.7p1,按 3.0.7 编的
  • 独立的 openssl RPM 甚至已经不在了,只剩 openssl-libs

这不是配置写错,也不是端口被占。先不要改 /etc/ssh/sshd_config,更不要重启无关服务。

踩坑:把 OpenSSL 再降一格没用

第一反应是把 OpenSSL 降回 3.0.7:

dnf -y downgrade openssl-libs

dnf 只从 3.5.9 降到 3.5.8,因为仓库里的相邻版本就是 3.5.8。sshd -t 依旧报:

OpenSSL version mismatch. Built against 30000070, you have 30500080

再看仓库里到底有什么:

dnf list --showduplicates openssl-libs

baseos 里只有:

openssl-libs  3.5.7 / 3.5.8 / 3.5.9

没有 3.0.7。 发行版已经把 OpenSSL 切到 3.5 线,不能再靠降库去迁就旧 sshd。方向反了:应该让 OpenSSH 跟上 OpenSSL,而不是把 OpenSSL 拧回 3.0。

正确修复:升级 OpenSSH

dnf list --showduplicates openssh-server
dnf -y update openssh openssh-server openssh-clients
sshd -t
systemctl start sshd
systemctl is-active sshd

这次会把整组升到匹配 3.5 的构建,例如:

openssh-9.9p1-16.el9
openssh-clients-9.9p1-16.el9
openssh-server-9.9p1-16.el9

升级过程中可能看到:

warning: /etc/ssh/sshd_config created as /etc/ssh/sshd_config.rpmnew

这表示 正在生效的仍是原来的 sshd_config,新包默认配置另存为 .rpmnew。密钥登录、监听端口一般不用动。

自检通过的标志:

  • sshd -t 没有输出(静默即成功)
  • systemctl is-active sshd 为 active

然后从外面再连一次 22 端口,应能正常完成密钥交换。

为什么会这样

OpenSSH 和 OpenSSL 必须 同一套 ABI 一起走。常见触发方式:

  1. dnf update 只更新了 openssl-libs,openssh-server 还停在旧构建
  2. 第三方源 / 预发布源把 OpenSSL 推到 3.5,但 OpenSSH 仍是 8.7
  3. 有人只升级加密库,没把 openssh、openssh-server、openssh-clients 一起升

EL9 上官方 openssh 8.7 是按 OpenSSL 3.0 编的。发行版若已经提供 openssh 9.9 + openssl-libs 3.5,就要整组对齐,不能一半新一半旧。

以后可以怎么防

  1. SSH 挂了优先看 journalctl -u sshd 和 sshd -t,不要先改配置。
  2. 看到 OpenSSL version mismatch,先对一下:
    • sshd 编译目标(Built against)
    • 当前 openssl-libs
    • 仓库里 openssh-server 有没有对应新构建
  3. 仓库已经没有旧 OpenSSL 时,升 OpenSSH,不要死磕 dnf downgrade。
  4. 修 SSH 时不要顺手启动业务进程,避免排障过程中再引入一台抢端口、抢连接的服务。
  5. 升级后如果出现 sshd_config.rpmnew,先确认旧配置仍在用;不要无脑用新文件覆盖。

一句话

sshd 起不来不一定是配置问题。Built against 3.0.7, you have 3.5.8 时,如果仓库里已经没有 3.0,就把 OpenSSH 升到和当前 OpenSSL 同一代,而不是把 OpenSSL 再降一小步。


标签建议:运维、Linux、SSH、OpenSSL、阿里云