Hotdry.

Article

SSH 首次连接的中间人攻击防护:StrictHostKeyChecking 与 VerifyHostKeyDNS 工程化配置

面向 DevOps 与安全工程师,系统性阐述 SSH 首次连接场景下中间人攻击的防护机制,重点覆盖 StrictHostKeyChecking 严格模式与 VerifyHostKeyDNS 的工程化配置参数、近期安全漏洞影响及可操作的最佳实践。

2026-05-10security

首次通过 SSH 连接一台陌生服务器时,客户端屏幕上会弹出一段熟悉至极的提示:Warning: Permanently added 'server' (RSA) to the list of known hosts. 正是这个 "自动添加" 的默认行为,为中间人攻击(Man-in-the-Middle,MITM)打开了一扇隐蔽的窗口。用户习惯性地输入 "yes",攻击者即可在这台新服务器真正上线之前,悄然接管连接。安全研究员 Joachim Schipper 多年前就已系统阐述过这一问题的本质,而 2025 年 2 月披露的 OpenSSH VerifyHostKeyDNS 绕过漏洞(CVE 相关)则进一步暴露了 DNS 验证路径的深层缺陷。本文从工程实用角度,给出覆盖 StrictHostKeyChecking 与 VerifyHostKeyDNS 的完整配置方案与监控策略。

问题本质:首次连接为何危险

SSH 协议的认证依赖主机密钥(host key)机制。服务器持有私钥,客户端在首次连接时获取公钥指纹并存储在 ~/.ssh/known_hosts(或全局的 /etc/ssh/ssh_known_hosts)中,后续连接时验证服务器是否持有对应私钥。这一机制在老练用户与已知服务器之间运作良好,但面对全新服务器时,默认行为是静默接受并永久记录 —— 这正是 MITM 攻击的入口。

攻击模型并不复杂:攻击者位于客户端与服务器之间的网络路径上(例如同局域网劫持、不安全公共 Wi-Fi、或 BGP 劫持),向客户端返回一个伪造的主机密钥并代为与真实服务器建立连接。由于 SSH 客户端在默认配置下会无条件信任首次见到的任何主机密钥,整个握手过程对用户完全透明,用户输入的密码或公钥将被攻击者截获。这种攻击在自动化脚本与 CI/CD 环境中尤为普遍,因为自动化流程通常无法交互式确认主机密钥,唯一的选择往往是设置 StrictHostKeyChecking=no,本质上将安全验证彻底关闭。

理解这一攻击面的第一步,是认识到 "首次连接" 并非一个可以轻率处理的安全边界 —— 它是一个需要在工程流程中显式处理的信任建立事件。

StrictHostKeyChecking 三档配置详解

OpenSSH 客户端的 StrictHostKeyChecking 选项控制主机密钥验证的行为,共有三个语义明确的取值,适用于全局配置(/etc/ssh/ssh_config)或用户级配置(~/.ssh/config)。

yes(默认值与推荐值):客户端仅允许连接 known_hosts 中已有记录且密钥匹配的主机。首次连接或主机密钥发生变化时,连接被直接拒绝,不存在任何提示或交互。这是最安全的设置,但需要用户在首次连接前手动获取并导入目标主机的主机密钥。它适合所有面向公网的生产服务器,尤其是不允许交互式确认的生产环境。

no(危险值,应避免):客户端接受任何主机密钥,不进行任何验证。这一设置使得 MITM 攻击完全畅通无阻,因为攻击者可以伪造任意密钥而客户端毫无察觉。绝大多数安全规范明令禁止在生产环境使用此值。它仅适用于临时调试场景(例如完全隔离的测试网络),且使用后必须立即还原。

accept-new(折中方案):客户端自动接受新的主机密钥并将其记录到 known_hosts,但若已有记录但密钥发生变化(即疑似 MITM 攻击或服务器重建),则拒绝连接。这比 yes 更宽松,但比 no 安全得多。它的语义是 "信任新的服务器,警惕变化的服务器",适合需要频繁接入新服务器但仍希望保留异常检测能力的场景。SSH 8.2+ 引入了 StrictHostKeyChecking accept-new 作为 StrictHostKeyChecking yes 的一种过渡策略。

对于团队基础设施,推荐的全局配置策略是:以 StrictHostKeyChecking yes 为基准,配合细粒度的例外规则处理特定可信主机。

# ~/.ssh/config 示例
# 全局默认:严格验证
Host *
    StrictHostKeyChecking yes

