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

SSH暴力破解频发时,CentOS香港服务器如何设置防火墙与登录告警?

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

在香港服务器的 CentOS 系统上处理 SSH 暴力破解,不能只依赖“换一个端口”或单纯封禁 IP。更稳妥的状态应当是:管理账号使用 SSH 密钥登录,禁止不必要的密码和 root 远程登录;firewalld 只放行明确需要的来源和端口;Fail2ban 或同类机制对重复失败进行临时封禁;成功登录、失败次数和配置变更都能在日志中追溯,并通过邮件或现有告警通道通知管理员。

实施时应先保留一个已验证可用的 SSH 会话,再从备份、密钥登录、防火墙、动态封禁、登录告警和审计几个层面逐步修改。每次调整后都要使用 sshd -t、新终端登录测试和 firewall-cmd 查询结果进行验证,确认新密钥能够登录后,才能关闭密码认证或 root 登录。

全文开篇与实施原则配图

一、实施前的准备条件

1. 确认 CentOS 和 SSH 当前状态

先通过控制台或现有 SSH 会话执行以下命令。CentOS 7 通常使用 yum,CentOS 8、CentOS Stream 通常同时提供 dnf 兼容命令。

cat /etc/centos-release
uname -r
rpm -q openssh-server openssh-clients firewalld audit fail2ban 2>/dev/null || true
systemctl status sshd --no-pager
systemctl status firewalld --no-pager

确认 SSH 正在监听的端口、绑定地址和当前防火墙区域:

ss -lntp | grep -E '(:22|sshd)'
firewall-cmd --get-active-zones
firewall-cmd --get-default-zone
firewall-cmd --zone=public --list-all

如果实际使用的不是 public 区域,应把后续命令中的 public 替换为 firewall-cmd --get-active-zones 输出的实际区域。

查看 SSH 的有效配置时,不要只看配置文件中的某一行。CentOS 可能加载了 /etc/ssh/sshd_config.d/ 下的配置,sshd -T 才能反映最终生效值:

sshd -T | egrep '^(port|listenaddress|permitrootlogin|passwordauthentication|pubkeyauthentication|usepam|maxauthtries|logingracetime|allowusers|allowgroups|x11forwarding|allowtcpforwarding)'

2. 备份将要修改的文件

防火墙、PAM 和 SSH 配置修改错误,都可能影响远程登录。先建立带时间标记的备份目录:

BACKUP_DIR="/root/ssh-hardening-backup-$(date +%F-%H%M%S)"
mkdir -p "$BACKUP_DIR"

cp -a /etc/ssh/sshd_config "$BACKUP_DIR/"
cp -a /etc/pam.d/sshd "$BACKUP_DIR/"
cp -a /etc/firewalld "$BACKUP_DIR/"
cp -a /etc/fail2ban "$BACKUP_DIR/" 2>/dev/null || true

chmod 700 "$BACKUP_DIR"
echo "$BACKUP_DIR"

不要在没有控制台、备用 SSH 会话或带外管理入口的情况下,同时修改 SSH 认证和防火墙。防火墙规则生效后,当前已建立的连接通常不会立即中断,但不能把这一点当成远程恢复手段。

3. 确定管理来源和账号

提前记录以下信息:

  • 管理员当前公网出口 IP,或者固定的办公网段;
  • 计划用于远程管理的普通账号;
  • 是否存在备份、监控、自动化部署等需要 SSH 的账号;
  • SSH 是否必须支持端口转发、TTY、SFTP 或 X11;
  • 新防火墙规则需要放行的业务端口。

如果管理出口 IP 经常变化,不要直接把 SSH 限制为单个 /32 地址,否则网络切换后可能把自己挡在服务器外。此时应优先使用密钥认证、Fail2ban 和较小的管理入口范围。

二、先建立 SSH 密钥登录

1. 在管理端生成密钥

在管理员自己的电脑上执行,不要在服务器上生成并把私钥下载到本地:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519_hk

命令会要求设置私钥口令。私钥应只保存在管理员设备或受控的密钥管理位置,不要上传到网站目录、代码仓库或服务器公共目录。

将公钥复制到服务器上的普通管理账号。下面的 opsadmin、服务器地址和端口仅为示例:

ssh-copy-id -i ~/.ssh/id_ed25519_hk.pub opsadmin@SERVER_IP

如果服务器暂时没有 ssh-copy-id,可以先在服务器上准备权限,再通过安全方式写入公钥:

