Linux命令-ssh-keyscan(从主机收集公钥)

Linux命令-ssh-keyscan(从主机收集公钥)

ssh-keyscan 是一个批量收集 SSH 主机公钥的工具。与交互式的 ssh 首次连接确认不同,ssh-keyscan 非交互地从指定主机获取公钥,非常适合自动化脚本、主机清单管理和大规模部署前的 known_hosts 预填充。

快速参考

bash 复制代码
ssh-keyscan [选项] [主机...]

ssh-keyscan 从目标的 SSH 服务端口连接并获取公钥,输出可重定向到 ~/.ssh/known_hosts 文件,避免首次连接时的交互式确认提示。

基本用法

bash 复制代码
# 获取单台主机的公钥
ssh-keyscan server.example.com

# 获取并直接添加到 known_hosts
ssh-keyscan -H server.example.com >> ~/.ssh/known_hosts

# 指定非标准端口
ssh-keyscan -p 2222 server.example.com

# 获取多个主机的公钥
ssh-keyscan server1 server2 server3

# 从文件批量获取
ssh-keyscan -f hosts.txt

选项详解

选项 说明
-H 哈希主机名(推荐,增加安全性)
-p PORT 指定 SSH 端口
-T TIMEOUT 连接超时时间(秒)
-t TYPE 指定密钥类型(rsa/dsa/ecdsa/ed25519)
-f FILE 从文件读取主机列表
-4/-6 强制使用 IPv4/IPv6
-c 请求证书而非纯密钥
-v 详细输出
-D 打印调试信息

常见使用场景

bash 复制代码
# === 场景 1: 避免首次连接提示 ===
# 传统方式(交互式)
ssh new-server.example.com
# The authenticity of host 'new-server.example.com' can't be established.
# Are you sure you want to continue connecting (yes/no)?

# 使用 ssh-keyscan 预填充
ssh-keyscan -H new-server.example.com >> ~/.ssh/known_hosts
ssh new-server.example.com  # 无提示!

# === 场景 2: Ansible/自动化部署 ===
# 部署前批量添加所有主机公钥
ansible all --list-hosts | tail -n +2 | while read host; do
    ssh-keyscan -H "$host" >> ~/.ssh/known_hosts 2>/dev/null
done

# === 场景 3: 不同密钥类型收集 ===
# 仅收集 Ed25519 密钥
ssh-keyscan -t ed25519 host.example.com

# 收集多种类型
ssh-keyscan -t ecdsa,ed25519 host.example.com

# 收集全部可用类型
ssh-keyscan -t rsa,dsa,ecdsa,ed25519 host.example.com 2>/dev/null

批量操作

bash 复制代码
# 从 IP 范围批量收集
for ip in 192.168.1.{1..254}; do
    ssh-keyscan -T 2 "$ip" >> ~/.ssh/known_hosts 2>/dev/null &
done
wait

# 从主机清单文件批量操作
cat > hostlist.txt << 'EOF'
192.168.1.10
192.168.1.20
db.private.local
web.prod.internal
EOF

# 哈希存储(推荐)
ssh-keyscan -H -f hostlist.txt >> ~/.ssh/known_hosts

# 非哈希存储(调试时使用)
ssh-keyscan -f hostlist.txt > known_hosts_plain.txt

# 去重 known_hosts
sort -u ~/.ssh/known_hosts -o ~/.ssh/known_hosts

# 并行批量收集(超时 3 秒)
cat hostlist.txt | xargs -P 10 -I {} ssh-keyscan -T 3 -H {} >> ~/.ssh/known_hosts 2>keyscan_errors.log

# 验证收集结果
wc -l ~/.ssh/known_hosts

安全管理

bash 复制代码
# 清除特定主机的旧记录
ssh-keygen -R compromised-host.example.com

# 清除旧记录后重新扫描
ssh-keyscan -H new-server.example.com >> ~/.ssh/known_hosts

# 验证 known_hosts 中的记录
ssh-keygen -H -F server.example.com

# 审计 known_hosts 文件
echo "=== known_hosts 审计 ==="
echo "总记录数: $(wc -l < ~/.ssh/known_hosts)"
echo "MD5 哈希: $(md5sum ~/.ssh/known_hosts | cut -d' ' -f1)"

