上一篇 下一篇 分享链接 返回 返回顶部

香港服务器CentOS如何配置SSH密钥登录?含权限检查与回滚步骤

发布人:Minchunlin 发布时间:2026-10-05 08:15 阅读量:36

在香港服务器的 CentOS 7、CentOS Stream 8/9 上,SSH 密钥登录的安全上线顺序是:先保留当前 SSH 会话,创建或确认具备 sudo 权限的管理账号,生成并安装公钥,修正目录与文件权限,验证新终端可以使用密钥登录,再关闭密码认证,最后通过 sshd -t、日志和第二个终端完成验收。

密钥登录本身不能阻止所有 SSH 连接,但关闭密码认证、禁止 root 直接登录、限制认证尝试次数,并配合 firewalld 与 Fail2ban,可以显著减少密码爆破风险。整个过程中不要先关闭当前连接,也不要在未验证密钥登录前直接执行 systemctl restart sshd。

一、适用环境与上线目标

本文适用于以下环境:

项目适用范围或参考值
操作系统CentOS 7、CentOS Stream 8/9
SSH 服务OpenSSH Server,服务名通常为 sshd
服务管理systemd,使用 systemctl 管理服务
防火墙firewalld,可选配 Fail2ban
客户端Linux、macOS、Windows OpenSSH Client
登录目标使用普通运维账号的 Ed25519 密钥登录
安全目标禁用密码认证,减少 root 直接登录和重复爆破

CentOS 7 与 CentOS Stream 8/9 的 SSH 配置项大体一致,但交互式认证配置项可能存在差异。开始修改前,应先核对系统版本、OpenSSH 版本、当前 SSH 端口和登录账号。

1. 保留当前管理会话

使用 SSH 连接服务器后,不要关闭当前终端。后续即使新配置导致密钥登录失败,仍可以利用当前会话回滚配置。

建议同时准备以下一种备用入口:

  • 云平台或服务器管理面板提供的 Web 控制台;
  • 独立的串口、VNC 或救援终端;
  • 已经验证可以使用密钥登录的第二个管理账号。

如果当前只有 root 密码登录,先创建普通管理账号并安装密钥,确认普通账号可用后,再禁用 root 直接登录。

2. 检查系统、服务和端口

以下命令在服务器端执行:

cat /etc/centos-release
uname -r
ssh -V
sudo systemctl status sshd --no-pager
sudo ss -lntp | grep -E 'sshd|:22'

不同结果的含义如下:

  • 能看到 sshd 服务处于 active (running),表示 SSH 服务正在运行;
  • ss -lntp 显示 0.0.0.0:22 或 [::]:22,表示服务监听 22 端口;
  • 如果监听的是其他端口,后续客户端连接时需要使用 -p 端口号;
  • 如果服务未运行,不要急于修改认证策略,应先确认当前 SSH 服务能正常启动。

检查当前生效的认证配置:

sudo sshd -T | grep -E '^(port|pubkeyauthentication|passwordauthentication|kbdinteractiveauthentication|challengeresponseauthentication|permitrootlogin|authorizedkeysfile|maxauthtries|logingracetime)'

sshd -T 会解析主配置及其包含文件,结果比单纯查看某一行配置更接近 SSH 服务实际使用的值。

3. 确认管理账号和 sudo 权限

如果已经有可用的普通运维账号,可以跳过创建步骤,直接确认账号信息:

id opsadmin
getent passwd opsadmin
sudo -l -U opsadmin

没有账号时,可以在当前 root 或具备 sudo 权限的会话中创建:

sudo useradd -m -s /bin/bash opsadmin
sudo usermod -aG wheel opsadmin
id opsadmin

CentOS 通常通过 wheel 组授予 sudo 权限,但具体权限仍应以 /etc/sudoers 和 /etc/sudoers.d/ 中的配置为准。确认账号能正常使用密钥登录、并能执行必要的 sudo 命令后,才适合关闭 root 直接登录。

二、在本地生成 SSH 密钥