install -d -m 700 -o opsadmin -g opsadmin /home/opsadmin/.ssh

将公钥内容追加到 /home/opsadmin/.ssh/authorized_keys 后,设置权限:

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

restorecon 用于恢复 SELinux 上下文。若系统没有该命令,应先确认 policycoreutils 是否安装,而不是随意关闭 SELinux。

2. 验证密钥后再关闭密码

使用新的终端窗口测试密钥登录,不要复用已经登录的旧会话:

ssh -i ~/.ssh/id_ed25519_hk opsadmin@SERVER_IP

登录后确认管理员具备必要的提权权限:

sudo -l
sudo id

如果管理账号需要使用 sudo,应加入受控的 wheel 组,并通过 visudo 检查配置:

usermod -aG wheel opsadmin
visudo

不要在没有业务需要时添加无限制的 NOPASSWD: ALL。如果自动化任务确实需要免密码提权,应限制到具体命令,并单独使用服务账号和密钥。

确认新会话可以登录、可以执行必要的 sudo 操作后,再修改 /etc/ssh/sshd_config。不要机械地在文件末尾重复追加同一个配置项,应先查找现有配置和 Include 关系:

grep -RniE '^(Include|Port|PermitRootLogin|PasswordAuthentication|PubkeyAuthentication|UsePAM|MaxAuthTries|AllowUsers|AllowGroups)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d 2>/dev/null

常见的安全基线可以调整为:

PubkeyAuthentication yes
PasswordAuthentication no
PermitRootLogin no
PermitEmptyPasswords no
UsePAM yes
MaxAuthTries 3
LoginGraceTime 30
LogLevel VERBOSE
X11Forwarding no

其中:

  • PasswordAuthentication no 禁止使用普通密码认证;
  • PermitRootLogin no 禁止 root 直接通过 SSH 登录;
  • MaxAuthTries 3 限制单次连接的认证尝试次数;
  • LoginGraceTime 30 将未完成认证的连接等待时间限制为 30 秒;
  • X11Forwarding no 适用于不需要图形转发的服务器;
  • LogLevel VERBOSE 便于记录密钥指纹等登录信息,但会增加日志内容。

CentOS 7 常见的键盘交互配置项是:

ChallengeResponseAuthentication no

较新的 OpenSSH 版本可能使用:

KbdInteractiveAuthentication no

不要在未验证版本的情况下盲目添加不支持的配置项。修改后先检查:

sshd -t

检查无误后,使用平滑重载:

systemctl reload sshd

再从第三个终端验证:

ssh -i ~/.ssh/id_ed25519_hk opsadmin@SERVER_IP

确认密钥登录正常后,可以验证密码认证是否已被拒绝:

ssh -o PubkeyAuthentication=no \
    -o PreferredAuthentications=password \
    opsadmin@SERVER_IP

预期结果应为认证失败,而不是登录成功。最后再验证 root:

ssh -i ~/.ssh/id_ed25519_hk root@SERVER_IP

如果 root 仍然可以登录,说明配置文件存在覆盖项、Match 条件或配置没有加载成功,应先查看:

sshd -T -C user=root,addr=203.0.113.10,host=example | grep -E 'permitrootlogin|passwordauthentication'

三、是否更换 SSH 端口

将 SSH 从 22 端口改为其他端口,只能减少低质量的自动扫描,不能替代密钥登录和失败封禁。攻击者可以通过端口探测找到新端口,因此不要把换端口当成主要防护措施。

如果确实需要使用 2222,应按以下顺序操作:

  1. 先在 firewalld 中放行新端口;
  2. 如果启用了 SELinux,为新端口添加 ssh_port_t;
  3. 修改 SSH 配置并验证;
  4. 使用新端口建立独立 SSH 会话;
  5. 确认成功后,再考虑移除 22 端口。

先放行防火墙端口:

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

查询 SELinux 当前允许的 SSH 端口:

semanage port -l | grep ssh_port_t

如果系统没有 semanage,CentOS 7 通常需要确认 policycoreutils-python,CentOS 8 或更新版本通常需要确认 policycoreutils-python-utils。安装前先检查当前仓库,不要为了换端口关闭 SELinux。

端口不存在时可使用:

semanage port -a -t ssh_port_t -p tcp 2222

如果该端口已经存在但类型不正确,使用修改命令:

semanage port -m -t ssh_port_t -p tcp 2222

然后将 SSH 配置中的端口调整为:

Port 2222

验证并重载:

sshd -t
systemctl reload sshd
ss -lntp | grep ':2222'

从另一台机器测试:

ssh -p 2222 -i ~/.ssh/id_ed25519_hk opsadmin@SERVER_IP

确认新端口可用后,才能移除旧端口。若原来使用的是 firewalld 的 SSH 服务定义:

firewall-cmd --permanent --zone=public --remove-service=ssh
firewall-cmd --reload

如果原来使用的是显式端口规则,则删除对应端口:

firewall-cmd --permanent --zone=public --remove-port=22/tcp
firewall-cmd --reload

四、使用 firewalld 限制 SSH 入口

1. 先确认区域和当前规则

firewalld 的规则属于具体区域。先查看活动区域:

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

如果 SSH 使用默认 22 端口,确认运行时和永久规则都放行:

firewall-cmd --zone=public --add-service=ssh
firewall-cmd --permanent --zone=public --add-service=ssh

如果使用 2222 端口,不要添加 ssh 服务,因为该服务通常代表 22 端口,应使用:

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

修改永久配置后执行:

firewall-cmd --reload

--add-service 或 --add-port 不会自动关闭其他已经放行的端口。应检查完整结果,确认没有遗留不必要的管理端口:

四、使用 firewalld 限制 SSH 入口配图

firewall-cmd --zone=public --list-all

2. 固定管理 IP 时使用来源限制

如果管理员有固定公网地址,例如示例地址 203.0.113.10/32,可以只允许该来源访问 SSH。以下命令以 22 端口为例:

firewall-cmd --permanent --zone=public --remove-service=ssh

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

firewall-cmd --reload

如果 SSH 使用 2222 端口:

firewall-cmd --permanent --zone=public --remove-port=2222/tcp

firewall-cmd --permanent --zone=public \
  --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="2222" protocol="tcp" accept'

firewall-cmd --reload

查询结果:

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

这类规则的优点是外部扫描基本无法触达 SSH 服务;边界是管理员出口地址变化后会立即失去远程访问。动态办公网络、移动网络或多地运维场景,不宜只依赖单个 /32 地址。

3. 不要用过度宽泛的规则“补救”

以下做法容易产生误配置:

  • 直接执行 iptables -F 或清空 firewalld 规则;
  • 把默认区域改成完全放行;
  • 为了排查问题临时关闭 firewalld 后忘记恢复;
  • 只开放新端口,却没有确认旧端口是否仍在监听;
  • 把业务端口和 SSH 端口全部开放到公网。

如果必须临时恢复远程入口,应只在控制台上临时放行指定端口,完成修复后再写入或删除永久规则:

firewall-cmd --zone=public --add-port=22/tcp

该命令只改变运行时配置。修复结束后应根据实际策略执行:

firewall-cmd --zone=public --remove-port=22/tcp

五、用 Fail2ban 对重复失败进行临时封禁

防火墙静态规则适合限制管理来源,Fail2ban 适合处理来源不固定的重复攻击。它会读取 SSH 认证失败日志,在指定时间窗口内达到阈值后,通过 firewalld 添加临时封禁规则。

五、用 Fail2ban 对重复失败进行临时封禁配图

Fail2ban 不应替代密钥认证。分布式攻击可以从多个 IP 各尝试少量次数,单个 IP 的封禁效果会下降。

1. 安装和确认日志来源

先确认软件仓库是否提供当前 CentOS 版本可用的 Fail2ban 包:

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

只有在仓库和软件包来源已确认的情况下再安装:

dnf install fail2ban

CentOS 7 环境可使用:

yum install fail2ban

确认 SSH 失败日志:

journalctl -u sshd --since "1 hour ago" --no-pager | \
  grep -E 'Failed password|Invalid user|authentication failure'

grep -E 'Failed password|Invalid user|authentication failure' \
  /var/log/secure 2>/dev/null | tail -n 20

如果 /var/log/secure 持续记录 SSH 日志,可以使用文件后端;如果系统主要依赖 journald,则使用 systemd 后端。两者不要同时配置成互相重复读取。

2. 配置基础封禁策略

备份配置后创建本地配置文件:

cp -a /etc/fail2ban/jail.local \
  /root/jail.local.before-ssh-hardening 2>/dev/null || true

touch /etc/fail2ban/jail.local
chmod 600 /etc/fail2ban/jail.local

