← 全部笔记

SSH 免密登录:从生成到关掉密码登录

2026-10-26 系统与运维 约 7 分钟

免密登录本身五分钟就能配好,麻烦的是配完之后偶尔失效,而报错信息又只有一句 Permission denied (publickey)。这篇把能想到的原因都列一遍。

一、生成一对密钥

ssh-keygen -t ed25519 -C "alin@laptop"
  • -t ed25519:现在的默认推荐,密钥短、签名快,兼容性已经足够。
  • 老系统不支持 ed25519 时退回 -t rsa -b 3072;2048 位也还能用,但没必要再新建。
  • -C 是注释,会附在公钥末尾,用来区分「这把钥匙是哪台机器的」,不影响认证。
  • 口令(passphrase)建议设。设了之后可以用 ssh-agent 免去反复输入。

生成后目录里有两个文件:

  • ~/.ssh/id_ed25519 私钥,任何情况下不外传。
  • ~/.ssh/id_ed25519.pub 公钥,这一行文本就是可以随便给出去的部分。

二、把公钥放到服务器上

# 最简单的方式
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

# 没有 ssh-copy-id 时手动追加
cat ~/.ssh/id_ed25519.pub | ssh user@host \
  'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

三、权限:90% 的「密钥没生效」都在这里

sshd 有一套严格检查(StrictModes,默认开启),不满足就静默忽略这把密钥,只回一句 publickey 失败:

  • ~/.ssh 权限必须是 700。
  • ~/.ssh/authorized_keys 必须是 600。
  • 家目录本身不能被 group 或其他用户写:755、750 都行,777 不行。
  • SELinux 开启的系统上,文件的安全上下文也要对,否则同样被拒。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod go-w ~            # 去掉家目录的组写和其他人写权限

查失败原因最快的办法是让 sshd 说出细节:

# 服务端(需要 root)
sshd -T | grep -E "strictmodes|pubkeyauthentication|authorizedkeysfile"
tail -f /var/log/auth.log        # Debian/Ubuntu
tail -f /var/log/secure          # RHEL/CentOS

# 客户端
ssh -vvv user@host               # 看它到底试了哪把钥匙

四、关掉密码登录

确认密钥能正常登录之后,再改 /etc/ssh/sshd_config 这三项:

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password

PermitRootLogin prohibit-password 的意思是「root 只能用密钥登录,不能用密码」, 比直接 no 宽松一点,救急时还能进。

改完不要立刻断开当前的连接。先 systemctl reload sshd, 然后另开一个窗口试登录,成功了再关旧窗口。 直接改完退出是把自己锁在门外最经典的方式。

五、客户端 config:把长命令变成别名

~/.ssh/config(权限 600)里可以写:

Host db
    HostName 10.0.0.12
    User alin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host *
    ServerAliveInterval 30
    ServerAliveCountMax 3

之后 ssh db 就够了。ServerAliveInterval 那两行是给容易断线的网络用的: 每 30 秒发一个保活包,连续 3 次没回应才判定断线。

六、host key 变了怎么办

重装系统或换机器后首次连接会看到一大段警告:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

这是 SSH 在提醒你「对面这台机器的身份变了」,可能是正常的重装, 也可能是中间人。确认是前者之后再删掉旧记录:

ssh-keygen -R host          # 按主机名删
ssh-keygen -R 10.0.0.12     # 按 IP 删,known_hosts 里两者是分开的两条

七、ssh-agent 与转发

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519        # 输入一次口令,本次会话内不再问
ssh-add -l                       # 列出已加载的钥匙
ssh-add -t 2h ~/.ssh/id_ed25519  # 2 小时后自动失效

ssh -A(Agent 转发)能让你从跳板机继续往内网跳而不用把私钥传过去, 但它把 agent 暴露给了远端主机——只在受控的跳板机上用。


一句话总结:公钥进 authorized_keys,权限必须 700 / 600,家目录不能给别人写;改完 sshd_config 先另开一个窗口试,别把自己锁在外面。