随机
Enter 搜索 ↑↓ 切换 Esc 清空

ssh-keyscan

命令

收集主机 SSH 公钥的工具

ssh-keyscan

收集主机 SSH 公钥的工具

补充说明

ssh-keyscan 是 OpenSSH 套件中的一个工具,用于批量收集远程主机的 SSH 公钥。它通过非交互方式连接 SSH 服务器并获取其主机密钥,常用于初始化 known_hosts 文件、搭建 SSH 信任网络或自动化部署场景。

相较于手动 ssh 连接后确认指纹,ssh-keyscan 可以批量、自动化地收集多台主机的公钥,无需逐个交互确认。

语法

ssh-keyscan [选项] [主机列表...]

选项

-4              强制使用 IPv4 地址
-6              强制使用 IPv6 地址
-f <文件>       从指定文件中读取主机列表(每行一个)
-H              对 known_hosts 中的主机名进行哈希处理
-p <端口>       指定连接远程主机的端口(默认 22-T <秒数>       指定连接尝试的超时时间(默认 5 秒)
-t <类型>       指定要获取的密钥类型(rsa/dsa/ecdsa/ed25519)
-v              调试模式,打印详细信息

密钥类型

# 支持的密钥类型
-t rsa             RSA 密钥
-t dsa             DSA 密钥(已不推荐)
-t ecdsa           ECDSA 密钥
-t ed25519         Ed25519 密钥

# 获取所有类型(默认行为,不加 -t)
ssh-keyscan hostname

# 指定多种类型
ssh-keyscan -t rsa,ed25519 hostname

基础用法

# 获取主机的所有公钥
ssh-keyscan example.com

# 获取指定类型的公钥(推荐)
ssh-keyscan -t ed25519 example.com

# 指定端口
ssh-keyscan -p 2222 example.com

# 指定超时时间
ssh-keyscan -T 10 example.com

# 调试模式
ssh-keyscan -v example.com

# 哈希主机名(保护隐私)
ssh-keyscan -H example.com

批量收集

# 从文件读取主机列表
cat hosts.txt
# 192.168.1.1
# 192.168.1.2
# server.example.com

ssh-keyscan -f hosts.txt

# 指定多个主机
ssh-keyscan host1 host2 host3

# 扫描子网(使用循环)
for ip in $(seq 1 20); do
    ssh-keyscan -t ed25519 192.168.1.$ip
done

# 扫描 IP 段并合并结果
ssh-keyscan -t ed25519 192.168.1.{1..20}

更新 known_hosts

# 将公钥追加到 known_hosts(追加模式)
ssh-keyscan -t ed25519 hostname >> ~/.ssh/known_hosts

# 哈希主机名后追加
ssh-keyscan -H -t ed25519 hostname >> ~/.ssh/known_hosts

# 覆盖写入(先备份再写入)
ssh-keyscan -t ed25519 hostname > ~/.ssh/known_hosts

# 追加到系统级 known_hosts
ssh-keyscan -t ed25519 hostname | sudo tee -a /etc/ssh/ssh_known_hosts

实际应用场景

1. 自动化部署 - 预先建立信任

# 在部署脚本中预先添加主机密钥
#!/bin/bash
HOSTS="server1 server2 server3"
for host in $HOSTS; do
    ssh-keyscan -H -t ed25519 $host >> ~/.ssh/known_hosts 2>/dev/null
done

# 这样后续 ssh/scp/rsync 等操作就不会弹出确认提示

2. 批量添加集群节点

# 集群初始化时批量添加所有节点
NODES=("node1.local" "node2.local" "node3.local" "node4.local")

for node in "${NODES[@]}"; do
    echo "收集 $node 的公钥..."
    ssh-keyscan -H -t ed25519 "$node" >> ~/.ssh/known_hosts 2>/dev/null
done

echo "所有节点公钥已添加"

3. 清理并重建 known_hosts

# 备份旧的 known_hosts
cp ~/.ssh/known_hosts ~/.ssh/known_hosts.bak

# 清空文件
> ~/.ssh/known_hosts

# 重新收集所有常用主机的公钥
ssh-keyscan -H -t ed25519 \
    github.com \
    gitlab.com \
    bitbucket.org \
    server1.example.com \
    server2.example.com >> ~/.ssh/known_hosts

# 验证
ssh-keygen -l -f ~/.ssh/known_hosts

4. 配合 Ansible 批量管理

# 在 Ansible 部署前置任务中使用
# playbook.yml 中的 pre_tasks:
# - name: 收集主机公钥
#   shell: |
#     ssh-keyscan -H -t ed25519 {{ inventory_hostname }} >> ~/.ssh/known_hosts
#   delegate_to: localhost
#   changed_when: false

与相关命令配合

# 检查 known_hosts 内容
ssh-keygen -l -f ~/.ssh/known_hosts

# 删除特定主机的旧密钥
ssh-keygen -R hostname

# 重新收集并添加
ssh-keyscan -H -t ed25519 hostname >> ~/.ssh/known_hosts

# 一键刷新:删除旧密钥 + 收集新密钥
ssh-keygen -R hostname && ssh-keyscan -H -t ed25519 hostname >> ~/.ssh/known_hosts

# 验证连接是否正常
ssh -o StrictHostKeyChecking=accept-new user@hostname "uptime"

注意事项

# 安全风险:ssh-keyscan 不验证密钥真实性
# 可能受到中间人攻击(MITM),建议配合以下方式使用:

# 1. 首次连接后手动验证指纹
ssh-keyscan hostname | ssh-keygen -l -f -

# 2. 对比已知指纹(从安全渠道获取)
# 服务器提供的指纹:SHA256:xxxxxx...
ssh-keyscan -t ed25519 hostname 2>/dev/null | ssh-keygen -l -f - | grep -q "SHA256:xxxxxx"

# 3. 仅用于内部信任网络
# 4. 结合 DNSSEC 使用(SSHFP 记录)

常见问题

# 连接超时
# 增加超时时间
ssh-keyscan -T 30 hostname

# 端口不通
# 确认服务器 SSH 端口并指定
ssh-keyscan -p 2222 hostname

# 获取不到特定类型的密钥
# 确认服务器支持该类型,不加 -t 获取所有类型
ssh-keyscan hostname

# 输出格式不对
# 正常输出格式:hostname algorithm base64key
# 若服务端返回异常,尝试调试模式查看
ssh-keyscan -v hostname 2>&1

输出格式

# 标准输出格式:
<hostname> <算法> <base64编码的公钥>

# 示例:
server.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDy...
server.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQ...

参数

主机列表:指定要收集公钥的主机名或 IP 地址列表。