原理一句话,别被教程绕晕
客户端私钥 + 远端 authorized_keys 里的公钥配对成功即可免密。所以排错时永远只围绕两件事:密钥对是否匹配、远端 sshd 是否「愿意信任」这份 authorized_keys(权限不合格会直接拒读)。
ssh-keygen -t ed25519 -C "you@laptop" # 生成密钥对(一路回车即可)
ssh-copy-id user@server # 把公钥写入远端 authorized_keys
ssh user@server # 验证:不再要密码即成功标准三步与验证方法
① 生成密钥:推荐 ed25519(更短更快更安全),路径默认 ~/.ssh/id_ed25519;② 分发公钥:ssh-copy-id 最稳(自动处理追加与权限),Windows 下没有该命令时手动追加公钥到远端 ~/.ssh/authorized_keys;③ 验证:`ssh -o BatchMode=yes user@server echo ok`——BatchMode 禁止交互式密码输入,能纯输出 ok 就证明免密真正生效,比「肉眼看着没弹密码」可靠得多。
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@server "cat >> ~/.ssh/authorized_keys"
# Windows 手动分发公钥的写法第一个隐形关卡:文件权限
sshd 对权限极其敏感:authorized_keys 或 .ssh 目录组可写就直接忽略整个文件(不报错、静默退回密码认证)。正确值:~/.ssh 700,authorized_keys 600,私钥 600。Windows 侧同理,私钥权限过宽会报 UNPROTECTED PRIVATE KEY FILE 并拒绝使用。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519第二个隐形关卡:家目录
更隐蔽的坑:家目录本身对组或其他人可写(常见于共享目录、手工 useradd 后 chmod 777 的历史遗留),sshd 同样拒绝信任 authorized_keys。用 `ls -ld /home/user` 检查,需要时收紧到 750 或更严格。排查顺序永远是「从家目录到 .ssh 到文件」逐层核对。
ls -ld /home/user # 家目录不能组/其他人可写
chmod 750 /home/user # 需要时收紧第三个隐形关卡:SELinux 与服务端日志
RHEL/CentOS 系启用 SELinux 时,authorized_keys 的安全上下文错了也会静默失效(尤其是手工 mv/cp 过文件后)。`restorecon -rv ~/.ssh` 恢复标准上下文即可。所有卡壳场景都有一个终极武器:服务端日志 `tail -f /var/log/secure`(Debian/Ubuntu 是 /var/log/auth.log),同时客户端加 -v 重连,两端信息一对,问题几乎无处藏身。
restorecon -rv ~/.ssh # SELinux 上下文修复
ssh -v user@server # 客户端详细握手过程
tail -f /var/log/secure # 服务端拒绝原因进阶:config 别名与多密钥管理
把常用连接写进 ~/.ssh/config,一条 Host 别名即可替代一长串参数,还能为不同服务器绑定不同密钥——比每次敲 -i 干净得多,git 仓库与部署脚本同样受益。
Host prod
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
ServerAliveInterval 60
# 之后只需:ssh prod