news 2026/9/12 6:52:48

SerenityOS SSH Server 每次重启后客户端提示主机密钥变化,如何用静态主机密钥修复

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SerenityOS SSH Server 每次重启后客户端提示主机密钥变化,如何用静态主机密钥修复

SerenityOS SSH Server 每次重启后客户端提示主机密钥变化,如何用静态主机密钥修复

【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity

如果你通过 SSH 连接 SerenityOS 的 SSH 服务器,会发现一个反复出现的问题:每次重启系统(或重新构建磁盘镜像)后,SSH 客户端都会报告服务器主机身份发生了变化(如WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED),必须再次清除本地known_hosts里的旧记录才能连接。原因是 SerenityOS 自带的 SSHServer 目前只支持生成 ephemeral(临时)主机密钥:每次启动时现场生成一对新的 ED25519 密钥作为服务器身份,客户端检测到身份变化后会将其视为中间人攻击的迹象并中止连接。

修复方法来自官方文档 Documentation/SSHServer.md:手动生成一对 ED25519 密钥对作为固定主机密钥,通过sync-local.sh构建脚本把它写进磁盘镜像的/etc/ssh/目录。重启后服务器加载的始终是同一对密钥,客户端就不会再提示身份变化。

为什么每次重启主机密钥都会变

服务端实现可以印证这一行为。ServerConfiguration.cpp 中ensure_ssh_ed25519_keys()的逻辑是:

  • 优先从/etc/ssh/host_ed25519(私钥)和/etc/ssh/host_ed25519.pub(公钥)加载静态主机密钥;
  • 两个文件都不存在时,回退到Crypto::Curves::Ed25519::generate_private_key()现场生成一对临时密钥——这就是每次重启密钥都变化的根源;
  • 如果文件存在但加载失败(例如公私钥不匹配),服务器会打印Unable to use the host key from /etc/ssh/:加具体错误,同样回退到临时密钥。其中公私钥不匹配对应 源码 中的Corrupted host key错误,服务器启动时会在控制台输出对应的dbgln信息,可作为排查依据。

因此只要把正确的密钥对放进镜像的/etc/ssh/,问题就能根治。

准备条件

  • 已按 BuildInstructions.md 完成 SerenityOS 构建,并习惯用Meta/serenity.sh run等方式运行/重建磁盘镜像;
  • 宿主机上有ssh-keygen(用于生成密钥对);
  • 项目根目录下可以创建sync-local.sh。AdvancedBuildInstructions.md 说明该脚本的用途:构建时向磁盘镜像的文件系统中添加、修改或删除文件,且变更可以在镜像重建后持久生效。Meta/build-root-filesystem.sh 在每次构建根文件系统时执行它:
# Run local sync script, if it exists if [ -f "${SERENITY_SOURCE_DIR}/sync-local.sh" ]; then sh "${SERENITY_SOURCE_DIR}/sync-local.sh" fi

sync-local.sh在构建环境中以mnt目录为磁盘镜像根目录执行,脚本内的mnt/...路径对应 SerenityOS 内的/...路径,无需替换其他变量。

第一步:在宿主机生成 ED25519 主机密钥对

Documentation/SSHServer.md 明确只支持 ED25519 密钥,其他类型(RSA、ECDSA 等)不可用。主机密钥与客户端认证用的密钥对相互独立,文档建议不要放在~/.ssh下,而是单独存一个目录,例如:

ssh-keygen -t ed25519 -f path/to/serenity/ssh_keys/host_ed25519

命令中的path/to/serenity/ssh_keys/host_ed25519是文档给出的示例路径,你可以换成任何自己指定的位置,但后文sync-local.sh里的路径必须与这里一致。执行后会生成两个文件:host_ed25519(私钥)和host_ed25519.pub(公钥),两者都要放进镜像。

第二步:配置 sync-local.sh,把密钥对写入镜像