使用 /var/log/secure 时,可以参考以下配置:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = firewallcmd-rich-rules
ignoreip = 127.0.0.1/8 203.0.113.10/32

[sshd]
enabled = true
port = 22
logpath = /var/log/secure

如果 SSH 使用 2222 端口,将 port = 22 改为:

port = 2222

如果系统没有可靠的 /var/log/secure,可改用 journald 后端:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = firewallcmd-rich-rules
ignoreip = 127.0.0.1/8 203.0.113.10/32

[sshd]
enabled = true
port = 22
backend = systemd

ignoreip 中只能加入可信、稳定的管理地址。不要把整个公网地址段加入白名单,否则攻击者一旦获得该范围内的地址,Fail2ban 将无法保护 SSH。

启动并设置开机运行:

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

查看当前封禁地址:

fail2ban-client get sshd banip
firewall-cmd --zone=public --list-rich-rules

不要在生产服务器上用脚本连续制造大量错误密码来测试封禁,这可能触发自身防护、污染审计日志或误封管理出口。应通过配置检查、状态查询和受控测试 IP 验证。

3. 将封禁事件接入邮件告警

Fail2ban 的邮件动作依赖本机邮件程序和可用的本地 MTA 或 SMTP 中继。没有邮件发送链路时,配置收件地址并不会产生实际通知。

在已经配置好邮件发送能力的前提下,可在 jail.local 的 [DEFAULT] 中增加:

destemail = security@example.com
sender = root@your-server.example
action = %(action_mw)s

其中地址需要替换为实际安全收件地址。重启后查看配置是否被接受:

fail2ban-client -d >/tmp/fail2ban-debug.txt
systemctl restart fail2ban
fail2ban-client status sshd

如果邮件不可用,至少应保留 Fail2ban 的服务日志和封禁状态,并通过已有的系统监控读取:

journalctl -u fail2ban --since "1 hour ago" --no-pager

六、配置成功登录告警

1. 先确保本地日志正常

CentOS 上可以从 journald 或 /var/log/secure 查看 SSH 事件:

journalctl -u sshd --since today --no-pager | \
  grep -E 'Accepted|Failed password|Invalid user'

grep -E 'Accepted|Failed password|Invalid user' \
  /var/log/secure 2>/dev/null | tail -n 50

常见日志含义如下:

日志关键词含义处理方向
Accepted publickey密钥认证成功核对用户、来源 IP 和密钥指纹
Accepted password密码认证成功如果策略要求密钥登录,应检查配置是否未生效
Failed password密码认证失败结合来源 IP 判断是否为暴力尝试
Invalid user用户不存在大量出现时通常是扫描或账号枚举
authentication failurePAM 或认证流程失败结合用户、来源和 SELinux 日志继续判断

2. 使用 PAM 在成功建立 SSH 会话时记录并通知

如果需要每次成功 SSH 登录都触发告警,可以使用 pam_exec。先创建脚本:

cat > /usr/local/sbin/ssh-login-alert <<'EOF'
#!/bin/bash
set -u

TO="security@example.com"
HOST="$(hostname -s)"
USER_NAME="${PAM_USER:-unknown}"
REMOTE="${PAM_RHOST:-unknown}"
TTY_NAME="${PAM_TTY:-unknown}"
NOW="$(date '+%F %T %z')"

MESSAGE="host=${HOST} user=${USER_NAME} remote=${REMOTE} tty=${TTY_NAME} time=${NOW}"

# 无论邮件是否可用,先写入本机日志
logger -t ssh-login-alert -- "$MESSAGE"

# 邮件只是附加通知,失败不能阻断 SSH 登录
if command -v s-nail >/dev/null 2>&1; then
    printf '%s\n' "$MESSAGE" | \
      timeout 8 s-nail -s "[SSH] successful login ${HOST}" "$TO" \
      || logger -t ssh-login-alert -- "mail notification failed"
elif command -v mailx >/dev/null 2>&1; then
    printf '%s\n' "$MESSAGE" | \
      timeout 8 mailx -s "[SSH] successful login ${HOST}" "$TO" \
      || logger -t ssh-login-alert -- "mail notification failed"
else
    logger -t ssh-login-alert -- "mail client not found"
fi

exit 0
EOF

chown root:root /usr/local/sbin/ssh-login-alert
chmod 750 /usr/local/sbin/ssh-login-alert