# 已知可信的内网服务器组(首次上线前已手动获取密钥)
Host 10.0.0.* 192.168.1.*
    StrictHostKeyChecking yes
    UserKnownHostsFile ~/.ssh/known_hosts_infra

# 临时实验室服务器——允许自动添加新密钥,但拒绝密钥变更
Host *.lab.internal
    StrictHostKeyChecking accept-new
    UserKnownHostsFile ~/.ssh/known_hosts_lab

上述配置中的 UserKnownHostsFile 将不同信任域的密钥分离管理,避免内网密钥与公网密钥混淆,这一实践在多环境管理中非常重要。

主机密钥的可靠获取策略

启用 StrictHostKeyChecking yes 后,首次连接到一台新服务器需要预先获取其主机密钥。获取方式有三种,各有其适用场景。

第一种方式是使用 ssh-keyscan。这是 OpenSSH 自带的工具,可以从目标服务器批量提取主机公钥指纹:

# 获取单台服务器的主机密钥
ssh-keyscan -t ed25519,rsa,ecdsa server.example.com >> ~/.ssh/known_hosts

# 批量获取内网服务器组(适用于基础设施即代码场景)
for host in $(cat infrastructure_hosts.txt); do
    ssh-keyscan -t ed25519,rsa "$host" >> ~/.ssh/known_hosts_infra
done

ssh-keyscan 的优势在于可脚本化,适合在配置管理工具(如 Ansible、Terraform)中自动执行。但需要注意的是,ssh-keyscan 本身默认不进行服务器身份验证 —— 它仅在首次部署阶段从可信网络(而非公网)执行,此时 MITM 攻击风险较低。对于高安全要求场景,建议在带外(out-of-band)网络中执行该命令。

第二种方式是让服务器管理员通过可信渠道发布 SSHFP 记录(见下节),客户端启用 VerifyHostKeyDNS 后可自动验证。

第三种方式是要求服务器管理员通过安全渠道(如企业内部即时通讯、经 PGP 签名的邮件、或带外电话确认)提供密钥指纹,管理员可以通过 ssh-keyscan -t ed25519 server 获取十六进制指纹后手动核对。

VerifyHostKeyDNS:DNSSEC 验证路径与深层陷阱

VerifyHostKeyDNS(配置文件中的同义词是 VerifyHostKeyDNS yes)允许 SSH 客户端通过 DNS 的 SSHFP 资源记录获取服务器的主机密钥指纹,并结合 DNSSEC 验证 DNS 响应的真实性来完成主机密钥验证。它的设计意图是简化首次连接场景 —— 用户无需手动获取服务器密钥,DNS 基础设施本身就可以提供可信赖的密钥来源。

从协议栈角度看,启用该选项后,SSH 客户端在握手阶段会查询目标域名的 SSHFP 记录,该记录包含服务器主机公钥的 SHA-256 或 SHA-1 指纹,DNS 响应由 DNSSEC 签名,客户端通过验证 DNSSEC 签名链确认 DNS 数据未被篡改。如果验证成功,客户端将 DNS 中的指纹与服务器提供的密钥比对,完全一致则建立连接;若验证失败(签名不匹配或 SSHFP 记录缺失),连接将被拒绝。

然而,这一机制在 2025 年 2 月披露了严重安全漏洞(CVE-2025-OpenSSH-VerifyHostKeyDNS 相关逻辑缺陷),攻击者可利用 DNS 验证路径中的逻辑漏洞绕过 SSHFP 指纹检查,实施服务器冒充攻击。OpenSSH 官方在 2025 年初的更新中修复了该绕过逻辑,但该事件揭示了一个更深层的问题:VerifyHostKeyDNS 的安全性高度依赖 DNSSEC 部署的完整性 —— 一旦 DNSSEC 签名验证过程中存在间隙(如部分委托链验证失败时的降级行为),整个验证假设即告破裂。

因此,当前的工程实践建议是:默认关闭 VerifyHostKeyDNS,仅在 DNSSEC 部署成熟且经过严格审计的环境中将其作为辅助验证手段,绝不将其作为唯一的主机密钥验证路径。即使启用了该选项,仍应配合 known_hosts 文件进行交叉验证,任何来自 DNS 和 known_hosts 的指纹不一致都应触发告警并阻断连接。

一个更安全的混合模式配置示例:

# ~/.ssh/config
Host *
    # 关闭 DNS 验证(防止 DNS 路径绕过)
    VerifyHostKeyDNS no
    # 启用变更检测(检测 MITM 或服务器重建)
    StrictHostKeyChecking accept-new
    # 使用独立的已知主机文件管理内网基础设施
    UserKnownHostsFile ~/.ssh/known_hosts_infra

可操作参数速查清单

以下是一组可直接落地的配置参数,针对常见场景进行了优化:

生产环境安全配置(推荐默认集)

# /etc/ssh/ssh_config 或 ~/.ssh/config
Host *
    # 核心防护:接受新密钥但拒绝变更
    StrictHostKeyChecking accept-new
    # 关闭 DNS 验证路径(防止近期绕过漏洞利用)
    VerifyHostKeyDNS no
    # 分离已知主机文件(按环境)
    UserKnownHostsFile ~/.ssh/known_hosts_prod
    # 记录密钥变更事件用于审计
    LogLevel VERBOSE

CI/CD 自动化环境配置

# CI runner 的 ssh_config(适合无交互环境)
Host *
    StrictHostKeyChecking yes
    # 自动化场景建议在构建阶段通过 ssh-keyscan 预填充 known_hosts
    UserKnownHostsFile /etc/ssh/ssh_known_hosts_ci
    # 超时控制防止挂起构建
    ConnectTimeout 10
    # 禁用密码认证(强制公钥)
    PreferredAuthentications publickey
    PasswordAuthentication no

混合云环境配置(内网 DNSSEC 受控,公网禁用)

# 内网:启用 DNS 验证
Host 10.* 192.168.* *.internal
    VerifyHostKeyDNS yes
    StrictHostKeyChecking yes

# 公网:严格模式
Host *
    StrictHostKeyChecking yes
    VerifyHostKeyDNS no

关键监控与告警指标

监控以下指标可以帮助团队在攻击发生前发现异常:

可信网络外的首次连接尝试次数。若该数量异常升高,可能表明 MITM 攻击正在进行,因为攻击者需要首先诱导客户端连接到伪造节点。

主机密钥变更事件。当 known_hosts 中已有记录的密钥发生变化时,accept-new 模式会拒绝连接。若此类事件突然增加,应立即启动安全事件响应流程。

DNSSEC 验证失败率。启用 VerifyHostKeyDNS 的客户端应监控 DNS 查询中的 DNSSEC 验证状态,若验证失败率高于基线,可能表明 DNS 基础设施遭到干扰。

回滚策略与应急响应

当检测到或怀疑 MITM 攻击发生时,以下步骤应在安全事件响应计划中明确定义:

第一步,立即切断可疑连接。不再使用当前 SSH 配置连接到目标服务器,撤销所有活跃会话。

第二步,通过可信带外渠道(如企业 VPN、电话确认、或管理控制台)重新获取目标服务器的真实主机密钥指纹,与 known_hosts 中的记录进行比对。

第三步,确认服务器确实重建(而非攻击)后,使用 ssh-keygen -R hostname 清除 known_hosts 中的旧记录,然后通过可信网络重新添加新密钥。

第四步,若攻击被确认,评估泄露范围 —— 包括是否使用了密码认证(密码是否已泄露)、公钥认证(私钥是否可能在攻击期间被使用),并按相应安全事件规程处理。

对于 accept-new 模式下突然拒绝大量服务器连接的情况,建议使用以下脚本来批量审计密钥变更原因:

#!/bin/bash
# 检测 known_hosts 中哪些主机的密钥发生了变化
ssh-keygen -l -f ~/.ssh/known_hosts_infra | while read line; do
    fingerprint=$(echo "$line" | awk '{print $2}')
    hostname=$(echo "$line" | awk '{print $3}')
    echo "Verifying: $hostname ($fingerprint)"
    # 对比当前服务器密钥
    ssh-keyscan -t ed25519 "$hostname" 2>/dev/null | ssh-keygen -lf /dev/stdin
done

资料来源

  • SSH StrictHostKeyChecking 配置行为与安全默认值(Server Hoya 技术指南,serverhoya.com)
  • OpenSSH VerifyHostKeyDNS 绕过漏洞披露(oss-security 邮件列表,openwall.com,2025 年 2 月)
  • DNSSEC 与 SSHFP 验证实践分析(Tore Anderson 技术博客,toreanderson.github.io)

security

内容声明:本文无广告投放、无付费植入。

如有事实性问题,欢迎发送勘误至 i@hotdrydog.com