# 提取所有主机名(需要先取消哈希,安全注意!)
ssh-keygen -F "*" -f ~/.ssh/known_hosts 2>/dev/null

# 对比新旧主机密钥(检测 MITM 攻击)
ssh-keyscan server.example.com | while read line; do
    if grep -qF "$line" ~/.ssh/known_hosts; then
        echo "✅ 密钥匹配: server.example.com"
    else
        echo "❌ 密钥不匹配!可能存在中间人攻击"
    fi
done

高级用法

bash 复制代码
# 为特定子网生成 known_hosts 文件
NETWORK="10.0.0"
mkdir -p /tmp/ssh_scan
for octet in {1..50}; do
    ssh-keyscan -T 1 -H "${NETWORK}.${octet}" >> /tmp/ssh_scan/network_hosts 2>/dev/null &
done
wait
echo "收集完成,条目数: $(wc -l < /tmp/ssh_scan/network_hosts)"

# 按密钥类型分类输出
ssh-keyscan -t rsa -H host.example.com > rsa_keys.txt
ssh-keyscan -t ed25519 -H host.example.com > ed25519_keys.txt

# 导出为 SSHFP DNS 记录格式
ssh-keyscan host.example.com | ssh-keygen -r host.example.com

# 扫描域名对应的多个 IP(处理负载均衡)
HOST="cdn.example.com"
for ip in $(dig +short "$HOST"); do
    echo "# IP: $ip"
    ssh-keyscan -T 3 "$ip" 2>/dev/null
done

# 脚本化:检查密钥是否已存在于 known_hosts
check_known_host() {
    local host="$1"
    if ssh-keygen -F "$host" -f ~/.ssh/known_hosts > /dev/null 2>&1; then
        echo "✅ $host 已存在于 known_hosts"
        return 0
    else
        echo "⚠️ $host 未在 known_hosts 中,正在添加..."
        ssh-keyscan -H "$host" >> ~/.ssh/known_hosts 2>/dev/null
        return $?
    fi
}
check_known_host "new-server.local"

安全注意事项

安全警告:

  • ssh-keyscan 不验证主机身份------它只是收集公钥。收到的主机公钥在首次使用时都应通过带外方式(如电话、当面确认)进行验证
  • 始终使用 -H 选项哈希主机名,防止主机名信息泄露
  • 在生产环境中,应使用 SSH CA 证书签名代替手动 known_hosts 管理
  • 定期使用 ssh-keygen -R 清理不再需要的 known_hosts 记录
bash 复制代码
# SSH CA 模式(企业推荐方案,避免手动管理 known_hosts)
# 客户端配置 ~/.ssh/config
cat >> ~/.ssh/config << 'EOF'
Host *.company.com
    CertificateFile ~/.ssh/user_key-cert.pub
EOF

# 这样就不需要逐台收集主机密钥了

ssh-keyscan 是自动化 SSH 部署中的先遣工具。虽然它不验证主机身份,但在可信任的私有网络环境中,它极大地简化了首次 SSH 连接的工作流程。

相关推荐
lzx_0024 小时前
Linux 进程(二) 深入理解进程
linux
沫璃染墨5 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互
温暖小土5 小时前
在 CentOS 上安装 Redis Stack
linux·redis·centos
GeW7 小时前
国产化替代进入深水区之后Linux 与数据库为什么必须走向重建
linux
十碗饭吃不饱7 小时前
SSH 密钥认证详解:原理、实操、参数、排错与加固
运维·ssh
女神下凡10 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
12.=0.10 小时前
【持续更新】shell脚本 + Linux命令
linux·运维·服务器
Escalating_xu11 小时前
【Linux 网络编程】五种 I/O 模型与非阻塞 I/O:从“等数据”到正确处理 EAGAIN
java·linux·网络
无言听风雨丶11 小时前
Linux 容器本质探秘:Cgroup 与 Namespace 深度解析与实战
linux·运维·服务器·kubernetes
万联WANFLOW11 小时前
CVE-2026-98432 等漏洞自查:AI 查出的 Linux、Windows 漏洞,运维怎么确认受不受影响
linux·运维·windows·网络安全