SSH 密钥登录配置全流程指南-将服务器的密码登录改为密钥登录,提升安全性,防止暴力破解攻击

5 阅读9分钟

SSH 密钥登录配置全流程指南

将服务器的密码登录改为密钥登录,提升安全性,防止暴力破解攻击。


📋 目录

  1. 整体流程概览
  2. [第一步:生成 SSH 密钥对](#第一步生成 ssh 密钥对)
  3. 第二步:将公钥部署到服务器
  4. 第三步:测试密钥登录
  5. 第四步:禁用密码登录
  6. 第五步:验证配置
  7. 常见问题与解决
  8. 最佳实践

整体流程概览

┌─────────────┐    ┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│  生成密钥对  │ →  │ 部署公钥到服务器 │ →  │ 测试密钥登录 │ →  │ 禁用密码登录 │
│  (本地电脑)  │    │  (线上服务器)  │    │  (验证成功)  │    │  (安全加固)  │
└─────────────┘    └─────────────┘    └─────────────┘    └─────────────┘

⚠️ 重要提醒:

  • 不要关闭当前 SSH 会话,直到新终端测试密钥登录成功
  • 配置错误时,可用当前会话恢复,避免被锁在服务器外

第一步:生成 SSH 密钥对

Mac / Linux

# 1. 检查是否已有密钥
ls -la ~/.ssh/

# 2. 生成新密钥(推荐 Ed25519,更安全)
ssh-keygen -t ed25519 -C "your_email@example.com"

# 或生成 RSA 密钥(兼容旧系统)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# 3. 按提示操作
# - 保存路径:直接回车(默认 ~/.ssh/id_ed25519)
# -  passphrase:建议设置(增加安全性)或回车跳过

输出示例:

Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/yourname/.ssh/id_ed25519): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/yourname/.ssh/id_ed25519
Your public key has been saved in /Users/yourname/.ssh/id_ed25519.pub

Windows(PowerShell 或 CMD)

# 1. 检查是否已有密钥
dir ~\.ssh\

# 2. 生成新密钥
ssh-keygen -t ed25519 -C "your_email@example.com"

# 3. 按提示操作(同上)

生成的文件

文件说明权限
~/.ssh/id_ed25519私钥(保密,不要分享)600
~/.ssh/id_ed25519.pub公钥(可公开,部署到服务器)644

查看公钥内容

cat ~/.ssh/id_ed25519.pub
# 输出示例:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... your_email@example.com

第二步:将公钥部署到服务器

方法一:使用 ssh-copy-id(Mac / Linux 推荐)

# 标准 SSH 端口(22)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname

# 自定义端口(如 12222)
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 12222 user@hostname

# 或指定 SSH 选项
ssh-copy-id -i ~/.ssh/id_ed25519.pub -o "Port=12222" user@hostname

参数说明:

  • -i:指定公钥文件路径
  • -p:SSH 端口号(放在主机名之前)
  • user@hostname:服务器用户名和 IP

方法二:使用 ssh-copy-id(Windows Git Bash)

如果安装了 Git Bash:

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

方法三:手动部署(通用方法)

1. 复制公钥内容

本地电脑:

cat ~/.ssh/id_ed25519.pub
# 复制输出内容,如:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
2. 登录服务器并配置

登录服务器(使用密码):

ssh user@hostname -p 12222

在服务器上执行:

# 1. 创建 .ssh 目录
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# 2. 添加公钥(粘贴刚才复制的内容)
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI..." >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

# 3. 修复权限(CentOS/RHEL 可能需要)
restorecon -R -v ~/.ssh 2>/dev/null || true

# 4. 验证文件内容
cat ~/.ssh/authorized_keys

第三步:测试密钥登录

⚠️ 关键步骤

不要关闭当前 SSH 会话! 新开一个终端窗口测试。

Mac / Linux 测试

# 标准端口
ssh -i ~/.ssh/id_ed25519 user@hostname

# 自定义端口
ssh -i ~/.ssh/id_ed25519 -p 12222 user@hostname

Windows(PowerShell / Git Bash)测试

# 标准端口
ssh -i ~/.ssh/id_ed25519 user@hostname

# 自定义端口
ssh -i ~/.ssh/id_ed25519 -p 12222 user@hostname

成功标志

  • 直接登录成功,不需要输入密码
  • 如果设置了 passphrase,会提示输入 passphrase(不是服务器密码)

失败排查

# 使用详细模式查看连接过程
ssh -v -i ~/.ssh/id_ed25519 -p 12222 user@hostname

# 查看服务器日志(需要另一个能登录的会话)
sudo tail -f /var/log/auth.log        # Ubuntu/Debian
sudo tail -f /var/log/secure          # CentOS/RHEL

第四步:禁用密码登录

Ubuntu / Debian

# 1. 备份原配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# 2. 修改配置(使用 sed 自动替换)
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config

# 3. 确认配置
sudo grep -E "^(PubkeyAuthentication|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config

# 4. 重启 SSH 服务
sudo systemctl restart sshd

# 5. 检查服务状态
sudo systemctl status sshd --no-pager

CentOS / RHEL

# 1. 备份原配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

# 2. 修改配置(使用 sed 自动替换)
sudo sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/^#*PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config

# 3. 确认配置
sudo grep -E "^(PubkeyAuthentication|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config

# 4. 重启 SSH 服务
sudo systemctl restart sshd

# 5. 检查服务状态
sudo systemctl status sshd --no-pager

配置项说明

配置项推荐值说明
PubkeyAuthenticationyes启用公钥认证
PasswordAuthenticationno禁用密码认证
PermitRootLoginprohibit-password禁止 root 密码登录,允许密钥登录

手动编辑配置(可选)

如果 sed 命令不生效,可手动编辑:

sudo vi /etc/ssh/sshd_config
# 或
sudo nano /etc/ssh/sshd_config

确保以下配置(取消注释并修改):

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin prohibit-password
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
UsePAM yes

第五步:验证配置

测试 1:密钥登录(应该成功)

ssh -i ~/.ssh/id_ed25519 -p 12222 user@hostname

预期: 直接登录成功

测试 2:密码登录(应该被拒绝)

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no -p 12222 user@hostname

预期:

user@hostname: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

测试 3:查看服务器日志

Ubuntu / Debian:

sudo grep "sshd" /var/log/auth.log | tail -20

CentOS / RHEL:

sudo grep "sshd" /var/log/secure | tail -20

成功标志:

  • 新连接日志显示 Connection closed by ... [preauth]
  • 没有 Failed password 记录(密码认证在验证前就被拒绝)

常见问题与解决

问题 1:密钥登录失败,仍然提示输入密码

可能原因:

  1. 公钥未正确部署到服务器
  2. 权限设置错误
  3. SSH 配置未生效

解决步骤:

# 1. 检查服务器上的 authorized_keys
ssh user@hostname
cat ~/.ssh/authorized_keys

# 2. 检查权限
ls -la ~/.ssh/
# 应该是:drwx------ .ssh 和 -rw------- authorized_keys

# 3. 修复权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# 4. 检查 SSH 配置
sudo grep -E "^(PubkeyAuthentication|PasswordAuthentication)" /etc/ssh/sshd_config

# 5. 重启 SSH
sudo systemctl restart sshd

问题 2:ssh-copy-id 报错 "Too many arguments"

原因: 参数顺序错误

错误示例:

ssh-copy-id -i ~/.ssh/id_ed25519.pub user@hostname -p 12222  # ❌ 错误

正确示例:

ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 12222 user@hostname  # ✅ 正确
# 或
ssh-copy-id -i ~/.ssh/id_ed25519.pub -o "Port=12222" user@hostname  # ✅ 正确

问题 3:CentOS 7 SELinux 阻止密钥登录

症状: 权限正确但仍无法登录

解决:

# 1. 检查 SELinux 状态
getenforce

# 2. 修复安全上下文
restorecon -R -v ~/.ssh

# 3. 或临时禁用 SELinux 测试
sudo setenforce 0

问题 4:防火墙阻止 SSH 连接

Ubuntu:

sudo ufw allow 22/tcp
# 或自定义端口
sudo ufw allow 12222/tcp

CentOS:

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-port=12222/tcp
sudo firewall-cmd --reload

问题 5:被锁在服务器外

紧急恢复:

  1. 通过云服务商控制台(阿里云/腾讯云/AWS)使用 VNC 登录
  2. 恢复备份配置:
    sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
    sudo systemctl restart sshd
    
  3. 重新检查配置

最佳实践

1. 使用强密钥

  • 优先使用 Ed25519(更安全、更快)
  • RSA 密钥至少 4096 位
  • 设置 passphrase 保护私钥

2. 密钥管理

# 为不同服务器生成不同密钥
ssh-keygen -t ed25519 -C "work-server" -f ~/.ssh/id_ed25519_work
ssh-keygen -t ed25519 -C "home-server" -f ~/.ssh/id_ed25519_home

# 配置 SSH config 简化登录
vi ~/.ssh/config

SSH config 示例:

# 工作服务器
Host work
    HostName 121.41.109.44
    Port 12222
    User root
    IdentityFile ~/.ssh/id_ed25519_work

# 家庭服务器
Host home
    HostName 192.168.1.100
    User ubuntu
    IdentityFile ~/.ssh/id_ed25519_home

使用:

ssh work    # 自动使用对应密钥
ssh home

3. 禁用 root 登录(可选)

# 修改 /etc/ssh/sshd_config
PermitRootLogin no

# 创建普通用户并授权
sudo adduser admin
sudo usermod -aG sudo admin  # Ubuntu
sudo usermod -aG wheel admin # CentOS

4. 配置 fail2ban(防止暴力破解)

Ubuntu:

sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

CentOS:

sudo yum install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

5. 定期轮换密钥

# 生成新密钥
ssh-keygen -t ed25519 -C "new-key-2026" -f ~/.ssh/id_ed25519_new

# 部署到服务器
ssh-copy-id -i ~/.ssh/id_ed25519_new user@hostname

# 测试成功后,从 authorized_keys 删除旧公钥

6. 备份私钥

# 备份到安全位置(加密 U 盘、密码管理器等)
cp ~/.ssh/id_ed25519 /mnt/secure_backup/
cp ~/.ssh/id_ed25519.pub /mnt/secure_backup/

# 设置严格权限
chmod 600 /mnt/secure_backup/id_ed25519

快速检查清单

  • 已生成 SSH 密钥对(Ed25519 或 RSA 4096)
  • 公钥已部署到服务器 ~/.ssh/authorized_keys
  • 服务器权限正确(.ssh 700,authorized_keys 600)
  • 密钥登录测试成功(新开终端验证)
  • SSH 配置已修改(PasswordAuthentication no
  • SSH 服务已重启
  • 密码登录测试被拒绝
  • 当前 SSH 会话保持打开直到验证完成
  • 已备份 SSH 配置文件

附录:各系统默认路径

系统SSH 配置文件日志文件重启命令
Ubuntu 20.04+/etc/ssh/sshd_config/var/log/auth.logsystemctl restart sshd
Debian 10+/etc/ssh/sshd_config/var/log/auth.logsystemctl restart sshd
CentOS 7/8/etc/ssh/sshd_config/var/log/securesystemctl restart sshd
RHEL 7/8/etc/ssh/sshd_config/var/log/securesystemctl restart sshd