SSH 密钥认证详解:原理、实操、参数、排错与加固

SSH 密钥认证详解:原理、实操、参数、排错

Windows OpenSSH 客户端 + Linux 服务端完整实操案例(Windows10 1809+/Win11 自带 OpenSSH,不依赖 Xshell/PuTTY)

前言

SSH 是 Linux、服务器、容器、跳板机最常用远程协议。很多开发者只会简单 ssh user@ip 和密钥复制,但是对 ssh-keygen 参数、~/.ssh/config、ssh-agent、签名机制、sshd 细粒度配置、排错参数 -v/-vv/-vvv、密钥轮换、证书、密钥隔离缺乏了解。

本文聚焦 OpenSSH 原生体系,所有命令可直接复制到生产环境,兼顾原理、工程实践和踩坑点。

核心铁律:密钥对由客户端生成,公钥部署到服务端,私钥本地保管;私钥永远不上传服务器,网络中永不传输私钥。

一、两种认证模式对比

认证方式 校验逻辑 安全短板 适用场景
PasswordAuthentication 密码认证 客户端发送密码,服务端比对 shadow 哈希 密码可被爆破、弱口令风险、公网暴露高危 本地虚拟机临时调试,公网生产禁止开启
PubkeyAuthentication 公钥密钥认证 挑战 + 签名机制,服务端用公钥验签 私钥泄露则账号失守,依赖本地私钥安全 跳板机、云服务器、CI/CD、自动化脚本、生产环境

补充:OpenSSH 还有 HostbasedAuthentication(基于主机认证,企业域环境,极少用)、Kerberos 认证,本文不展开。

二、非对称加密 & 密钥对基础

SSH 公钥认证使用签名,不是 "公钥加密消息",这点非常容易混淆:

  • 私钥:用于签名;
  • 公钥:用于验签;
  • 数学特性:签名可公开验签,但是无法从公钥反推私钥。

支持算法(OpenSSH 8.0+)

  1. ed25519:首选,椭圆曲线,密钥短、速度快、安全强度高,推荐所有新密钥
  2. rsa:兼容性最好,老旧设备兼容;至少 4096 bit,不建议 2048
  3. ecdsa:不推荐,有实现争议

命令指定算法:-t ed25519 / -t rsa

三、ssh-keygen 完整参数详解(重点)

基础生成:

复制代码
ssh-keygen -t ed25519 -C "work-laptop@zhangsan"

完整常用参数合集:

复制代码
# 生成 ed25519,指定备注、输出路径、强制覆盖、设置密钥密码
ssh-keygen -t ed25519 \
-C "dev-machine | dev@company.com" \
-f ~/.ssh/id_ed25519-work \
-N "MyPassphrase123" \
-q

参数说明:

  • -t:密钥类型 ed25519/rsa
  • -C:comment 备注,仅文本标记,不参与校验,方便区分多套密钥
  • -f:输出文件路径,不写则默认 ~/.ssh/id_xxx
  • -N:非交互设置私钥密码(passphrase),脚本自动化生成密钥使用;交互式直接回车留空 = 私钥无密码(风险高)
  • -q:静默模式,不输出交互提示
  • -b:密钥长度,仅 RSA 需要:-b 4096
  • -o:使用新 OpenSSH 私钥格式(默认新版已开启,老版本需要加)
  • -a:KDF 迭代次数,增加暴力破解私钥难度,-a 100

⚠️ 区分两个密码:

  1. 服务器账号密码 :密码登录用,存在 /etc/shadow
  2. 私钥 passphrase:加密本地私钥文件;私钥本身是加密文件,拿到私钥文件没有这个密码依然无法签名。这是保护私钥的最后一道防线。

私钥密码管理命令

复制代码
# 修改已有私钥的密码
ssh-keygen -p -f ~/.ssh/id_ed25519-work

# 查看密钥指纹(用于核对公钥,防止中间人)
ssh-keygen -lf ~/.ssh/id_ed25519-work.pub

# 导出公钥(有时候.pub丢了,可以从私钥恢复公钥)
ssh-keygen -y -f ~/.ssh/id_ed25519-work > ~/.ssh/id_ed25519-work.pub

四、Windows (OpenSSH 客户端) + Linux 服务器 完整实操案例

环境说明

  • 客户端:Windows 11 / Windows10 1809+,系统自带 OpenSSH 客户端,使用 PowerShell(推荐)或者 Windows Terminal

  • 服务端:CentOS7 / Rocky8 / Ubuntu(Linux),sshd 服务正常运行,IP:

    复制代码
    10.0.0.20

    登录用户:

    复制代码
    dev

    SSH 端口:

    复制代码
    22

    ⚠️ 先确认 Windows 已经安装 OpenSSH 客户端:

    设置 → 应用 → 可选功能 → 添加功能,搜索

    复制代码
    OpenSSH 客户端

    安装。

    验证(PowerShell):

    复制代码
    ssh -V

