news 2026/8/5 13:31:45

预置known_hosts如何防止中间人攻击(MITM)?(服务器公钥、服务器私钥)Runner、DNS污染、BGP劫持、同网络ARP欺骗、SSH握手

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
预置known_hosts如何防止中间人攻击(MITM)?(服务器公钥、服务器私钥)Runner、DNS污染、BGP劫持、同网络ARP欺骗、SSH握手
  • 为什么这条最容易被忽略、却最重要(指将服务器主机公钥配置到github上):每次 CD 都是一台全新的 runner,(Github)~/.ssh/known_hosts 是空的。如果不预置主机公钥,就只能用「首次连接即信任」——而每次部署都是一次「首次连接」,等于每次都开一个中间人窗口。有人劫持了到那个 IP 的连接,你的 runner 会毫无察觉地把私钥用于认证。预置之后,工作流里的 StrictHostKeyChecking=yes 才有意义:主机公钥对不上就直接断开。

预置known_hosts如何防止中间人攻击(MITM)?

文章目录

    • 不是"伪造 IP"那么简单,是中间人攻击(MITM)
      • 你的 Runner 连接服务器的过程
      • 攻击者在哪里动手脚?
      • 攻击成功后会发生什么?
      • 最坏的情况是什么?
      • 预置 known_hosts 后怎么防住的?
      • 总结
    • 在预置known_hosts过程中,服务器私钥也要参与
      • 为什么必须用到服务器私钥?
      • SSH 握手时的真实过程(公钥与私钥的配合)
      • 理清容易混淆的"两对密钥"
        • 第一对:服务器主机密钥(Host Key)—— 证明服务器身份
        • 第二对:用户登录密钥(User Key)—— 证明 Runner 身份
      • 总结

不是"伪造 IP"那么简单,是中间人攻击(MITM)

让我用一个具体场景解释:


你的 Runner 连接服务器的过程

GitHub Runner (美国某个数据中心) │ │ ssh deploy@your-server.com │ │ 第一步:DNS 解析 your-server.com → 1.2.3.4 │ 第二步:TCP 连接 1.2.3.4:22 │ 第三步:SSH 握手,服务器返回主机公钥 │ 第四步:Runner 用私钥认证 │ 第五步:执行部署命令 │ ▼ 你的服务器 (1.2.3.4)

攻击者在哪里动手脚?

攻击者不需要入侵你的服务器,只需要在网络路径上做手脚:

场景一:DNS 污染

Runner 做 DNS 解析时,攻击者返回一个假 IP:

Runner 查询:your-server.com 的 IP 是多少? 攻击者回答:是 6.6.6.6(攻击者的服务器)

场景二:BGP 劫持

攻击者在互联网路由层面宣告"我能到达 1.2.3.0/24 这个网段",把流量引到自己那里。这是真实发生过的攻击,Cloudflare、AWS 都遭遇过。

场景三:同网络 ARP 欺骗

GitHub 的 Runner 跑在共享数据中心,如果同网络有恶意机器,可以声称自己是网关,截获 Runner 的出站流量。


攻击成功后会发生什么?

Runner 攻击者 (6.6.6.6) 你的服务器 │ │ │ │── SSH 连接 ─────────────────────▶│ │ │ │ │ │◀─ 返回攻击者的主机公钥 ──────────│ │ │ │ │ │ (StrictHostKeyChecking=no) │ │ │ "管他呢,接受!" │ │ │ │ │ │── 用私钥签名认证 ───────────────▶│ ← 攻击者看到你用哪个密钥、 │ │ 哪个用户名、部署什么代码 │ │ │ │◀─ 攻击者假装是你的服务器 ────────│ │ │ "部署成功!" │ │ │ │ │ │ Runner 以为部署成功了 │ 实际上代码根本没到你的服务器 │ 开心地结束了 │

最坏的情况是什么?

攻击者不只是"看",他可以:

