SSH 安全加固:密钥认证与密码禁用

SSH 是绝大多数服务器、VPS 与云主机默认唯一的远程管理通道,也是被扫描和爆破最频繁的入口。根据 Mozilla 的安全指南,SSH 加固并不需要复杂工具,核心就几件事:改用密钥认证、关闭密码登录、禁止 root 直接登录、收紧加密算法,再配合 Fail2ban 做暴力破解拦截。这些改动一次完成,几乎不增加日常使用成本,却能把"弱口令撞库"和"暴力猜解"这类最常见攻击挡在门外。

如果你刚拿到一台新服务器,建议先完成服务器初始化安全脚本中的基础设置,再按本文逐步加固。

为什么暴力破解如此普遍

大多数 VPS 一开机就会在几分钟内被扫描工具探测到,/var/log/auth.log 里往往能看到这样的记录:

Feb  3 02:14:31 host sshd[1234]: Failed password for root from 185.220.101.34 port 51234 ssh2
Feb  3 02:14:33 host sshd[1236]: Failed password for root from 185.220.101.34 port 51236 ssh2
Feb  3 02:14:35 host sshd[1238]: Failed password for root from 45.155.205.12 port 40211 ssh2

这些大多来自肉鸡池,会轮换 IP 持续尝试。只要密码够长够随机,纯暴力其实很难成功,但攻击者还会配合撞库——用你其他平台泄露的口令试登录。关闭密码认证后,这类攻击直接失效,这是它性价比最高的原因。

第一步:生成并部署密钥对

先在本机生成一对密钥,推荐优先使用 ed25519;需要兼容旧系统时再用 RSA 4096。

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519 -C "your-comment"

然后把公钥复制到服务器上(首次仍用密码登录):

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip

使用要点:

  • 私钥必须设置强口令,且不要拷贝到其他机器;
  • 公钥文件权限建议 600~/.ssh 目录权限 700
  • 不同用途使用不同密钥,避免一把密钥走天下,并定期用 ssh-keygen -lf 审计现有密钥。

第二步:禁用密码与 root 直接登录

编辑 /etc/ssh/sshd_config,确认以下配置:

PermitRootLogin no
PasswordAuthentication no
AuthenticationMethods publickey
PubkeyAuthentication yes
LogLevel VERBOSE

注意:PasswordAuthentication no 并不能完全阻止 PAM 层面走密码认证,建议同时检查 /etc/pam.d/sshd,确保密码认证确实被禁用。改完后用 sshd -t 校验语法,再 systemctl restart sshd。在确认密钥可以正常登录之前,请保留一个可用的登录会话,避免把自己锁在门外。

一个常见做法是先只改 PasswordAuthentication no 而不禁 root,等密钥登录稳定一两天后,再补上 PermitRootLogin no,把风险降到最低。

第三步:收紧算法与密钥强度

Mozilla 的 Modern 配置建议只保留 ed25519/rsa/ecdsa 三种 HostKey,密钥交换使用 curve25519 等安全曲线,加密算法优先 chacha20-poly1305 与 AES-GCM。同时清理过短的 Diffie-Hellman 参数:所有 moduli 建议至少 3072 位。

awk '$5 >= 3071' /etc/ssh/moduli > /etc/ssh/moduli.tmp && mv /etc/ssh/moduli.tmp /etc/ssh/moduli

算法配置越窄,兼容老客户端的可能性越低,建议先在测试环境验证后再上线。可以用开源工具 ssh-audit 快速检查当前 sshd 的算法套件是否符合预期:

pip install ssh-audit
ssh-audit your-server-ip

第四步:Fail2ban 与访问控制

即使启用密钥认证,仍建议部署 Fail2ban 拦截反复探测的 IP,并利用 Match 块把自动化机器账号限制在可信网段。也可在云厂商安全组或安全加固分类中的防火墙方案里,只对指定 IP 开放 22 端口。

Fail2ban 最小配置示例(/etc/fail2ban/jail.local):

[sshd]
enabled = true
port = ssh
maxretry = 3
bantime = 3600
findtime = 600
ignoreip = 127.0.0.1/8 你的固定IP
  • 结合Linux 防火墙配置做好端口最小化;
  • 修改非默认端口可减少扫描噪音,但不能作为安全手段本身;
  • 定期检查 /var/log/auth.log,与安全日志审计联动。

常见配置误区与上线检查清单

以下几条最容易踩坑:

  • 只改 sshd_config 却不同步检查 PAM,密码认证仍然有效;
  • 公钥部署后未验证就断开当前会话,导致无法登录;
  • 密钥文件权限过宽,被其他用户读取;
  • 修改非默认端口后忘了同步防火墙与云安全组规则。

上线前按清单核对:用 sshd -T 检查生效配置、ssh -v 验证密钥登录、ufw status 确认 22 端口放行来源、journalctl -u ssh 查看登录日志。配置可配合服务器初始化安全脚本一次性固化,并定期用 ssh-keygen -lf 复核服务器 authorized_keys,删除不再使用的密钥。

常见问题

  • 关了密码登录,临时忘带私钥怎么办? 保留一个备用密钥,或让同事临时放行指定 IP 一段时间,再切回密钥。
  • 多台服务器怎么管理密钥? 用 SSH config 组织别名,配合机密管理集中管理私钥,避免散落。
  • 能只对部分账号禁用密码吗? 可以,用 Match UserMatch Group 块按用户差异化配置。
  • 需要再叠加两步验证吗? 想要更严格,可以给密钥登录叠加 TOTP 或硬件密钥(配合 PAM 的 MFA),对统一登录入口尤其值得。

16IDC 观察

对站长和中小团队来说,SSH 加固是投入产出比最高的安全动作:几行配置就能移除最常见的暴力破解路径。真正容易出问题的是"改完忘记保留会话"和"密钥散落各处",建议把密钥管理纳入机密管理体系,从入口到凭据全链路收敛。

原文来源:https://infosec.mozilla.org/guidelines/openssh
参考:OpenSSH 手册 https://www.openssh.com/manual.html
参考:ssh-audit https://github.com/jtesta/ssh-audit