将 security@example.com 换成实际收件地址。CentOS 7 常见邮件客户端命令为 mailx,较新的系统可能使用 s-nail。邮件客户端本身仍需要本地 MTA 或 SMTP 中继支持。

备份 PAM 配置:

cp -a /etc/pam.d/sshd \
  /root/sshd.pam.before-login-alert

在 /etc/pam.d/sshd 的 session 部分加入:

session optional pam_exec.so type=open_session /usr/local/sbin/ssh-login-alert

这里使用 optional,表示告警脚本失败时不应阻断正常登录。修改后不要立即关闭当前 SSH 会话,应先从另一台机器建立新会话,验证:

六、配置成功登录告警配图

journalctl -t ssh-login-alert --since "10 minutes ago" --no-pager

如果能看到用户、来源地址和时间,说明 PAM 脚本已执行。邮件是否到达还要单独检查本机邮件队列和 SMTP 中继。

这种方式的适用边界是“成功建立 SSH 会话时告警”。它不能替代失败尝试统计,也不能覆盖控制台登录、业务程序登录或所有 sudo 行为。失败尝试应由 journald、/var/log/secure 和 Fail2ban 负责记录与封禁。

七、启用审计,记录配置和权限变化

如果服务器需要更完整的追溯,应启用 auditd。它主要用于保留证据,不是实时告警系统。

dnf install audit
systemctl enable --now auditd
systemctl status auditd --no-pager

CentOS 7 可使用:

yum install audit
systemctl enable --now auditd

创建针对 SSH、权限和账号文件的审计规则:

cat > /etc/audit/rules.d/ssh-hardening.rules <<'EOF'
-w /etc/ssh/sshd_config -p wa -k ssh_config
-w /etc/ssh/sshd_config.d/ -p wa -k ssh_config
-w /etc/sudoers -p wa -k privilege_config
-w /etc/sudoers.d/ -p wa -k privilege_config
-w /etc/passwd -p wa -k identity_config
-w /etc/group -p wa -k identity_config
EOF

augenrules --load

查询规则:

auditctl -l | grep -E 'ssh_config|privilege_config|identity_config'

查看 SSH 登录和账号认证记录:

ausearch -m USER_LOGIN -ts today -i
aureport -au -ts today

如果系统开启了不可变审计规则,augenrules --load 可能不会立即接受新规则,需要在维护窗口重启后加载。不要为了临时修改规则而删除审计策略。

八、最小权限和补丁不能省略

1. 限制 SSH 可登录账号

确认服务器上哪些账号确实需要 SSH:

awk -F: '$7 !~ /(nologin|false)$/ {print $1 ":" $7}' /etc/passwd

如果账号数量少,可以在 SSH 配置中使用白名单:

AllowUsers opsadmin backupuser

如果账号按组管理,可以使用:

AllowGroups sshusers

使用 AllowUsers 或 AllowGroups 前,必须把所有合法运维账号列入清单,否则会造成批量锁定。备份、部署和监控账号也要分别确认其密钥、来源和命令权限。

不需要交互式登录的服务账号,应考虑使用:

usermod -s /sbin/nologin serviceuser

该命令会影响该账号的交互式 Shell,不能用于仍需要执行登录脚本的账号。修改前应确认业务依赖,并保留回滚方式。

2. 及时更新 SSH 和系统安全组件

先查看当前版本:

rpm -q openssh-server openssh-clients openssl firewalld

在维护窗口中更新系统。CentOS 8 或更新版本:

dnf update

CentOS 7:

yum update

更新范围、重启需求和仓库来源应结合实际维护制度确定。涉及 openssh-server、openssl 或内核的更新,应保留当前 SSH 会话,并准备控制台入口。更新后检查:

systemctl status sshd --no-pager
sshd -t
ss -lntp | grep sshd
journalctl -u sshd -b --no-pager | tail -n 50

补丁只能修复已知缺陷,不能替代账号权限控制和网络入口限制。

九、结果验证与常见失败处理

1. 外部连接失败

先检查服务器是否仍在监听目标端口:

ss -lntp | grep -E '(:22|:2222).*sshd'

再检查防火墙实际区域:

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

如果服务在监听但外部无法连接,通常是以下原因之一:

  • 规则加到了错误的 firewalld 区域;
  • SSH 端口已修改,但防火墙仍只放行旧端口;
  • SELinux 没有允许新端口;
  • 云平台或上游访问控制没有放行该端口;
  • 管理出口 IP 不在允许列表中。