攻击者能做的后果
看到部署的代码泄露你的源码
看到你用的 SSH 密钥名和用户名为进一步攻击收集信息
返回假的"部署成功"你以为上线了,其实服务器没更新
执行恶意操作后假装成功比如在你的服务器上留后门,然后告诉你"部署正常"

注意:SSH 协议本身不会直接泄露你的私钥(私钥只在本地签名,不会传输)。但攻击者能看到所有其他信息,而且如果你的服务器配置了密码认证,密码会被捕获。


预置 known_hosts 后怎么防住的?

Runner 攻击者 (6.6.6.6) │ │ │── SSH 连接 ─────────────────────▶│ │ │ │◀─ 返回攻击者的主机公钥 ──────────│ │ │ │ (StrictHostKeyChecking=yes) │ │ 对比 known_hosts: │ │ 期望: AAAAC3NzaC1lZDI1... │ │ 实际: BBBBD4NzbC1lZDI1... │ │ │ │ "公钥不匹配!断开连接!" ❌ │ │ │ │ 部署失败,你收到告警 │ │ 攻击者什么也得不到 │

注意:因为服务器公钥是公开的,即使攻击者拿到了服务器真实公钥,与Github known_hosts中的服务器公钥对比后一致,后续也会验证服务器私钥,若私钥不匹配,仍会断开连接


总结

没有预置 known_hosts: Runner 对任何自称是你服务器的机器都信任 = 在公共网络上裸奔 预置 known_hosts + StrictHostKeyChecking=yes: Runner 只信任持有特定公钥的机器 = 即使网络被劫持,也能立刻发现并断开

这不是理论风险。2024 年就有安全研究员演示过通过 DNS 劫持拦截 CI/CD 管道的 SSH 连接。只是大多数人没被攻击过,就觉得"不会发生在我身上"。

在预置known_hosts过程中,服务器私钥也要参与

在这个过程中,服务器的私钥也用到了,而且起着决定性的作用。只是它永远留在服务器本地,不会传输到网络上,所以你在 Runner 端感知不到它。

如果只用公钥,这个安全机制就形同虚设了。下面解释为什么必须用到服务器私钥。


为什么必须用到服务器私钥?

公钥是公开的,谁都能复制。

假设验证过程只用公钥(比对字符串):

Runner 的 known_hosts 里存着:你的服务器公钥 A 攻击者做的事: 1. 连上你的服务器,把公钥 A 抄下来 2. 放在自己的钓鱼服务器上 3. Runner 连过来时,攻击者把公钥 A 发给 Runner 4. Runner 比对:哇,一模一样!信任!

如果这样,攻击者轻易就能冒充你的服务器。

所以必须用私钥来"自证清白"。


SSH 握手时的真实过程(公钥与私钥的配合)

在 SSH 握手阶段,服务器不仅要把公钥发给 Runner,还要证明自己是这个公钥的真正主人

你的服务器 GitHub Runner │ │ │── 1. 发送:这是我的服务器公钥 ───────────▶ │ │ │ │── 2. 发送:这是我用「服务器私钥」 │ │ 对刚才的握手数据做的签名 ──────────▶ │ │ │ │ 3. 验证: │ 用 known_hosts 里的「服务器公钥」 │ 去解密/验证这个签名。 │ │ │ ├── 验证通过 ✅ │ │ 说明对方确实持有对应的私钥 │ │ 身份确认! │ │ │ └── 验证失败 ❌ │ 说明对方只有公钥,没有私钥 │ 是冒牌货!断开连接!

结论:

  • 服务器私钥:在服务器端用于签名,证明"我是我"。
  • 服务器公钥:在 Runner 端(known_hosts)用于验证签名,确认"你是你"。

理清容易混淆的"两对密钥"

在这个 CI/CD 部署场景中,其实有两对密钥在同时工作,很多人会把它们搞混:

第一对:服务器主机密钥(Host Key)—— 证明服务器身份
  • 作用:防止中间人攻击(就是你问的这个)。
  • 服务器私钥:存在服务器的/etc/ssh/ssh_host_ed25519_key,用于签名。
  • 服务器公钥:存在 Runner 的~/.ssh/known_hosts,用于验证。
第二对:用户登录密钥(User Key)—— 证明 Runner 身份
  • 作用:让服务器知道"这个 Runner 有权限登录并部署"。
  • Runner 私钥(部署私钥):存在 GitHub Secrets,Runner 用它签名,证明自己有权限登录。
  • Runner 公钥(部署公钥):存在服务器的~/.ssh/authorized_keys,服务器用它验证 Runner 的身份。

总结

密钥存放位置作用是否离开本机
服务器私钥你的服务器/etc/ssh/签名握手数据,证明服务器身份❌ 绝不离开服务器
服务器公钥Runnerknown_hosts验证服务器签名✅ 提前配置到 GitHub Secrets
部署私钥GitHub Secrets签名登录请求,证明 Runner 权限❌ 绝不离开 Runner
部署公钥你的服务器authorized_keys验证 Runner 登录权限✅ 手动添加到服务器

所以,服务器的私钥不仅用到了,而且是整个"防伪造"机制的核心。没有它参与签名,公钥比对就只是一场毫无安全意义的字符串匹配游戏。

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

Windows环境下Fscan内网扫描工具实战指南:从安装配置到高级应用

1. 从一次应急响应说起:为什么我们需要Fscan去年处理一个内部安全事件,客户反馈说内网有几台服务器响应异常,怀疑有横向移动的迹象。当时手上没有现成的内网扫描工具,临时用Python写脚本去探测端口和服务,效率低不说&a…

作者头像 李华
网站建设 2026/8/5 13:25:49

基于STM32单片机车位停车管理收费语音导航无线APP设计套件1881111(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

基于STM32单片机车位停车管理收费语音导航无线APP设计套件1881111(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ STM32停车管理车位收费语音导航APP设计188-3 产品功能描述: 本系统由STM32F103C8T6单片机核心板、1.44寸TFT彩屏、&…

作者头像 李华
网站建设 2026/8/5 13:23:43

如何快速下载加密m3u8视频流:终极完整指南

如何快速下载加密m3u8视频流:终极完整指南 【免费下载链接】m3u8_downloader m3u8(HLS流)下载,实现了AES解密、合并、多线程、批量下载 项目地址: https://gitcode.com/gh_mirrors/m3/m3u8_downloader 想要保存在线课程视频…

作者头像 李华
网站建设 2026/8/5 13:22:37

深度解析:如何通过CAN总线构建智能汽车数字神经系统

深度解析:如何通过CAN总线构建智能汽车数字神经系统 【免费下载链接】model3dbc DBC file for Tesla Model 3 CAN messages 项目地址: https://gitcode.com/gh_mirrors/mo/model3dbc 你是否曾想过,一辆特斯拉Model 3如何在毫秒间协调数百个电子控…

作者头像 李华
网站建设 2026/8/5 13:21:18

Input Leap:免费开源跨设备控制终极指南,一套键鼠掌控多台电脑

Input Leap:免费开源跨设备控制终极指南,一套键鼠掌控多台电脑 【免费下载链接】input-leap Open-source KVM software 项目地址: https://gitcode.com/gh_mirrors/in/input-leap 你是否厌倦了在多台电脑之间来回切换键盘和鼠标?是否在…

作者头像 李华
网站建设 2026/8/5 13:20:48

Linux bzmore 命令详解|bz2 压缩文件分页查看实用指南

1. 命令简介bzmore 是一个用于查看 bzip2 压缩过的文本文件内容的命令行工具。它能够自动解压 .bz2 格式的压缩文件,并将文本内容以分页方式显示在终端中。当文件内容超过一屏时,bzmore 会暂停输出,允许用户逐屏或逐行浏览,非常适…

作者头像 李华