如果项目根目录还没有sync-local.sh,先创建它(参照 AdvancedBuildInstructions.md 的示例加上#!/bin/shset -e),然后把下面这段文档给出的命令追加进去。cp后面的*会同时拷走私钥和公钥两个文件;chown/chmod将文件属主设为 root、权限收敛为属主只读(u=r,g=,o=),因为镜像中 root 的 umask 相关配置由构建脚本统一管理,这一步按文档原样保留即可:

mkdir -p mnt/etc/ssh/ cp path/to/serenity/ssh_keys/host_ed25519* mnt/etc/ssh/ chown root:root mnt/etc/ssh/host_ed25519* chmod u=r,g=,o= mnt/etc/ssh/host_ed25519*

mkdir -p保证目录已存在时不会报错,所以这段内容在后续镜像重建时反复执行是安全的。

第三步:重建磁盘镜像

保存好sync-local.sh后,按你平时的方式重建镜像(例如Meta/serenity.sh run)。镜像构建过程中,各build-image-*.sh脚本都会调用 Meta/build-root-filesystem.sh,其中会在安装完基础系统后执行你的sync-local.sh,密钥对随之写入镜像的/etc/ssh/目录。

注意:该机制依赖每次重建都执行sync-local.sh。如果镜像是在没有该脚本的情况下构建的,/etc/ssh/host_ed25519不存在,服务器仍会回退到临时密钥,问题依旧。

验证:重启后客户端不再提示身份变化

  1. 重建镜像后启动系统,用与之前相同的方式建立 SSH 连接。
  2. 重启 SerenityOS,再次连接。预期现象:不再出现“远程主机身份已变化”的警告,无需再删除客户端known_hosts中的旧条目。这正是文档描述的目标状态——“If this identity changes between two connections, clients will detect it and abort”,而静态密钥让身份在多次连接之间保持不变。
  3. 如果警告依旧出现,检查服务器启动时的控制台输出:出现Unable to use the host key from /etc/ssh/: ...说明密钥文件缺失或不合法(例如Corrupted host key表示公钥与私钥不匹配),此时服务器已悄悄回退为临时密钥。对照确认两点:sync-local.sh中的路径是否指向真实存在的密钥文件;私钥与公钥是否出自同一次ssh-keygen

限制与边界

  • 主机密钥只支持 ED25519;ServerConfiguration在读取静态密钥后会对密钥类型做SSH_ED25519校验,公钥文件还要求恰好一行、且公钥必须能由私钥推导出来,否则按加载失败处理并回退临时密钥。
  • 客户端认证是另一个独立问题:该服务器只支持publickey认证,客户端公钥需要安装到用户主目录的.config/ssh/authorized_keys(例如通过sync-local.sh追加mnt/home/anon/.config/ssh/authorized_keys)。本文只处理主机密钥这一侧;如果连接在认证阶段失败,属于客户端授权密钥的问题,需按 Documentation/SSHServer.md 的 “Authentication” 一节另行配置。

【免费下载链接】serenityThe Serenity Operating System 🐞项目地址: https://gitcode.com/GitHub_Trending/se/serenity

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 6:51:41

数字化族谱管理系统:DAG建模与协同编辑技术解析

1. 族谱管理系统的时代需求与行业痛点在中国传统文化语境中,族谱承载着家族血脉传承的历史记忆。随着数字化浪潮席卷各行各业,传统纸质族谱正面临三大核心挑战:首先是信息更新滞后,纸质版本修订周期长、成本高;其次是查…

作者头像 李华
网站建设 2026/9/12 6:50:28

OpenStock实时价格追踪:3分钟跑在自己电脑上的免费行情工具

OpenStock实时价格追踪:3分钟跑在自己电脑上的免费行情工具 【免费下载链接】OpenStock OpenStock is an open-source alternative to expensive market platforms. Track real-time prices, set personalized alerts, and explore detailed company insights — bu…

作者头像 李华
网站建设 2026/9/12 6:50:07

CAN总线故障排查:90%难题卡在物理层,从电压到电阻的实战套路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 6:49:34

Linux wheel组与sudo权限完全指南:从原理到安全配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 6:47:12

Halcon20.11图像拼接练习文件自制:从特征匹配到zip打包

简介:面向使用Halcon20.11进行图像拼接的开发者与学习者,压缩包围绕特征点匹配与投影变换展开,完整覆盖了从算法原理到实验验证的闭环。包内集成了Forstner和Harris两种经典角点检测算法,并以膀胱癌细胞33图像拼接作为实战案例&am…

作者头像 李华
网站建设 2026/9/12 6:46:38

Java Integer缓存机制与自动装箱陷阱解析

1. 问题现象解析:当数字比较背叛直觉第一次在Java中执行Integer a 1000和Integer b 1000,然后比较a b时,很多开发者会惊讶地发现结果是false。而同样的操作换成100时,Integer c 100和Integer d 100比较c d却返回true。这看似…

作者头像 李华