步骤 1:Windows 本地生成密钥对(PowerShell 执行)

Windows 下 ~ 对应目录:C:\Users\你的用户名\.ssh\

复制代码
# 生成 ed25519 密钥,备注 windows-dev-pc
ssh-keygen -t ed25519 -C "windows-dev-pc"

交互提示:

  1. Enter file in which to save the key (C:\Users\xxx\.ssh\id_ed25519): 回车默认
  2. Enter passphrase:推荐设置私钥密码(保护私钥,每次使用私钥需要输入;直接回车为空密码,方便自动化但是不安全)
  3. Enter same passphrase again:确认

生成文件:

复制代码
C:\Users\你的用户名\.ssh\id_ed25519      # 私钥(保密!)
C:\Users\你的用户名\.ssh\id_ed25519.pub  # 公钥,上传Linux

指定自定义路径、非交互(脚本场景)

复制代码
ssh-keygen -t ed25519 -C "windows-dev-pc" -f C:\Users\xxx\.ssh\id_ed25519-linux -N "Pass@1234" -q

步骤 2:把 Windows 公钥推送到 Linux 服务器

两种方案:优先方案 A(ssh-copy-id,新版 OpenSSH 支持)

方案 A:PowerShell 直接 ssh-copy-id(推荐)
复制代码
# 默认端口22
ssh-copy-id dev@10.0.0.20

# 如果服务器修改了端口,例如2222
ssh-copy-id -p 2222 dev@10.0.0.20

# 指定私钥文件推送对应公钥
ssh-copy-id -i C:\Users\xxx\.ssh\id_ed25519-linux.pub dev@10.0.0.20

执行时输入一次 Linux 服务器 dev 账号密码,命令自动追加公钥、自动修复 Linux 端.ssh目录与 authorized_keys 权限。

方案 B:手动复制公钥(ssh-copy-id 不可用时,老旧 OpenSSH 版本)
  1. PowerShell 查看公钥内容,完整复制

    cat C:\Users\xxx.ssh\id_ed25519.pub

  2. 先用密码登录 Linux 服务器

    ssh dev@10.0.0.20

  3. Linux 内执行,写入公钥

    mkdir -p ~/.ssh

    【重点】>> 追加,不要用 > 覆盖原有公钥

    echo "粘贴你复制的全部公钥字符串" >> ~/.ssh/authorized_keys

    权限加固(Linux sshd强制校验)

    chmod 700 ~/.ssh
    chmod 600 ~/.ssh/authorized_keys
    chown -R dev:dev ~/.ssh

步骤 3:Windows PowerShell 使用密钥登录 Linu

复制代码
# 默认私钥路径,端口22
ssh dev@10.0.0.20

# 自定义SSH端口
ssh -p 2222 dev@10.0.0.20

# 指定私钥文件(多密钥场景高频使用)
ssh -i C:\Users\xxx\.ssh\id_ed25519-linux dev@10.0.0.20

步骤 4:Windows 配置~/.ssh/config 简化连接

新建 / 编辑文件:C:\Users\xxx\.ssh\config

注意:config 文件没有后缀名

复制代码
Host linux-dev
  HostName 10.0.0.20
  User dev
  Port 22
  IdentityFile C:\Users\xxx\.ssh\id_ed25519-linux
  IdentitiesOnly yes

保存后,以后一行命令直接登录:

复制代码
ssh linux-dev

参数说明:

  • IdentitiesOnly yes:只使用指定私钥,避免客户端尝试一堆密钥导致服务器拒绝(Too many authentication failures)

步骤 5:Windows ssh-agent 托管私钥(不用反复输入 passphrase)

PowerShell(管理员权限)

复制代码
# 启动ssh-agent服务
Start-Service ssh-agent
# 设置开机自动启动
Set-Service -Name ssh-agent -StartupType Automatic
# 添加私钥到代理
ssh-add C:\Users\xxx\.ssh\id_ed25519-linux

添加之后,本次会话不用重复输入私钥密码。

Windows 专属坑点

  1. Windows 私钥文件权限:Windows NT 权限宽松,OpenSSH 会告警。右键私钥文件 → 属性 → 安全,删除其他用户,只保留当前用户拥有读取权限;
  2. 不要用记事本编辑 config,容易引入 BOM、换行符问题,推荐 VS Code;
  3. PuTTY 是另外一套体系:需要把 OpenSSH 私钥转成 ppk,本文优先原生 OpenSSH,不推荐混合使用。

五、部署公钥到服务端:ssh-copy-id 与手动方案(Linux 客户端版本)

复制代码
# 默认端口
ssh-copy-id -i ~/.ssh/id_ed25519-work user@10.0.0.10

# 自定义端口
ssh-copy-id -p 2222 -i ~/.ssh/id_ed25519-work user@10.0.0.10

# 只输出,不写入(调试看将要推送的公钥内容)
ssh-copy-id -n -i ~/.ssh/id_ed25519-work user@10.0.0.10

