如何将 SSH Keys 添加到新的或现有的 VPS
SSH密钥是加密密钥对——存储在服务器上的公钥和保存在本地计算机上的私钥——无需通过网络传输密码即可验证您的身份。连接时,服务器会发出只有您的私钥才能解答的加密挑战,若响应有效则授予访问权限。这种机制使SSH密钥认证在抵御暴力破解攻击、凭据填充和中间人拦截方面,从根本上优于任何基于密码的方案。
本指南涵盖在新旧VPS实例上生成、部署和强化SSH密钥认证的完整流程——包括大多数教程完全跳过的边缘情况、权限陷阱和多密钥管理。
为什么SSH密钥在架构上优于密码
密码认证会通过网络发送密钥(或其哈希值),并依赖服务器存储可验证的凭据。SSH公钥认证从不暴露私钥——无论是在生成时、登录时,还是任何其他时候。私钥永远不会离开您的本地计算机。
除了原始安全性之外,SSH密钥还解锁了密码无法实现的操作能力:
- 无人值守自动化 — CI/CD流水线、Ansible playbook和cron驱动的rsync任务需要非交互式认证。密码完全无法满足这一需求。
- 细粒度访问控制 —
authorized_keys中的每个条目都可以携带command=、from=和no-pty限制,精确限定特定密钥被允许执行的操作。 - 可审计性 — 可以撤销单个密钥,而无需更改共享密码并影响其他所有用户或脚本。
- 防钓鱼 — 不存在可通过虚假登录页面窃取的密码。
| 功能 | 密码认证 | SSH密钥认证 |
|---|---|---|
| 暴力破解抵抗力 | 低——受密码复杂度限制 | 极高——256位或4096位密钥空间 |
| 凭据暴露风险 | 高——密码在服务器上发送或哈希 | 无——私钥从不传输 |
| 自动化支持 | 差——需要交互式输入或明文存储 | 优秀——完全非交互式 |
| 每密钥访问限制 | 不可能 | 通过authorized_keys选项支持 |
| 撤销粒度 | 影响所有会话 | 按密钥撤销,不影响其他密钥 |
| 密码短语保护 | 不适用 | 私钥上的可选第二因素 |
| 多用户密钥管理 | 共享密码 = 共同风险 | 每个用户或服务获得独立密钥 |
前提条件
在继续之前,请确认以下事项:
- 您有一台正在运行的VPS,或正在配置一台。
- 您的本地计算机运行Linux、macOS,或安装了OpenSSH的Windows(Windows 10/11默认附带OpenSSH;使用
ssh -V验证)。 - 您对目标服务器拥有root或sudo访问权限。
- 您了解,在没有其他登录方式(控制台访问、恢复密钥)的情况下丢失私钥可能导致您被永久锁定。
选择正确的密钥算法
原始的ssh-keygen -t rsa -b 4096命令很可靠,但并非唯一选择。了解各方案的权衡有助于您为环境做出正确选择。
| 算法 | 命令标志 | 密钥大小 | 安全级别 | 备注 |
|---|---|---|---|---|
| RSA | -t rsa -b 4096 | 4096位 | 高 | 通用兼容,包括旧版系统 |
| ECDSA | -t ecdsa -b 521 | 521位 | 非常高 | 比RSA更快;适合现代技术栈 |
| Ed25519 | -t ed25519 | 256位(固定) | 最高 | 推荐默认选项;最快、最小、最安全 |
| DSA | -t dsa | 1024位 | 已弃用 | 请勿使用——已损坏,在OpenSSH 7.0+中已禁用 |
Ed25519是推荐算法,适用于运行OpenSSH 6.5或更高版本(2014年发布)的任何服务器。仅在连接不支持椭圆曲线密钥的旧版系统时才使用RSA 4096。
第一部分:向新VPS添加SSH密钥
许多托管控制面板允许您在配置时注入公钥,即在实例启动之前。这是最简洁的方法——密钥已嵌入镜像中,可能永远不需要启用密码认证。
步骤1:生成SSH密钥对
在本地计算机上打开终端。生成Ed25519密钥对:
ssh-keygen -t ed25519 -C "your_email@example.com"如果出于兼容性原因需要RSA:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"当提示输入文件位置时,按Enter接受默认值(~/.ssh/id_ed25519或~/.ssh/id_rsa)。当提示输入密码短语时,请设置一个——它会加密磁盘上的私钥,即使您的笔记本电脑被盗,没有密码短语该密钥也毫无用处。您的SSH代理(ssh-agent)会将解密后的密钥缓存在内存中,因此每个会话只需输入一次密码短语。
验证生成的文件:
ls -la ~/.ssh/您将看到:
id_ed25519— 您的私钥(权限必须为600;切勿共享此文件)id_ed25519.pub— 您的公钥(可安全复制到任何地方)
显示公钥以复制它:
cat ~/.ssh/id_ed25519.pub输出如下所示:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.com复制整个字符串——您将把它粘贴到托管面板中。
步骤2:在VPS配置期间添加公钥
登录您的托管控制面板。在VPS创建工作流程中:
- 选择您的操作系统(Ubuntu 22.04 LTS、Debian 12、Rocky Linux 9等)。
- 找到SSH密钥或认证部分。
- 将
id_ed25519.pub的完整内容粘贴到提供的字段中。 - 完成其余配置(套餐、地区、主机名)。
VPS启动后,配置系统会自动将您的公钥写入/root/.ssh/authorized_keys。无需密码登录。
步骤3:连接到新配置的VPS
ssh root@your_vps_ip如果您使用了非默认密钥文件名,请明确指定:
ssh -i ~/.ssh/id_ed25519 root@your_vps_ip无需密码提示即可成功连接,确认密钥已正确注入。如果您设置了密码短语,SSH代理或本地密码短语提示将在本地处理它。
第二部分:向现有VPS添加SSH密钥
如果您的VPS已在运行密码认证,则需要手动部署公钥。这是一个两阶段过程:复制密钥,然后可选地强化SSH守护进程。
步骤1:生成密钥对(如果您还没有)
按照上面第一部分步骤1中的相同流程操作。如果您已有密钥对,请检索您的公钥:
cat ~/.ssh/id_ed25519.pub步骤2:将公钥复制到服务器
方法A — ssh-copy-id(推荐)
ssh-copy-id工具自动处理目录创建、文件追加和权限设置:
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@your_vps_ip出现提示时输入您的密码。该工具将密钥追加到远程服务器上的~/.ssh/authorized_keys并设置正确的权限。这是最安全的方法,因为它可以防止意外覆盖现有密钥。
方法B — 手动部署
当ssh-copy-id不可用时使用此方法(例如,在某些Windows环境或受限网络中):
cat ~/.ssh/id_ed25519.pub | ssh root@your_vps_ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"这个单一管道比在远程服务器上打开文本编辑器更安全,因为它是追加而非覆盖。
方法C — 通过文本编辑器手动操作(备用方案)
使用密码登录服务器:
ssh root@your_vps_ip如果.ssh目录不存在,请创建它:
mkdir -p ~/.ssh
chmod 700 ~/.ssh在文本编辑器中打开authorized_keys:
nano ~/.ssh/authorized_keys在新行上粘贴您的公钥。按Ctrl+X保存,然后按Y,再按Enter。设置权限:
chmod 600 ~/.ssh/authorized_keys退出会话:
exit步骤3:验证基于密钥的登录
在对SSH守护进程进行任何进一步更改之前测试连接。打开一个新的终端窗口(暂时不要关闭现有会话):
ssh -i ~/.ssh/id_ed25519 root@your_vps_ip如果您无需密码提示即可连接,则密钥正在工作。仅在确认此操作后才继续执行下面的强化步骤。
关键陷阱:如果您在验证密钥访问之前禁用密码认证,而密钥部署由于任何原因失败,您将把自己锁定在外。请务必先测试。
步骤4:强化SSH守护进程配置
确认基于密钥的访问后,打开SSH守护进程配置文件:
nano /etc/ssh/sshd_config应用以下设置:
PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin prohibit-password
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
UsePAM yes关于这些指令的重要说明:
PermitRootLogin prohibit-password允许通过密钥进行root登录,但阻止root密码登录——在您仍在设置非root sudo用户时,这比PermitRootLogin no是更好的折中方案。ChallengeResponseAuthentication no禁用键盘交互式认证,这在某些PAM配置中可以绕过PasswordAuthentication no。- 在Ubuntu 22.04+上,文件
/etc/ssh/sshd_config.d/50-cloud-init.conf可能会覆盖您的设置。如有必要,请检查并编辑它。
在重启之前验证配置语法:
sshd -t如果未报告错误,请重启SSH服务:
systemctl restart sshd在使用ssh.service而非sshd.service的系统上:
systemctl restart ssh管理多个SSH密钥和用户
现实环境中很少只涉及单个密钥和单个用户。以下是处理更复杂场景的方法。
为多个用户添加密钥
每个用户账户都有自己的~/.ssh/authorized_keys文件。要为名为deploy的非root用户添加密钥:
mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
echo "ssh-ed25519 AAAAC3... deploy@ci-server" >> /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.sshchown步骤经常被遗漏,会导致认证失败——SELinux和OpenSSH都会验证authorized_keys文件是否由认证用户拥有。
限制密钥的操作权限
您可以在authorized_keys中的任何行前添加选项以限制其功能。这对于部署密钥或备份自动化特别有用:
command="/usr/bin/rsync --server --daemon .",no-pty,no-agent-forwarding,no-X11-forwarding ssh-ed25519 AAAAC3... backup@monitoring此密钥只能以守护进程模式运行rsync——不能执行其他任何操作。
使用~/.ssh/config实现更简洁的连接
与其输入冗长的ssh命令,不如在本地计算机上定义主机别名:
Host myserver
HostName 203.0.113.45
User root
IdentityFile ~/.ssh/id_ed25519
Port 22将此内容保存到~/.ssh/config后,只需使用以下命令连接:
ssh myserver使用ssh-agent缓存密码短语
如果您的私钥有密码短语(应该有),请将其添加到代理中,这样就不会反复提示您输入:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519在macOS上,添加--apple-use-keychain以在重启后持久保存:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519常见陷阱与故障排除
问题:添加密钥后仍提示输入密码
使用详细输出运行连接以进行诊断:
ssh -vvv root@your_vps_ip查找类似Offering public key和Server accepts key的行。如果密钥已提供但被拒绝,问题几乎总是服务器上的文件权限。
检查服务器上的权限:
ls -la ~/.ssh/
stat ~/.ssh/authorized_keys所需权限:
~/.ssh/—700(drwx——)~/.ssh/authorized_keys—600(-rw——-)- 主目录
~/— 不得对所有人可写(755或750)
问题:SELinux在RHEL/Rocky/AlmaLinux上阻止认证
restorecon -Rv ~/.ssh问题:authorized_keys文件有Windows行尾(CRLF)
如果您在Windows上编辑了文件并传输,行尾可能已损坏。使用以下命令修复:
sed -i 's/r//' ~/.ssh/authorized_keys问题:提供了错误的密钥
如果您有多个密钥,请明确指定正确的密钥:
ssh -i ~/.ssh/id_ed25519 root@your_vps_ip或如上所示在~/.ssh/config中配置它。
SSH密钥在托管基础设施中的应用
SSH密钥认证不仅仅是单服务器的问题——它可以扩展到整个基础设施。如果您管理一批独立服务器,使用Ansible、Puppet或密钥管理器(HashiCorp Vault、AWS Secrets Manager)等工具集中分发和轮换授权密钥至关重要。
对于在带cPanel的VPS上运行Web应用程序的团队,cPanel安全部分下的SSH访问界面提供了用于生成和管理密钥对的图形界面——对于不熟悉命令行但仍需要安全访问的开发人员非常有用。
如果您在GPU托管基础设施上运行GPU密集型工作负载,SSH密钥认证尤为关键,因为这些实例通常运行长期无人值守的任务。GPU服务器上的凭据泄露除了数据暴露外,还可能导致大量未经授权的计算费用。
将SSH强化与同一服务器上运行的任何面向Web服务的有效SSL证书配合使用,可同时关闭两个最常见的攻击向量——未经认证的Shell访问和未加密的HTTP流量。
对于使用共享虚拟主机同时需要SSH访问的项目,请检查您的提供商是否支持通过托管面板注入SSH密钥,因为共享环境通常将SSH限制为具有有限Shell访问权限的特定用户。
密钥轮换与长期密钥管理
SSH密钥不会自动过期。没有轮换策略,多年前泄露的密钥可能仍然可以授予访问权限。建立以下实践:
- 每年轮换密钥,或在怀疑泄露时立即轮换。
- 定期审计所有服务器上的
authorized_keys文件。删除属于前员工或已停用服务的密钥。 - 每台设备使用独立密钥——不要将同一私钥复制到多台笔记本电脑或服务器。如果某台设备丢失,您只需撤销该密钥。
- 每个角色使用独立密钥——您的个人访问密钥、CI/CD部署密钥和备份自动化密钥应该各不相同。
- 记录密钥所有权——维护一个注册表,将每个公钥指纹映射到其所有者、用途和到期日期。
显示密钥指纹以进行审计:
ssh-keygen -lf ~/.ssh/id_ed25519.pub技术决策检查清单
在最终确定SSH密钥设置之前,请使用此矩阵:
- 算法:使用Ed25519,除非连接到OpenSSH 6.5之前的系统;使用RSA 4096作为备用方案。
- 密码短语:始终为人类使用的私钥设置密码短语;如果存储在密钥管理器中,自动化使用的服务密钥可以省略。
- 部署方法:交互式设置使用
ssh-copy-id;批量部署使用配置管理工具(Ansible、Puppet)。 - 权限验证:在禁用密码认证之前,确认
700对~/.ssh/,600对authorized_keys,以及正确的所有权。 - 锁定前先测试:在设置
PasswordAuthentication no之前,始终在单独的终端会话中验证密钥登录。 - 守护进程配置验证:在重启SSH服务之前运行
sshd -t以捕获语法错误。 - 禁用密码认证:同时设置
PasswordAuthentication no和ChallengeResponseAuthentication no——在启用PAM的系统上,单独设置其中一个是不够的。 - Root登录策略:优先选择
PermitRootLogin prohibit-password而非PermitRootLogin yes;迁移到非root sudo用户,并将PermitRootLogin no设置为最终强化状态。 - 密钥轮换:安排每年轮换;设备丢失或人员变动时立即撤销。
- 审计:定期运行
grep -r "" /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys以审查系统中所有授权密钥。
常见问题
我可以向同一台服务器添加多个SSH密钥吗?
可以。~/.ssh/authorized_keys中的每一行代表一个授权的公钥。您可以根据需要添加任意数量的密钥——每行一个。这允许多个管理员或多台设备独立进行认证,您可以通过删除某行来撤销任何单个密钥,而不影响其他密钥。
如果我在禁用密码认证后丢失了私钥会怎样?
您将被锁定在SSH之外。恢复需要通过带外方式访问服务器:您的托管提供商的Web控制台、VNC或救援/恢复启动环境。从那里您可以重新启用密码认证或添加新的公钥。这就是为什么保持控制台访问凭据安全且独立至关重要。
Ed25519在所有服务器上都受支持吗?
Ed25519需要OpenSSH 6.5或更高版本,该版本于2014年1月发布。任何运行现代Linux发行版(Ubuntu 18.04+、Debian 9+、CentOS 7+、Rocky Linux 8+)的服务器都支持它。唯一需要RSA的场景是连接到真正的旧版系统或具有过时OpenSSH版本的嵌入式设备。
添加SSH密钥会自动禁用密码登录吗?
不会。将密钥添加到authorized_keys会启用基于密钥的登录,但不会禁用密码认证。您必须在/etc/ssh/sshd_config中明确设置PasswordAuthentication no并重启SSH守护进程,才能强制执行仅密钥访问。
我可以在多台服务器上使用同一个SSH密钥对吗?
技术上可以,但不建议在生产环境中这样做。在多台服务器上使用单个密钥意味着泄露一个私钥就会授予对所有服务器的访问权限。更好的做法是使用每台设备独立的密钥(每台工作站或笔记本电脑一个密钥),这样丢失设备只需在服务器群中撤销该密钥,而不必同时在所有地方替换密钥。
