跳转到内容

SSH 密钥登录配置完全指南 | VPS 安全防护教程

SSH Key Authentication Security

购买 VPS 后,大部分服务商默认提供的是账号密码登录。然而,随着公网上恶意的扫描程序和自动化工具越来越多,仅仅使用密码登录有着极高被暴力破解(爆破)的风险。

最安全的做法是:改用 SSH 密钥登录,并关闭密码登录。这样即便是世界上最顶级的黑客,在没有你的私钥的情况下也无法登入你的服务器。

什么是 SSH 密钥?

SSH 密钥由两部分组成:

  • 私钥 (Private Key):存放在你自己的电脑上,绝对不能泄露给任何人。
  • 公钥 (Public Key):上传并保存在你的 VPS 服务器上。

登录时,服务器通过公钥来验证你电脑上的私钥,验证匹配后即允许登录,全程无需输入密码。

SSH 密钥 vs 密码登录对比

特性密码登录SSH 密钥登录
安全性⭐⭐(易被爆破)⭐⭐⭐⭐⭐(几乎无法破解)
便利性每次输入密码一键登录(可配置免密)
抗暴力破解❌ 弱✅ 极强
多设备管理同一密码风险高每设备独立密钥
自动化支持需存储明文密码脚本友好
推荐程度不推荐强烈推荐

步骤一:在本地电脑生成密钥对

无论你使用的是 Windows、macOS 还是 Linux 电脑,目前的系统均内置了生成 SSH 密钥的工具。

生成 Ed25519 密钥(推荐)

打开你本地电脑的终端(Windows 可以使用 PowerShell 或 CMD,macOS 使用 Terminal),输入以下命令并回车:

bash
ssh-keygen -t ed25519 -C "your_email@example.com"

注:-t ed25519 是一种更新、更安全、更高效的加密算法。如果较老的系统不支持,可使用 ssh-keygen -t rsa -b 4096。后面的邮箱只作为标识备注。

生成 RSA 密钥(兼容旧系统)

bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

参数说明:

  • -t: 指定密钥类型(ed25519 或 rsa)
  • -b: 密钥位数(RSA 建议 4096)
  • -C: 注释(通常是邮箱,便于识别)

交互式配置

输入命令后,系统会连续向你询问三个问题,通常直接一直按回车键即可:

  1. 保存路径确认:默认保存在 ~/.ssh/id_ed25519(Windows 一般在 C:\Users\用户名\.ssh\id_ed25519)。
  2. 设置密钥保护密码(passphrase):如果设置了,每次使用私钥还需要输入这个密码。为图方便可以直接留空回车。
  3. 再次确认密码:留空回车。

Passphrase 建议:

  • 个人电脑:可以留空,方便免密登录
  • 共享电脑:务必设置强密码
  • 生产环境:建议配合 ssh-agent 使用

完成后,你的本地电脑上会生成两个文件:

  • id_ed25519(这就是私钥)- 保密!
  • id_ed25519.pub(这就是公钥)- 可以公开

查看生成的密钥:

bash
# 列出 .ssh 目录内容
ls -la ~/.ssh/

# 查看公钥内容
cat ~/.ssh/id_ed25519.pub

# 输出示例:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.com

步骤二:将公钥上传到 VPS

目前你的公钥还在本地,接下来我们要把它放到 VPS 服务器的指定位置。我们将它放在 root 账户下(如果你使用的是其它用户如 ubuntu,请自行替换路径):

方法 1:使用快捷命令 ssh-copy-id (推荐 macOS / Linux / 较新 Windows)

在本地电脑终端中输入:

bash
ssh-copy-id root@你的VPS_IP地址

然后系统会提示你输入 VPS 的 root 密码,输入完毕回车,公钥就会被自动导入。

批量添加多个服务器:

bash
# 创建服务器列表文件
cat > servers.txt <<EOF
root@192.168.1.100
root@192.168.1.101
ubuntu@203.0.113.50
EOF

# 批量上传公钥
while read server; do
  ssh-copy-id "$server"
done < servers.txt

方法 2:手动复制公钥

如果你觉得命令不好用,也可以通过手动方式:

  1. 用记事本(或用 cat 命令)打开本地的 id_ed25519.pub 文件,复制里面那一长串以 ssh-ed25519 开头的文本。
  2. 使用密码正常登录你的 VPS。
  3. 在 VPS 终端上执行以下命令:
    bash
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
    nano ~/.ssh/authorized_keys
  4. 将刚刚复制的公钥文本粘贴进去。
  5. Ctrl + X,再按 Y,然后按回车保存退出。
  6. 最后设置权限:
    bash
    chmod 600 ~/.ssh/authorized_keys

