5月28日 02:06

如何配置 SSH 密钥认证?密钥认证相比密码认证有哪些优势?

SSH 密钥认证基于非对称加密,客户端持有私钥、服务器持有公钥,登录时通过加密挑战完成身份验证,无需传输密码。相比密码认证,密钥认证抗暴力破解、免输入密码、可精细控制权限,是服务器安全运维的基本要求。

密钥类型怎么选

主流密钥算法对比:

算法密钥长度安全性性能推荐度
ED25519256 bit极高最快首选
ECDSA256 bit可用
RSA4096 bit兼容性场景

ED25519 基于 Curve25519 椭圆曲线,密钥短、签名快、抗侧信道攻击,是当前首选。RSA 4096 仅在需要兼容老旧系统时使用。

生成密钥对

bash
# 生成 ED25519 密钥(推荐) ssh-keygen -t ed25519 -C "user@example.com" # 生成 RSA 4096 密钥(兼容旧系统) ssh-keygen -t rsa -b 4096 -C "user@example.com" # 指定密钥文件名 ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "ci/deploy" # 生成带硬件绑定的 FIDO2 密钥(需要 YubiKey 等设备) ssh-keygen -t ed25519-sk -C "user@example.com"

生成后会产生两个文件:

  • 私钥~/.ssh/id_ed25519):绝对不能泄露,等同于你的身份凭证
  • 公钥~/.ssh/id_ed25519.pub):可以公开,上传到目标服务器

私钥建议设置 passphrase,即使私钥被盗,攻击者也无法直接使用。

配置服务器端密钥登录

第一步:复制公钥到服务器

bash
# 方法一:ssh-copy-id(最简单) ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname # 方法二:手动追加(目标机器没有 ssh-copy-id 时) cat ~/.ssh/id_ed25519.pub | ssh user@hostname \ "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

第二步:确认服务器 SSH 配置

编辑服务器上的 /etc/ssh/sshd_config

bash
# 启用公钥认证 PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys # 确认密钥登录成功后,再禁用密码认证 PasswordAuthentication no

修改后重启服务:

bash
# Ubuntu/Debian sudo systemctl restart sshd # CentOS/RHEL sudo systemctl restart sshd

注意:先测试密钥登录成功,再禁用密码认证,否则可能锁死自己。

第三步:设置文件权限

权限不对是密钥登录失败最常见的原因:

bash
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chmod 600 ~/.ssh/id_ed25519 # 私钥 chmod 644 ~/.ssh/id_ed25519.pub # 公钥

密钥认证比密码认证强在哪

抗暴力破解:密码可被字典攻击逐个尝试,而 256 bit 的 ED25519 私钥暴力破解概率在计算上不可能。一次暴力尝试的代价相差约 2^128 倍。

零密码传输:密码认证每次登录都要把密码发送到服务器,存在中间人截获风险。密钥认证只传输加密签名,私钥永不离开本地。

免交互登录:配合 ssh-agent 或无 passphrase 的密钥,可实现自动化部署、定时备份、CI/CD 流水线免密操作,密码认证做不到。

细粒度权限控制:在 authorized_keys 中可限制单个密钥的权限:

bash
# 限制只能执行 git 操作 command="/usr/bin/git-shell" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... # 限制来源 IP from="10.0.0.0/8" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... # 禁用端口转发和 X11 no-port-forwarding,no-X11-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... # 组合限制:只允许从内网 SCP 文件 command="/usr/libexec/openssh/sftp-server",from="10.0.0.0/8",no-port-forwarding ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...

多因素叠加:密钥本身是「你有的」,加上 passphrase 就是「你知道的」,再加 FIDO2 硬件密钥就是「你有的物理设备」,三因素认证也轻松实现。

ssh-agent 管理多个密钥

管理多台服务器或多个 Git 平台时,需要不同的密钥:

bash
# 启动 agent eval "$(ssh-agent -s)" # 添加密钥(会提示输入 passphrase) ssh-add ~/.ssh/id_ed25519 ssh-add ~/.ssh/deploy_key # 查看已加载的密钥 ssh-add -l # 删除所有密钥 ssh-add -D

配置 ~/.ssh/config 让不同主机使用不同密钥:

bash
Host github.com IdentityFile ~/.ssh/id_ed25519 User git Host production-server IdentityFile ~/.ssh/deploy_key User deploy Port 2222 Host jump-server IdentityFile ~/.ssh/id_ed25519 ProxyJump none Host internal-* ProxyJump jump-server IdentityFile ~/.ssh/id_ed25519

常见排错

密钥登录失败时,按以下顺序排查:

1. 用 verbose 模式看详细日志

bash
ssh -vvv user@hostname

重点看 Offering public keyServer accepts key 两行。

2. 检查权限

bash
# 客户端 ls -la ~/.ssh/ # 私钥必须是 600,目录必须是 700 # 服务器端 ls -la ~/.ssh/ ~/.ssh/authorized_keys # authorized_keys 必须 600,~/.ssh 必须 700

3. 检查服务器端日志

bash
# 查看 SSH 服务日志 sudo journalctl -u sshd --since "10 minutes ago" # 或 sudo tail -f /var/log/auth.log

常见错误原因:

现象原因解决
Permission deniedauthorized_keys 权限 644chmod 600
Permission denied.ssh 目录权限 755chmod 700
Permission denied家目录被组可写chmod 750 ~
Connection refusedsshd 未运行systemctl start sshd
密钥不被接受公钥内容被截断/换行重新复制
SELinux 阻止文件安全上下文不对restorecon -Rv ~/.ssh

安全加固清单

  • 使用 ED25519 或 RSA 4096,不用 RSA 2048 及以下
  • 私钥设置 passphrase,用 ssh-agent 避免反复输入
  • 服务器端禁用密码认证:PasswordAuthentication no
  • 禁用 root 远程登录:PermitRootLogin noprohibit-password
  • 限制 SSH 端口,不用默认 22
  • 定期轮换密钥,移除 authorized_keys 中的旧公钥
  • 敏感服务器使用 FIDO2 硬件密钥(ed25519-sk
  • 配置 fail2ban 防止扫描探测
  • 审计 SSH 登录日志,关注异常 IP
标签:SSH