最稳妥的做法是先生成密钥对并测试密钥登录成功,再关闭密码认证,适合所有需要远程管理的 Linux 服务器。
先说结论:批量修复的核心是“先通密钥,后禁密码”,避免把自己锁在门外。
- 先判断:确认云厂商 VNC 控制台或物理 IPMI 权限可用,这是最后的救命通道。
- 优先做:在所有目标机器上部署公钥并验证密钥登录可用,必须通过 sshd -t 配置检查。
- 再验证:修改配置关闭密码登录后,务必保留一个会话不要断开,新开窗口测试。
- 留后路:修改配置前备份原文件,确保可快速回滚。
前置检查:确保有备用控制台
在进行任何 SSH 配置修改前,必须确认拥有服务器的带外管理权限。如果密钥配置错误导致 SSH 服务无法启动或拒绝连接,只有控制台能挽救服务器。
- 云服务器:登录云控制台,确认“远程连接”或“VNC 登录”功能可用。
- 物理服务器:确认 IPMI/iDRAC/ILO 管理口可达。
- 权限确认:确保当前登录用户有 sudo 权限,且知道 root 密码(以防 sudo 配置异常)。
单机配置流程(基准测试)
批量操作前,务必先在一台测试机上跑通全流程,确认无误后再推广。
1. 生成密钥对
在管理机(本地电脑)上执行。推荐使用 ed25519 算法,安全性高且生成快。
ssh-keygen -t ed25519 -C "your_email@example.com"
# 默认保存在 ~/.ssh/id_ed25519,私钥切勿泄露
2. 分发公钥
将公钥写入服务器的 ~/.ssh/authorized_keys。
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server_ip
# 此步骤需要服务器当前允许密码登录
3. 备份配置文件(关键)
修改前务必备份,以便出错时快速还原。
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
4. 修改 SSH 配置
使用 sed 修改配置,同时覆盖注释和未注释的情况,并确保配置语法正确。
# 禁用密码认证(兼容注释和未注释行)
sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
# 允许公钥认证
sudo sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
# 建议禁止 root 密码登录,允许密钥
sudo sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
5. 检查配置语法(防启动失败)
重启服务前必须检查配置文件语法,防止因格式错误导致 SSH 服务无法启动。
sudo sshd -t
# 若无输出则表示配置正确;若有报错,请立即还原备份
6. 重载服务
确认语法无误后重启服务。
sudo systemctl restart sshd
批量自动化部署实战
针对多台服务器,建议使用脚本或配置管理工具,避免人工操作失误。
方案一:Shell 循环脚本
将服务器 IP 列入 ips.txt,每行一个 IP。
#!/bin/bash
USER="root"
KEY_FILE="~/.ssh/id_ed25519.pub"
while read -r IP; do
echo "Processing $IP..."
# 1. 分发密钥
ssh-copy-id -i $KEY_FILE $USER@$IP
# 2. 备份并修改配置
ssh $USER@$IP "sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak"
ssh $USER@$IP "sudo sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config"
# 3. 检查配置并重启
ssh $USER@$IP "sudo sshd -t && sudo systemctl restart sshd"
if [ $? -eq 0 ]; then
echo "[SUCCESS] $IP"
else
echo "[FAILED] $IP - 请检查控制台"
fi
done < ips.txt
方案二:Ansible Playbook
适合大规模集群管理,具备幂等性。
- name: Secure SSH Configuration
hosts: all
become: yes
tasks:
- name: Backup sshd_config
copy:
src: /etc/ssh/sshd_config
dest: /etc/ssh/sshd_config.bak
remote_src: yes
force: no
- name: Disable Password Authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
state: present
- name: Validate SSH Config
command: sshd -t
changed_when: false
ignore_errors: yes
register: sshd_test
- name: Restart SSHD
service:
name: sshd
state: restarted
when: sshd_test.rc == 0
验证与日志检查
1. 保持当前会话
在执行重启命令后,不要关闭当前已经登录的 SSH 窗口。这是你的救命通道。
2. 新开窗口测试密钥
打开一个新的终端窗口,尝试连接:
ssh -i ~/.ssh/id_ed25519 user@server_ip
# 不需要输入密码直接登录即为成功
3. 测试密码登录(应失败)
尝试强制使用密码认证,应该被拒绝:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@server_ip
# 应提示 Permission denied (publickey)
4. 查看日志
检查 /var/log/secure (CentOS) 或 /var/log/auth.log (Ubuntu),确认没有异常报错。
sudo tail -f /var/log/secure
# 观察登录尝试记录
故障应急回滚方案
如果修改配置后无法连接 SSH,请立即通过云控制台或物理终端登录服务器执行回滚。
1. 恢复配置文件
sudo cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
sudo systemctl restart sshd
2. 检查服务状态
sudo systemctl status sshd
# 确认服务处于 active (running) 状态
3. 排查权限问题
如果密钥仍无法登录,检查服务器端权限:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
常见坑与注意事项
1. 把自己锁在门外
这是最大的风险。如果密钥没配好就关了密码,且没有云厂商的 VNC 控制台权限,服务器就无法访问了。务必先测试密钥登录成功,再改配置。
2. 配置语法错误导致服务启动失败
修改 sshd_config 后必须执行 sshd -t。如果直接重启且配置有误,SSH 服务将无法启动,导致所有连接断开。
3. Root 权限设置冲突
PermitRootLogin 如果设置为 no,即使有密钥也无法用 root 登录。建议设置为 prohibit-password,普通用户登录后再 sudo 提权更安全。
4. 文件权限问题
SSH 对权限非常敏感。服务器上的 ~/.ssh 目录权限应为 700,authorized_keys 文件应为 600。权限过宽会导致密钥登录失败。
5. 批量操作时的顺序
批量修复时,不要一次性重启所有服务器。建议分批次,先改一台,验证无误后再推广到其余机器,每批次间隔观察。