密钥应在自己的管理电脑上生成。私钥只保存在本地,不要上传到服务器,不要通过工单、聊天工具或网页表单传递。

1. Linux 或 macOS 客户端

在本地终端执行:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_hk -C "opsadmin@hk-server"

参数说明:

  • -t ed25519:使用 Ed25519 算法;
  • -a 100:增加私钥口令的 KDF 计算轮数,降低私钥文件泄露后的离线猜测效率;
  • -f:指定密钥文件名,避免覆盖已有的默认密钥;
  • -C:添加便于识别的注释,不参与认证。

执行后会提示输入私钥口令。建议设置口令,即使私钥文件被复制,也不能直接使用。

生成结果通常包括:

~/.ssh/id_ed25519_hk       # 私钥,只保存在本地
~/.ssh/id_ed25519_hk.pub   # 公钥,可以写入服务器

检查文件权限:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519_hk
chmod 644 ~/.ssh/id_ed25519_hk.pub

查看公钥内容时,只查看 .pub 文件:

cat ~/.ssh/id_ed25519_hk.pub

公钥应当是单行文本,通常以 ssh-ed25519 开头。私钥文件不要执行 cat,也不要将私钥内容粘贴到服务器。

2. Windows 客户端

Windows 10/11 通常已经包含 OpenSSH Client。可以在 PowerShell 中执行:

ssh-keygen -t ed25519 -a 100 -f "$env:USERPROFILE\.ssh\id_ed25519_hk" -C "opsadmin@hk-server"

公钥文件通常位于:

C:\Users\当前用户名\.ssh\id_ed25519_hk.pub

可以使用以下命令查看公钥:

Get-Content "$env:USERPROFILE\.ssh\id_ed25519_hk.pub"

如果提示找不到 ssh-keygen,需要先在 Windows 的“可选功能”中安装 OpenSSH Client,或使用已有的 OpenSSH 环境。不要为了生成密钥而把私钥上传到服务器。

三、将公钥安装到 CentOS 服务器

1. 使用 ssh-copy-id 安装

如果客户端存在 ssh-copy-id,可以执行:

ssh-copy-id -i ~/.ssh/id_ed25519_hk.pub opsadmin@服务器IP

如果 SSH 使用非 22 端口:

ssh-copy-id -i ~/.ssh/id_ed25519_hk.pub -p 端口号 opsadmin@服务器IP

该命令通常会要求输入一次当前账号密码,然后将公钥追加到服务器的:

/home/opsadmin/.ssh/authorized_keys

如果登录账号是 root,则文件通常位于:

/root/.ssh/authorized_keys

但生产运维更建议将密钥安装到普通管理账号,而不是长期使用 root 直接登录。

2. 没有 ssh-copy-id 时手动追加公钥

在本地执行以下命令,将公钥通过当前可用的 SSH 会话追加到服务器:

cat ~/.ssh/id_ed25519_hk.pub | ssh opsadmin@服务器IP \
'umask 077; mkdir -p ~/.ssh; cat >> ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys'

如果当前只能使用 root 登录,也可以先追加到目标账号,但需要确保路径和属主正确:

cat ~/.ssh/id_ed25519_hk.pub | ssh root@服务器IP \
'umask 077; mkdir -p /home/opsadmin/.ssh; cat >> /home/opsadmin/.ssh/authorized_keys; chown -R opsadmin:opsadmin /home/opsadmin/.ssh; chmod 700 /home/opsadmin/.ssh; chmod 600 /home/opsadmin/.ssh/authorized_keys'

这类追加操作可能造成同一公钥重复出现。重复通常不影响登录,但会增加后续审计难度。正式上线前应检查 authorized_keys,删除重复或不再使用的密钥。

3. 检查公钥是否完整

在服务器端执行:

sudo wc -l /home/opsadmin/.ssh/authorized_keys
sudo sed -n '1,5p' /home/opsadmin/.ssh/authorized_keys

每个公钥必须独占一行,不能因为复制换行、少字符或多出不可见字符而被拆开。可以在本地查看公钥指纹:

ssh-keygen -lf ~/.ssh/id_ed25519_hk.pub

服务器上的 authorized_keys 应包含相同的公钥内容或相同的指纹。

四、检查目录、文件和 SELinux 权限

SSH 服务默认会执行严格权限检查。如果家目录、.ssh 目录或 authorized_keys 对其他用户可写,sshd 可能拒绝使用公钥登录。

1. 查看路径上每一级目录的权限

服务器端执行:

四、检查目录、文件和 SELinux 权限配图

namei -l /home/opsadmin/.ssh/authorized_keys

重点检查:

  • /home/opsadmin 的属主应为 opsadmin 或符合实际账号设计;
  • /home/opsadmin/.ssh 通常应为 700;
  • authorized_keys 通常应为 600;
  • .ssh 和 authorized_keys 的属主、属组应属于目标登录账号;
  • 家目录不应被其他用户或组写入。

查看详细状态:

sudo stat -c '%A %a %U:%G %n' \
/home/opsadmin \
/home/opsadmin/.ssh \
/home/opsadmin/.ssh/authorized_keys

典型的安全结果类似:

drwx------ 700 opsadmin:opsadmin /home/opsadmin/.ssh
-rw------- 600 opsadmin:opsadmin /home/opsadmin/.ssh/authorized_keys

2. 修正密钥目录权限

确认路径确实属于目标账号后,可以执行:

sudo chown -R opsadmin:opsadmin /home/opsadmin/.ssh
sudo chmod 700 /home/opsadmin/.ssh
sudo chmod 600 /home/opsadmin/.ssh/authorized_keys

如果家目录被设置为组或其他用户可写,应先记录原始权限,再根据实际业务需要修正。常见修正方式如下:

sudo chmod go-w /home/opsadmin

不要对整个 /home 目录执行递归权限修改,也不要在不了解业务权限的情况下使用 chmod -R 777。权限变更范围应限定在目标账号的 SSH 目录。

3. 修正 SELinux 文件标签

检查 SELinux 状态和文件上下文:

getenforce
ls -Zd /home/opsadmin /home/opsadmin/.ssh /home/opsadmin/.ssh/authorized_keys

如果 SELinux 处于 Enforcing,或者公钥内容和权限都正确但仍然无法登录,可以恢复默认上下文:

sudo restorecon -Rv /home/opsadmin/.ssh

再检查是否有 SELinux 拒绝记录:

sudo ausearch -m avc -ts recent

restorecon 只恢复安全标签,不会改变文件内容。若目录是通过特殊挂载、网络文件系统或自定义路径提供,还需要根据实际路径配置相应的 SELinux 上下文,不能简单复制其他目录的标签。

五、先验证密钥登录,再关闭密码认证

1. 使用新终端验证公钥登录

保持原有 SSH 会话不动,在本地打开第二个终端,执行:

五、先验证密钥登录,再关闭密码认证配图

ssh -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  opsadmin@服务器IP

如果 SSH 使用其他端口:

ssh -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  -p 端口号 \
  opsadmin@服务器IP

登录后执行:

whoami
hostname
id

预期结果应显示目标账号为 opsadmin,主机名和用户组信息与服务器实际情况一致。

为了确认客户端没有偷偷使用其他密钥,可以开启详细日志:

ssh -vv \
  -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  opsadmin@服务器IP

日志中通常可以看到类似信息:

Offering public key: /home/local/.ssh/id_ed25519_hk
Server accepts key
Authentication succeeded (publickey)

示例仅用于说明判断方式,不代表某台服务器的实际执行记录。

2. 为 SSH 配置文件做备份

在服务器端执行:

sudo cp -a /etc/ssh/sshd_config \
  /etc/ssh/sshd_config.bak.$(date +%Y%m%d%H%M%S)

sudo ls -l /etc/ssh/sshd_config.bak.*

如果系统通过 Include 引用了其他配置目录,也应一并确认:

sudo grep -nE '^[[:space:]]*Include|^[[:space:]]*(Port|PubkeyAuthentication|PasswordAuthentication|PermitRootLogin)' \
  /etc/ssh/sshd_config /etc/ssh/sshd_config.d/* 2>/dev/null

不要直接把一整段配置无条件追加到文件末尾。OpenSSH 配置中重复项可能导致实际生效值与预期不同。应先搜索已有配置,修改原有项,或者确认包含文件的加载顺序后再新增配置。

3. 第一阶段只启用公钥,不立即关闭密码

在已经确认新账号可以使用公钥登录后,先将 SSH 配置调整为安全过渡状态:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication yes
PermitRootLogin prohibit-password
MaxAuthTries 3
LoginGraceTime 30
UsePAM yes

其中:

  • PubkeyAuthentication yes:允许公钥认证;
  • AuthorizedKeysFile:指定公钥文件位置;
  • PasswordAuthentication yes:过渡阶段保留密码认证,便于回滚;
  • PermitRootLogin prohibit-password:root 不允许密码登录,但仍允许 root 使用密钥;
  • MaxAuthTries 3:限制单次连接的认证尝试次数;
  • LoginGraceTime 30:限制连接建立后停留在认证阶段的时间;
  • UsePAM yes:保留 CentOS 常用的 PAM 账号策略。

修改后先检查语法:

sudo sshd -t -f /etc/ssh/sshd_config

没有任何输出通常表示语法检查通过。出现错误时不要 reload,先根据错误行号修正。

4. 验证配置并平滑加载

确认语法通过后,使用 reload 而不是直接重启:

sudo systemctl reload sshd
sudo systemctl status sshd --no-pager

reload 会让新连接使用新配置,通常不会主动断开已经建立的 SSH 会话。检查生效值:

sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|permitrootlogin|maxauthtries|logingracetime|usepam)'

然后再次从第二个本地终端测试:

ssh -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  opsadmin@服务器IP 'whoami && hostname'

5. 第二阶段关闭密码认证

确认以下条件全部满足后,再关闭密码认证:

五、先验证密钥登录,再关闭密码认证配图

  • 新建的普通账号可以使用密钥登录;
  • 当前 root 或旧账号会话仍然保持连接;
  • 新账号具有所需的 sudo 权限;
  • 已经保存了 sshd_config 备份;
  • 已确认 SSH 端口和防火墙状态;
  • 至少有一种控制台或备用登录方式。

修改为:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no
PermitRootLogin no
MaxAuthTries 3
LoginGraceTime 30
UsePAM yes

CentOS 7 常见的交互式认证配置项为:

ChallengeResponseAuthentication no

CentOS Stream 8/9 可以检查并设置:

KbdInteractiveAuthentication no

可以先查看系统是否识别某个配置项:

sudo sshd -T | grep -Ei 'kbdinteractiveauthentication|challengeresponseauthentication'

如果 sshd -t 报告 Bad configuration option,删除不被当前 OpenSSH 版本识别的配置项,只保留该版本支持的对应项。不要为了套用其他系统的配置而强行保留未知参数。

修改后执行:

sudo sshd -t -f /etc/ssh/sshd_config
sudo systemctl reload sshd
sudo sshd -T | grep -E '^(pubkeyauthentication|passwordauthentication|permitrootlogin)'

预期结果应包含:

pubkeyauthentication yes
passwordauthentication no
permitrootlogin no

再次使用新终端验证:

ssh -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  -o PasswordAuthentication=no \
  -o KbdInteractiveAuthentication=no \
  opsadmin@服务器IP

还可以测试禁用密码后的结果:

ssh -o BatchMode=yes \
  -o PreferredAuthentications=password \
  -o PubkeyAuthentication=no \
  opsadmin@服务器IP 'true'

该命令预期返回非零状态,并出现认证失败信息。测试时不要反复尝试,以免触发 Fail2ban 或其他封禁规则。

六、检查 firewalld 与 SSH 端口

关闭密码认证后,仍需确保防火墙允许合法的 SSH 连接。先查看活动区域:

sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones

假设实际活动区域是 public,检查已开放服务:

sudo firewall-cmd --zone=public --list-services
sudo firewall-cmd --zone=public --list-ports

如果 SSH 使用默认 22 端口且 ssh 服务尚未开放,可以执行:

sudo firewall-cmd --zone=public --permanent --add-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-services

如果当前使用自定义端口,应以 sshd -T 的 port 结果为准,例如:

sudo firewall-cmd --zone=public --permanent --add-port=2222/tcp
sudo firewall-cmd --reload

防火墙规则变更前应确认区域名称和实际监听端口。不要在远程会话中直接删除当前 SSH 端口,也不要在没有控制台的情况下同时修改 SSH 端口、SELinux 和 firewalld,否则很容易造成远程失联。

固定管理地址时限制 SSH 来源

如果运维出口拥有固定公网 IP,可以将 SSH 访问限制为指定地址。以下地址 203.0.113.10/32 只是文档示例,实际操作时必须替换为真实管理出口地址:

sudo firewall-cmd --zone=public --permanent \
  --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" service name="ssh" accept'

确认新规则已经加入并且从该地址测试成功后,再考虑移除面向所有来源的 ssh 服务规则:

sudo firewall-cmd --zone=public --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-all

管理出口地址经常变化时,不建议直接采用这类白名单,否则可能因为出口变化而无法登录。密钥认证和 Fail2ban 应作为主要控制措施,非标准端口只能减少部分自动化扫描,不能替代密钥认证。

七、使用 Fail2ban 限制重复爆破

密钥登录可以阻止密码猜测成功,但攻击者仍可能持续建立 SSH 连接。Fail2ban 会读取 SSH 失败日志,在指定时间内失败次数超过阈值时,通过 firewalld 临时封禁来源地址。

1. 安装软件包

CentOS 7 使用 yum,CentOS Stream 8/9 使用 dnf。软件包名称和仓库可用性应以当前系统仓库为准。

CentOS 7 示例:

sudo yum install -y epel-release
sudo yum install -y fail2ban

CentOS Stream 8/9 示例:

sudo dnf install -y epel-release
sudo dnf install -y fail2ban

如果软件包无法找到,不要随意添加来源不明的第三方仓库。可以先检查仓库和软件包信息:

sudo yum repolist
sudo yum info fail2ban 2>/dev/null || sudo dnf info fail2ban

如果无法安装 Fail2ban,仍然可以通过“密钥登录、关闭密码认证、禁止 root 直接登录、限制认证次数”完成基础防护。

2. 配置 SSH 监控规则

先确认 CentOS 是否有 SSH 安全日志:

sudo ls -l /var/log/secure

如果文件存在,可创建配置文件:

sudo install -d -m 755 /etc/fail2ban/jail.d
sudo vi /etc/fail2ban/jail.d/sshd.local

写入以下内容:

[sshd]
enabled = true
port = ssh
backend = auto
logpath = /var/log/secure
maxretry = 5
findtime = 10m
bantime = 1h
banaction = firewallcmd-rich-rules
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

参数含义:

  • maxretry = 5:在统计窗口内失败 5 次后封禁;
  • findtime = 10m:统计最近 10 分钟的失败记录;
  • bantime = 1h:首次封禁 1 小时;
  • ignoreip:不封禁本机、回环地址和固定管理出口;
  • banaction:使用 firewalld rich rule 执行封禁。

其中 203.0.113.10 仍是示例地址,应替换为真实管理出口;如果管理出口不固定,不要把不确定的地址加入白名单。

如果系统没有 /var/log/secure,而 SSH 日志主要由 journald 保存,可以将配置调整为:

[sshd]
enabled = true
port = ssh
backend = systemd
maxretry = 5
findtime = 10m
bantime = 1h
banaction = firewallcmd-rich-rules
ignoreip = 127.0.0.1/8 ::1 203.0.113.10

不要同时保留不适用的 logpath。选择配置后先进行检查:

sudo fail2ban-client -t

检查通过后启动并设置开机启动:

sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager
sudo fail2ban-client status
sudo fail2ban-client status sshd

正常情况下可以看到 sshd jail,以及当前失败次数和封禁数量。

3. 处理误封管理地址

如果管理出口被误封,必须从未被封禁的终端或控制台执行:

sudo fail2ban-client set sshd unbanip 203.0.113.10

查看当前封禁状态:

sudo fail2ban-client status sshd
sudo firewall-cmd --zone=public --list-rich-rules

Fail2ban 的封禁时长、失败阈值应结合实际运维情况调整。阈值过低可能误伤共享出口、办公网络或自动化任务,阈值过高则会降低对重复扫描的抑制效果。

八、按日志定位常见失败

1. Permission denied (publickey)

先在本地确认使用的是正确私钥和账号:

ssh -vv \
  -i ~/.ssh/id_ed25519_hk \
  -o IdentitiesOnly=yes \
  opsadmin@服务器IP

服务器端同步查看日志:

sudo journalctl -u sshd -n 100 --no-pager
sudo tail -n 100 /var/log/secure

重点排查:

sudo namei -l /home/opsadmin/.ssh/authorized_keys
sudo stat -c '%A %U:%G %n' /home/opsadmin/.ssh /home/opsadmin/.ssh/authorized_keys
sudo restorecon -Rv /home/opsadmin/.ssh

常见原因包括:

  • 连接时使用了错误的账号;
  • 私钥与服务器上的公钥不是一对;
  • authorized_keys 被换行或内容不完整;
  • .ssh 或 authorized_keys 权限过宽;
  • 文件属主不是目标账号;
  • SELinux 标签不正确;
  • AuthorizedKeysFile 被改成了其他路径;
  • Fail2ban 已封禁当前出口地址。

2. Connection refused

检查 SSH 服务和监听端口:

sudo systemctl status sshd --no-pager
sudo ss -lntp | grep sshd
sudo sshd -T | grep '^port '

如果修改配置后服务没有重新加载,先检查语法:

sudo sshd -t -f /etc/ssh/sshd_config

Connection refused 通常表示目标主机可以到达,但该端口没有服务监听,或服务主动拒绝连接,不应优先从密钥权限入手。

3. 连接超时

检查 firewalld 当前区域和规则:

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=public --list-all

确认客户端使用的端口与 sshd -T 输出一致,并检查是否因为来源白名单或 Fail2ban 规则而被拒绝。远程修改防火墙时必须保留当前会话或使用控制台,避免在错误区域上删除 SSH 访问规则。

4. 关闭密码后仍然出现密码提示

检查最终生效配置,而不是只查看配置文件中某一行:

sudo sshd -T | grep -Ei 'passwordauthentication|kbdinteractiveauthentication|challengeresponseauthentication|authenticationmethods'

可能原因包括:

  • PasswordAuthentication 仍为 yes;
  • KbdInteractiveAuthentication 或 ChallengeResponseAuthentication 仍允许交互式认证;
  • 配置文件存在重复项或 Include 文件覆盖;
  • 客户端使用了旧的连接复用会话;
  • 实际连接到了另一台服务器或另一个端口。

可以在本地强制只使用公钥:

ssh -o IdentitiesOnly=yes \
  -o PasswordAuthentication=no \
  -o KbdInteractiveAuthentication=no \
  -i ~/.ssh/id_ed25519_hk \
  opsadmin@服务器IP

5. sshd -t 检查失败

不要执行 reload 或 restart。记录报错行号后恢复最近一次备份,或者只撤销最近修改的配置项:

sudo ls -lt /etc/ssh/sshd_config.bak.*

恢复后再次检查:

sudo cp -a /etc/ssh/sshd_config.bak.时间戳 /etc/ssh/sshd_config
sudo sshd -t -f /etc/ssh/sshd_config

备份文件名中的“时间戳”需要替换为实际文件名,不能直接照抄。

九、上线验收检查

完成部署后,建议按以下顺序验收:

  1. 从新终端使用指定私钥登录普通管理账号。
  2. 确认 whoami、hostname、id 输出正确。
  3. 确认普通账号能够执行所需的 sudo 操作。
  4. 确认 sshd -t 返回成功。
  5. 确认 systemctl status sshd 为运行状态。
  6. 确认 sshd -T 显示 pubkeyauthentication yes。
  7. 确认 passwordauthentication no。
  8. 确认 permitrootlogin no,或仍处于明确评估过的过渡状态。
  9. 确认 firewalld 开放的是实际 SSH 端口和实际活动区域。
  10. 确认 Fail2ban 的 sshd jail 已启用,且管理出口未被封禁。
  11. 确认 /home/账号/.ssh 为 700,authorized_keys 为 600,属主正确。
  12. 确认已保存 SSH 配置备份和密钥变更记录。

可以使用以下命令进行集中复核:

sudo sshd -t
sudo systemctl is-active sshd
sudo sshd -T | grep -E '^(port|pubkeyauthentication|passwordauthentication|permitrootlogin|maxauthtries)'
sudo firewall-cmd --get-active-zones
sudo fail2ban-client status sshd 2>/dev/null || true

十、失败时的回滚步骤

1. SSH 服务仍可通过当前会话操作

先不要退出当前会话。找到最近的配置备份:

sudo ls -lt /etc/ssh/sshd_config.bak.*

恢复指定备份:

sudo cp -a /etc/ssh/sshd_config.bak.实际时间戳 /etc/ssh/sshd_config
sudo sshd -t -f /etc/ssh/sshd_config
sudo systemctl reload sshd

如果只是误关闭密码认证,也可以进行定向回滚,将以下配置恢复为过渡状态:

PubkeyAuthentication yes
PasswordAuthentication yes
PermitRootLogin prohibit-password

然后执行:

sudo sshd -t -f /etc/ssh/sshd_config
sudo systemctl reload sshd

只有语法检查通过后才 reload。不要直接执行 systemctl restart sshd 作为第一步。

2. 回滚错误或失效的公钥

先备份当前文件:

sudo cp -a /home/opsadmin/.ssh/authorized_keys \
  /home/opsadmin/.ssh/authorized_keys.bak.$(date +%Y%m%d%H%M%S)

使用编辑器删除对应的单行公钥:

sudoedit /home/opsadmin/.ssh/authorized_keys

不要根据模糊的用户名或注释批量删除,最好依据本地公钥指纹和完整密钥内容确认目标行。删除后重新检查权限:

sudo chown opsadmin:opsadmin /home/opsadmin/.ssh/authorized_keys
sudo chmod 600 /home/opsadmin/.ssh/authorized_keys
sudo restorecon -v /home/opsadmin/.ssh/authorized_keys

3. 回滚 Fail2ban

如果 Fail2ban 配置导致误封或服务启动失败,可以先停止服务:

sudo systemctl disable --now fail2ban

然后检查 firewalld 中是否还残留由 Fail2ban 产生的临时规则:

sudo firewall-cmd --zone=public --list-rich-rules

不要直接清空整个 firewalld 配置。只删除能够确认属于 Fail2ban、且不会影响正常 SSH 访问的临时规则。完成后确认 SSH 端口仍然开放。

4. 已经失去 SSH 连接时

如果所有 SSH 会话都断开,应使用服务器控制台或救援终端:

  1. 登录控制台;
  2. 检查 SSH 配置备份;
  3. 恢复最近一次可用的 sshd_config;
  4. 执行 sshd -t;
  5. 重新加载 sshd;
  6. 检查 .ssh 目录属主和权限;
  7. 检查 firewalld 和 Fail2ban 是否封禁管理出口;
  8. 使用第二个终端验证恢复结果。

回滚的核心原则是:保留当前会话、先恢复配置、再验证语法、最后 reload;不要通过删除整个 .ssh 目录或清空防火墙规则来处理单一故障。这样既能恢复 SSH 密钥登录,也能避免把原有的访问控制和其他服务规则一并破坏。