前言

一台公网服务器上线几小时,/var/log/secure 里就会堆满爆破记录。SSH 是大门,这篇是一份可以直接照抄的加固清单。

一、先看看有多少人在撬门

# 今天的爆破尝试
grep "Failed password" /var/log/secure | wc -l

# 谁在撬(来源 IP Top10)
grep "Failed password" /var/log/secure \
  | grep -oE "from [0-9.]+" | sort | uniq -c | sort -rn | head

# 用哪些用户名试
grep "Failed password" /var/log/secure | grep -oE "invalid user \S+" | sort | uniq -c | sort -rn | head

看完这些数字,你会立刻想做下面所有事。

二、第一优先级:密钥登录,禁用密码

1. 生成密钥对(在自己电脑上)

ssh-keygen -t ed25519 -C "zy@laptop"
# 一路回车( passphrase 可留空, 更安全是设一个)
# 生成: ~/.ssh/id_ed25519(私钥, 绝不外传) + id_ed25519.pub(公钥)

2. 公钥上服务器

ssh-copy-id -i ~/.ssh/id_ed25519.pub root@1.2.3.4
# 或手动: 把公钥内容追加到服务器 ~/.ssh/authorized_keys

3. 验证密钥能登录后,再关闭密码

vim /etc/ssh/sshd_config

三、sshd_config 加固清单

# ===== /etc/ssh/sshd_config 关键项 =====

# 1. 禁用 root 直接登录(先建好普通用户 + sudo!)
PermitRootLogin no

# 2. 禁止密码认证(前提: 密钥已验证可用!)
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes

# 3. 只允许特定用户/组登录
AllowUsers zy deploy
# AllowGroups ops

# 4. 改默认端口(挡掉无脑扫描, 防不住针对性攻击)
Port 2222

# 5. 空闲超时自动踢下线
ClientAliveInterval 300
ClientAliveCountMax 2

# 6. 限制登录尝试与认证时限
MaxAuthTries 3
LoginGraceTime 30

# 7. 不用到的认证方式全关掉
GSSAPIAuthentication no
UseDNS no                    # 还能加快登录速度
# 生效前先验证语法!
sshd -t

# 用另一个终端保持现有连接不动, 新开连接测试(保命操作!)
systemctl restart sshd

⚠️ 顺序就是安全:先建普通用户并配好 sudo → 部署密钥 → 验证密钥登录 → 才能改 sshd_config 重启。反着来就是把自己锁在门外。

# 建用户 + sudo(wheel 组)
useradd -m -G wheel zy
passwd zy

改了端口后记得放行防火墙和安全组:

firewall-cmd --add-port=2222/tcp --permanent && firewall-cmd --reload

四、fail2ban:自动拉黑爆破者

dnf install -y epel-release && dnf install -y fail2ban

cat > /etc/fail2ban/jail.local <<'EOF'
[DEFAULT]
bantime  = 3600          # 封禁 1 小时
findtime = 600           # 10 分钟窗口内
maxretry = 5             # 失败 5 次就封
banaction = firewallcmd-rich-rules

[sshd]
enabled = true
port    = 2222           # 与 sshd 端口一致
EOF

systemctl enable --now fail2ban

# 查看战果
fail2ban-client status sshd
# 目前封禁列表、总攻击次数一目了然

fail2ban-client set sshd unbanip 1.2.3.4    # 手动解封

五、进阶招式

只允许证书 + 双因素(如 Google Authenticator)

dnf install -y google-authenticator
google-authenticator            # 扫码绑定, 生成 ~/.google_authenticator
# sshd_config 追加:
#   AuthenticationMethods publickey,keyboard-interactive
#   ChallengeResponseAuthentication yes

跳板机模式(团队标准姿势)

所有服务器只监听内网/白名单 IP,外部统一走一台跳板机:

# 服务器 sshd_config
ListenAddress 10.0.0.5            # 只听内网

# 或者防火墙层面只放跳板机 IP
firewall-cmd --add-rich-rule='rule family=ipv4 source address=10.0.0.10 port port=2222 protocol=tcp accept' --permanent
# 客户端 ~/.ssh/config 简化跳板
Host web01
    HostName 10.0.1.11
    User zy
    Port 2222
    ProxyJump bastion.example.com    # 一条命令直达: ssh web01

免密自动化(CI/CD 部署用)

# 服务器侧限制自动化密钥的能力(只能跑特定命令)
# ~/.ssh/authorized_keys:
command="/opt/deploy/pull.sh",no-pty,no-port-forwarding ssh-ed25519 AAAA... deploy@ci

六、加固核对清单

  • 普通用户 + sudo 已就绪,不再日常使用 root
  • ed25519 密钥登录验证通过
  • PasswordAuthentication no
  • PermitRootLogin no
  • AllowUsers 白名单
  • 改默认端口(同步防火墙 + 安全组)
  • sshd -t 通过后才 restart,且保留旧会话保底
  • fail2ban 运行中,status sshd 有数据
  • 客户端 ~/.ssh/config 配好 ProxyJump

小结

安全是分层洋葱:密钥 > 禁密码 > 白名单 > 改端口 > fail2ban > 跳板机。每一层都在提高攻击成本。而加固的铁律是:每改一步,先验证,再进行下一步——把自己锁在门外是新手最贵的一课。


本文是「安全」系列第 1 篇。