方法 3:使用 scp 命令上传

bash
# 从本地复制公钥到服务器
scp ~/.ssh/id_ed25519.pub root@你的VPS_IP:/tmp/

# SSH 登录服务器
ssh root@你的VPS_IP

# 在服务器上执行
mkdir -p ~/.ssh
cat /tmp/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
rm /tmp/id_ed25519.pub

权限要求总结

文件/目录权限说明
~/.ssh700仅所有者可读写执行
~/.ssh/authorized_keys600仅所有者可读写
私钥文件600绝对保密
公钥文件644可以公开

步骤三:测试密钥登录是否成功

在没关闭密码登录之前,务必先测试一次密钥登录是否生效! 如果生效了,再去关闭密码,否则你可能会把你自己锁在服务器外面!

基本测试

在本地电脑终端重新登录服务器:

bash
ssh root@你的VPS_IP地址

如果你发现这一次没有让你输入密码就直接登录进去了,恭喜你,密钥配置成功!

指定私钥文件测试

如果你有多个密钥,可以指定使用哪个:

bash
ssh -i ~/.ssh/id_ed25519 root@你的VPS_IP地址

详细调试模式

如果登录失败,使用 -v 参数查看详细日志:

bash
ssh -v root@你的VPS_IP地址

# 更详细的日志
ssh -vv root@你的VPS_IP地址

# 最详细的日志
ssh -vvv root@你的VPS_IP地址

常见错误及解决:

  • Permission denied (publickey):公钥未正确安装或权限错误
  • Connection refused:SSH 服务未启动或端口错误
  • Connection timed out:防火墙阻止或 IP 错误

步骤四:关闭 SSH 密码登录(关键一步)

密钥登录成功后,我们需要彻底关掉传统的账号密码登录入口。