参数:

  • -i:指定要推送的公钥文件
  • -p:ssh 端口
  • -n:dry-run 试运行

手动写入 authorized_keys(跳板机、无 ssh-copy-id 环境)

复制代码
# 本地查看公钥
cat ~/.ssh/id_ed25519-work.pub

# 服务端执行
mkdir -p ~/.ssh
# 追加公钥,不要覆盖!
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIxxx comment" >> ~/.ssh/authorized_keys

✅ 服务端权限硬性要求(sshd 内置校验,权限宽松直接拒绝)

复制代码
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# 属主必须是登录用户,不能是root或其他账号
chown -R user:user ~/.ssh

常见坑:windows 复制粘贴公钥带入换行、空格;authorized_keys 一行一条公钥。

六、ssh 连接命令参数大全

复制代码
# 指定私钥、端口、用户
ssh -i ~/.ssh/id_ed25519-work -p 2222 dev@10.0.0.10

# 调试模式,逐级增加日志
ssh -v dev@10.0.0.10    # 简要调试
ssh -vv dev@10.0.0.10   # 中等日志,日常排错首选
ssh -vvv dev@10.0.0.10  # 完整底层交互日志,定位握手、算法协商问题

# 端口转发(本地端口转发,开发经常用到)
ssh -L 8080:127.0.0.1:8080 dev@10.0.0.20
# 远程端口转发
ssh -R 9000:127.0.0.1:9000 dev@10.0.0.20

# 静默执行远程命令(CI脚本)
ssh dev@10.0.0.20 "df -h && free -h"

七、sshd 服务端配置(Linux /etc/ssh/sshd_config)生产加固

复制代码
# 启用公钥认证(必须开启)
PubkeyAuthentication yes
# 公钥文件路径,默认
AuthorizedKeysFile .ssh/authorized_keys
# 关闭密码认证,密钥调试成功之后再打开!
PasswordAuthentication no
# 禁止空密码账号登录
PermitEmptyPasswords no
# 限制最大尝试次数,防探测
MaxAuthTries 3
# 禁用老旧不安全算法
KexAlgorithms curve25519-sha256@libssh.org

修改后重启 sshd

复制代码
# RHEL / CentOS / Rocky
systemctl restart sshd
# Ubuntu / Debian
systemctl restart ssh
# 查看状态
systemctl status sshd

八、排错清单(高频)

  1. Permissions 0644 for 'id_ed25519' are too open:私钥权限太松,Windows 收紧安全权限,Linux 执行 chmod 400 私钥文件
  2. 密钥不生效,一直弹出密码输入:检查 authorized_keys 权限、公钥是否换行空格、sshd_config PubkeyAuthentication yes
  3. Too many authentication failures:客户端自动尝试一堆密钥,配置 IdentitiesOnly yes
  4. 指纹校验:首次连接提示 host key,是主机指纹校验(中间人防护,和用户密钥不是一回事)

九、ssh-agent 补充说明

ssh-agent 是密钥代理进程,把解密后的私钥放在内存,避免反复输入 passphrase。

  • Windows:系统自带 ssh-agent 服务
  • Linux:eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519
  • Mac:ssh-add --apple-use-keychain 存入钥匙串

十、全文总结

  1. 规范流程:客户端(Windows/Linux)生成密钥对,公钥下发 Linux 服务器,私钥本地保管
  2. 优先 ed25519,RSA 仅兼容老旧环境,长度≥4096
  3. Windows 原生 OpenSSH 无需 Xshell/PuTTY,PowerShell 原生全套命令,支持 config、ssh-agent、ssh-copy-id
  4. 权限是密钥登录失败第一诱因:Linux .ssh 700、authorized_keys 600;Windows 收紧私钥 NTFS 权限
  5. 公网服务器务必关闭 PasswordAuthentication,只保留公钥认证
  6. 私钥设置 passphrase + ssh-agent 托管,兼顾安全和开发效率
相关推荐
echoarts1 小时前
服务器连不上?FileZilla 改被动模式就好了
运维·服务器·其他
无言听风雨丶2 小时前
Redis 运维实战与排错
运维·数据库·redis
QXWZ_IA2 小时前
变电站数字孪生巡检的能力分层、数据接入与空间计算边界
运维·服务器·空间计算
miaobinfei2 小时前
docker拉取dify镜像,执行docker compose up -d 报错
运维·docker·容器
女神下凡3 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
天远API3 小时前
零信任架构实战:基于天远租凭分期报告构建自动化智慧租房免押分期履约评估网关
运维·人工智能·架构·自动化
我要见SA姐13 小时前
Chrome 扩展安全攻防实录:从权限滥用到供应链投毒
运维·人工智能·python·机器学习·自动化
kobe_OKOK_3 小时前
docker compose命名卷 映射到宿主机的路径
运维·docker·容器
克里斯蒂亚诺更新4 小时前
一个服务器访问另外一个服务器端口页面
运维·服务器