464 字
2 分钟
让密码登录“先过 2FA”而私钥秒进:一份不说废话的 SSH 配置笔记
服务器搭好后,我把私钥扔进服务器ssh,一点就能连服务器,爽得像回自家。
可Last seen里偶尔冒出陌生 IP,说明 root 密码还在被爆破。
于是想:能不能让“输密码”的先去 Google Authenticator 报个到,
而用私钥的继续保持丝滑?
踩了两次“keyboard-interactive 找不到”的坑后,终于把最小改动集整理出来,
只改 3 处,给同样不想整行复制粘贴的你。
1 思路:让 PAM 做“安检员”,sshd 只做“引路员”
| 登录方式 | sshd 默认允许 | PAM 脚本判断 | 结果 |
|---|---|---|---|
| 私钥 (publickey) | ✅ | 检测到 SSH_AUTH_SOCK → 放行 | 免 2FA |
| 密码 (keyboard-interactive) | ✅ | 无 auth sock → 走 GA | 要 2FA |
全程不碰
AuthenticationMethods,所以永远不会因为拼写错误把自己锁死。
2 改 sshd_config
sudo nano /etc/ssh/sshd_config取消注释(或追加):
KbdInteractiveAuthentication yesChallengeResponseAuthentication yes确保下面 3 项保持默认/启用(你的配置已满足):
PubkeyAuthentication yesPasswordAuthentication yesUsePAM yes不需要
AuthenticationMethods行!
改完:wq→sudo systemctl restart sshd
3 改 PAM 策略
sudo nano /etc/pam.d/sshd- 在最顶部加入“公钥免检”钩子(先 success 就跳过 GA)
auth [success=1 default=ignore] pam_exec.so quiet /usr/local/bin/check_ssh_pubkey.sh
- 紧接着强制 GA 模块
auth required pam_google_authenticator.so nullok
nullok允许用户尚未绑定 GA 时仍可登录(过渡阶段友好)。
4 写免检脚本
sudo nano /usr/local/bin/check_ssh_pubkey.sh#!/bin/bash# 如果环境变量里出现 SSH_AUTH_SOCK 说明是公钥登录if [ -n "$SSH_AUTH_SOCK" ]; then exit 0 # 公钥派 → 跳过 2FAelse exit 1 # 密码派 → 继续走 GAfi加执行权限
sudo chmod +x /usr/local/bin/check_ssh_pubkey.sh5 一分钟自测
| 测试场景 | 预期结果 |
|---|---|
ssh root@ip 有私钥 | 直接进,不提示验证码 |
ssh -o PreferredAuthentications=password root@ip | 提示 Verification code: |
| 输错 2FA 码 | Permission denied |
全部通过后,把窗口关掉再开,留一条 SSH 会话别断,防止把自己锁外面。
安心睡觉,爆破党再见 👋
让密码登录“先过 2FA”而私钥秒进:一份不说废话的 SSH 配置笔记
https://blog.sheepmc.top/posts/让密码登录先过-2fa而私钥秒进一份不说废话的-ssh-配置笔记/