编辑 SSH 配置文件

  1. 在 VPS 终端中,编辑 SSH 配置文件:

    bash
    nano /etc/ssh/sshd_config
  2. 在文件中寻找以下这两行配置项,把它们改成 no(如果前面有 # 号注释,记得把 # 删掉):

    text
    PasswordAuthentication no
    PermitEmptyPasswords no

    提示:在 nano 编辑器中可以按 Ctrl + W 搜索 "PasswordAuthentication"。

  3. 修改完成后,按 Ctrl + X,再按 Y,回车保存退出。

其他安全加固选项

在同一配置文件中,还可以优化以下设置:

text
# 禁用 root 直接登录(推荐先创建普通用户)
PermitRootLogin prohibit-password

# 修改 SSH 端口(避免使用默认 22)
Port 2222

# 限制登录用户
AllowUsers your_username

# 禁用 X11 转发(不需要图形界面时)
X11Forwarding no

# 设置登录超时时间(秒)
ClientAliveInterval 300
ClientAliveCountMax 2

# 禁用 DNS 查询(加快登录速度)
UseDNS no

重启 SSH 服务

  1. 重启 SSH 动作使配置生效:
    bash
    systemctl restart sshd
    注意:Debian/Ubuntu 系统有时服务名叫 ssh,可以尝试 systemctl restart ssh

重要提醒: 重启前确保:

  • ✅ 已在另一个终端窗口测试密钥登录成功
  • ✅ 保留了 VNC 控制台访问权限(应急用)
  • ✅ 记录了新的 SSH 端口(如果修改了)

SSH Agent - 密钥管理神器

什么是 SSH Agent?

SSH Agent 是一个密钥管理程序,可以在内存中缓存你的私钥,避免每次连接都输入 passphrase。

启动 SSH Agent

bash
# 启动 agent
eval "$(ssh-agent -s)"

# 添加私钥到 agent
ssh-add ~/.ssh/id_ed25519

# 列出已加载的密钥
ssh-add -l

# 删除所有密钥
ssh-add -D

自动启动配置

添加到 ~/.bashrc~/.zshrc

bash
# 自动启动 ssh-agent
if [ -z "$SSH_AUTH_SOCK" ]; then
  eval "$(ssh-agent -s)"
  ssh-add ~/.ssh/id_ed25519 2>/dev/null
fi

macOS 集成钥匙串

bash
# macOS 可以将密钥存储在钥匙串中
ssh-add --apple-use-keychain ~/.ssh/id_ed25519

# 编辑 ~/.ssh/config
Host *
  UseKeychain yes
  AddKeysToAgent yes

SSH 配置文件进阶

创建 SSH 客户端配置

编辑本地 ~/.ssh/config 文件:

bash
nano ~/.ssh/config

基础配置示例:

text
# 全局默认设置
Host *
    IdentityFile ~/.ssh/id_ed25519
    User root
    Port 22
    ServerAliveInterval 60
    ServerAliveCountMax 3
    ConnectTimeout 10

# 特定服务器配置
Host my-vps
    HostName 192.168.1.100
    User root
    Port 2222
    IdentityFile ~/.ssh/my_vps_key

Host work-server
    HostName 203.0.113.50
    User admin
    Port 22
    IdentityFile ~/.ssh/work_key

# 跳板机配置(堡垒机)
Host *.internal
    ProxyJump bastion.example.com
    User deploy

使用简化命令:

bash
# 原本需要输入
ssh -p 2222 -i ~/.ssh/my_vps_key root@192.168.1.100

# 现在只需输入
ssh my-vps

常用配置参数

参数说明示例
HostName实际主机名或 IP192.168.1.100
User登录用户名root, ubuntu
PortSSH 端口22, 2222
IdentityFile私钥路径~/.ssh/id_ed25519
ProxyJump跳板机bastion.example.com
LocalForward端口转发3306 localhost:3306
ServerAliveInterval保活间隔(秒)60

多密钥管理

场景:不同服务器使用不同密钥

生成多个密钥:

bash
# 工作服务器密钥
ssh-keygen -t ed25519 -f ~/.ssh/work_key -C "work@example.com"

# 个人服务器密钥
ssh-keygen -t ed25519 -f ~/.ssh/personal_key -C "personal@example.com"

# GitHub 密钥
ssh-keygen -t ed25519 -f ~/.ssh/github_key -C "github@example.com"

配置 ~/.ssh/config

text
# 工作服务器
Host work-*
    IdentityFile ~/.ssh/work_key
    User admin

# 个人服务器
Host personal-*
    IdentityFile ~/.ssh/personal_key
    User root

# GitHub
Host github.com
    IdentityFile ~/.ssh/github_key
    User git

查看和管理密钥

bash
# 列出所有密钥指纹
ssh-add -l

# 查看密钥详细信息
ssh-add -L

# 删除特定密钥
ssh-add -d ~/.ssh/old_key

# 删除所有密钥
ssh-add -D

SSH 证书认证(企业级)

什么是 SSH 证书?

SSH 证书是由 CA(证书颁发机构)签名的公钥,提供更细粒度的访问控制和自动过期机制。

创建 CA 密钥

bash
# 在 CA 服务器上
ssh-keygen -t ed25519 -f ca_key -C "SSH CA Key"

签署用户密钥

bash
# 签署用户公钥,有效期 52 周
ssh-keygen -s ca_key -I user_id -n username -V +52w id_ed25519.pub

# 生成证书文件:id_ed25519-cert.pub

配置服务器信任 CA

bash
# 在 SSH 服务器上
echo "TrustedUserCAKeys /etc/ssh/ca_key.pub" >> /etc/ssh/sshd_config
systemctl restart sshd

优势:

  • ✅ 集中管理密钥
  • ✅ 自动过期
  • ✅ 细粒度权限控制
  • ✅ 易于撤销

常见问题排查

Q1: 密钥登录失败,提示 "Permission denied (publickey)"?

排查步骤:

  1. 检查文件权限
bash
# 在服务器上执行
ls -la ~/.ssh/
# 应该显示:
# drwx------ .ssh
# -rw------- authorized_keys

# 修复权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
  1. 检查公钥格式
bash
# 确保公钥在一行内
cat ~/.ssh/authorized_keys
# 不应该有换行符
  1. 检查 SELinux(CentOS/RHEL)
bash
# 恢复正确的安全上下文
restorecon -Rv ~/.ssh
  1. 查看详细日志
bash
# 在服务器上查看
tail -f /var/log/auth.log
# 或
journalctl -u sshd -f

# 在客户端使用调试模式
ssh -vvv root@your_server

Q2: 误把自己的 IP 锁在外面怎么办?

紧急救援方案:

  1. 使用 VNC 控制台

    • 登录云服务商面板
    • 打开 VNC 控制台
    • 临时启用密码登录
    bash
    nano /etc/ssh/sshd_config
    # 修改:PasswordAuthentication yes
    systemctl restart sshd
  2. 从其他可信 IP 登录

    • 如果有其他已配置密钥的设备
    • 或通过同事的电脑访问
  3. 联系服务商重置

    • 大多数云服务商提供密码重置功能
    • 或通过工单系统请求帮助

预防措施:

  • ✅ 始终保留 VNC 访问权限
  • ✅ 在白名单中添加备用 IP
  • ✅ 测试完成后再关闭密码登录

Q3: 如何在多台服务器间同步密钥?

方法 1:使用配置管理工具

bash
# Ansible 示例
ansible all -m authorized_key -a "user=root key='{{ lookup('file', '~/.ssh/id_ed25519.pub') }}'"

方法 2:使用脚本批量部署

bash
#!/bin/bash
servers=("192.168.1.100" "192.168.1.101" "203.0.113.50")

for server in "${servers[@]}"; do
  echo "Deploying to $server..."
  ssh-copy-id root@$server
done

方法 3:使用 Git 管理

bash
# 将 authorized_keys 纳入版本控制
cd /etc/ssh
git init
git add authorized_keys
git commit -m "Update SSH keys"

# 在其他服务器上拉取
git pull
systemctl restart sshd

Q4: 密钥文件丢失怎么办?

恢复步骤:

  1. 从备份恢复
bash
# 如果有备份
cp backup/id_ed25519 ~/.ssh/
chmod 600 ~/.ssh/id_ed25519
  1. 通过 VNC 重新部署
bash
# 在 VNC 控制台中
# 1. 临时启用密码登录
# 2. 从本地重新上传公钥
# 3. 生成新密钥对
  1. 重新生成密钥
bash
# 在本地生成新密钥
ssh-keygen -t ed25519 -f ~/.ssh/new_key

# 通过 VNC 部署新公钥
# 然后更新所有服务器的 authorized_keys

预防建议:

  • ✅ 定期备份 .ssh 目录
  • ✅ 使用密码管理器存储 passphrase
  • ✅ 在多个安全位置保存私钥副本

Q5: 如何审计和清理无效密钥?

查看当前授权密钥:

bash
# 在服务器上
cat ~/.ssh/authorized_keys

# 查看最后登录时间
lastlog

# 查看活跃会话
who
w

清理策略:

bash
#!/bin/bash
# 审计脚本

echo "=== SSH Key Audit ==="
echo ""
echo "Authorized keys:"
cat ~/.ssh/authorized_keys | wc -l
echo ""

echo "Recent logins:"
last -n 10
echo ""

echo "Active sessions:"
who

最佳实践:

  • 每季度审查一次 authorized_keys
  • 移除离职员工或废弃项目的密钥
  • 记录每个密钥的用途和所有者
  • 使用注释标识密钥用途
text
ssh-ed25519 AAAA... user@company-laptop # John Doe, Dev Team
ssh-ed25519 BBBB... deploy@ci-server   # CI/CD Pipeline

额外建议与安全提醒

安全最佳实践清单

必须做:

禁止做:

高级安全加固

1. 使用 Fail2ban 防护

bash
# 参考我们的 Fail2ban 教程
# 自动封禁多次失败的 IP
apt install fail2ban

2. 启用双因素认证(2FA)

bash
# 安装 Google Authenticator
apt install libpam-google-authenticator

# 配置 PAM
nano /etc/pam.d/sshd
# 添加:auth required pam_google_authenticator.so

# 配置 SSH
nano /etc/ssh/sshd_config
# 添加:AuthenticationMethods publickey,keyboard-interactive

3. 限制登录来源 IP

bash
# 在 /etc/ssh/sshd_config 中
AllowUsers root@192.168.1.0/24
AllowUsers deploy@203.0.113.50

4. 使用 SSH 证书代替密钥

  • 适合大型企业
  • 集中管理
  • 自动过期
  • 细粒度权限

保管好你的私钥!

既然密码登录已经关闭,那么本地电脑上的那个 id_ed25519 私钥文件就是你连接这台服务器的 唯一凭证。如果你重装了电脑或者弄丢了这个私钥文件,你将永远无法再次登入这台服务器!(除非主机面板提供了 VNC 救援控制台)

私钥备份策略:

  1. 加密存储:使用 VeraCrypt 或 BitLocker 加密 U 盘
  2. 密码管理器:1Password、Bitwarden 等支持附件存储
  3. 纸质备份:打印 QR 码或助记词(极端情况)
  4. 多地点存储:家中保险箱 + 银行保管箱

不要把私钥发送给任何人,尤其是不要将其上传到公开的代码仓库(如 GitHub)。

按照以上步骤,你可以高枕无忧了,公网上的无聊扫描机器人再也无法攻破你的 SSH 堡垒。🔒✨


免责声明

本文仅供技术交流和学习参考,请遵守当地法律法规,合理合法使用网络服务。