不要第一时间清空防火墙。优先通过控制台临时放行明确端口,再修正永久规则。

2. Permission denied (publickey)

检查账号目录和密钥权限:

namei -l /home/opsadmin/.ssh/authorized_keys
ls -ld /home/opsadmin /home/opsadmin/.ssh
ls -l /home/opsadmin/.ssh/authorized_keys
restorecon -Rv /home/opsadmin/.ssh

服务端查看最近一次失败原因:

journalctl -u sshd -n 100 --no-pager

客户端使用详细模式确认实际使用的密钥:

ssh -vvv -i ~/.ssh/id_ed25519_hk opsadmin@SERVER_IP

重点检查用户名、私钥路径、公钥内容是否完整、authorized_keys 所属用户是否正确,以及 AllowUsers、AllowGroups 是否排除了该账号。

3. 修改后密码和密钥都无法登录

通过控制台恢复备份配置,或临时恢复密码认证:

PasswordAuthentication yes

然后检查并重载:

sshd -t
systemctl reload sshd

恢复访问后,应先修复密钥、权限或配置覆盖问题,再次验证密钥登录,最后重新关闭密码认证。不要在无法确认密钥可用时长期保留密码认证。

4. 管理 IP 被 Fail2ban 封禁

先通过控制台或其他可信会话查询:

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

解除指定地址的封禁:

fail2ban-client set sshd unbanip 203.0.113.10

如果误封是因为出口地址变化,应调整 ignoreip,但只加入明确可信的地址,不要直接关闭整个 jail:

vi /etc/fail2ban/jail.local
systemctl restart fail2ban

5. 能登录但没有邮件告警

先确认本机日志脚本是否执行:

journalctl -t ssh-login-alert --since "30 minutes ago" --no-pager

再确认邮件程序:

command -v s-nail
command -v mailx

手动发送一封测试邮件:

printf 'SSH alert test\n' | mailx -s 'SSH alert test' security@example.com

如果命令执行但收不到邮件,应检查本机 MTA、SMTP 中继、DNS、邮件队列和收件策略。邮件系统故障不应阻断 SSH 登录,因此脚本中的超时和 optional 设置不要删除。

十、回滚方式

SSH 回滚时,先恢复配置文件,再执行语法检查,最后重载服务:

cp -a /root/ssh-hardening-backup-YYYY-MM-DD-HHMMSS/sshd_config \
  /etc/ssh/sshd_config

sshd -t
systemctl reload sshd

PAM 告警导致登录异常时,恢复原文件:

cp -a /root/sshd.pam.before-login-alert /etc/pam.d/sshd

防火墙回滚前先查看当前规则,避免误删业务端口:

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

如果需要恢复此前的完整 firewalld 配置,应在确认备份目录路径后恢复:

systemctl stop firewalld
cp -a /root/ssh-hardening-backup-YYYY-MM-DD-HHMMSS/firewalld/. /etc/firewalld/
systemctl start firewalld
firewall-cmd --reload

回滚 Fail2ban 时,优先停用 SSH jail,而不是清空整个 firewalld:

fail2ban-client stop sshd

如果只是误封单个地址,应使用 unbanip,不要执行会影响其他业务的全局防火墙清空命令。

上线验收清单

  • [ ] 已通过第二个独立终端验证 SSH 密钥登录。
  • [ ] 管理账号可以正常执行必要的 sudo 操作。
  • [ ] sshd -t 返回无错误。
  • [ ] sshd -T 显示 PasswordAuthentication no。
  • [ ] sshd -T 显示 PermitRootLogin no。
  • [ ] 未使用的 SSH 端口没有继续监听。
  • [ ] firewalld 活动区域正确,SSH 规则位于正确区域。
  • [ ] 固定管理 IP 已加入白名单,动态出口没有被错误限制。
  • [ ] Fail2ban 的 sshd jail 状态为正常运行。
  • [ ] 管理地址已加入合理的 ignoreip,且没有误放行过大的网段。
  • [ ] 成功登录能在 journalctl -t ssh-login-alert 中留下记录。
  • [ ] 邮件或既有告警通道已经完成测试。
  • [ ] auditd 正在运行,SSH 和权限配置变更规则已加载。
  • [ ] 已保存 SSH、PAM 和 firewalld 配置备份。
  • [ ] 已明确控制台或带外管理入口,能够处理误封和远程锁定。
  • [ ] SSH、OpenSSL、firewalld 等关键组件已纳入后续补丁计划。