一台新服务器能够通过 SSH 登录,只代表它“可以使用”,并不代表它已经适合长期运行。真正上线前,我通常会按下面的顺序做一次基础加固:先建立可恢复的登录方式,再缩小暴露面,最后补上更新、监控和备份。

文中的用户名、端口和地址都是示例。修改 SSH 配置前,请务必保留一个已登录终端,并先验证新连接成功。

1. 安装更新并确认是否需要重启

sudo apt update
sudo apt full-upgrade -y
test -f /var/run/reboot-required && cat /var/run/reboot-required

更新完成后不要急着重启。先确认业务进程、数据库和反向代理是否有可靠的开机自启配置。

2. 创建日常管理账号

长期直接使用 root 会放大误操作的后果。可以创建一个普通账号,并只在需要时使用 sudo:

sudo adduser deploy
sudo usermod -aG sudo deploy
id deploy

3. 使用 SSH 密钥登录

在本地生成密钥:

ssh-keygen -t ed25519 -a 64
ssh-copy-id deploy@example.com

先新开终端确认密钥登录成功,再考虑关闭密码登录。不要在唯一会话里直接修改后重启 SSH。

4. 收紧 SSH 配置

编辑 /etc/ssh/sshd_config.d/99-hardening.conf:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 4
LoginGraceTime 30

验证语法后平滑重载:

sudo sshd -t
sudo systemctl reload ssh

改 SSH 端口不是核心安全措施。密钥登录、限制来源和及时更新通常更重要。

5. 启用最小化防火墙

如果服务器只提供 SSH、HTTP 和 HTTPS:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

云厂商安全组也要同步收紧。主机防火墙和安全组是两层控制,不能只配置其中一层。

6. 使用 Fail2ban 限制暴力尝试

sudo apt install -y fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Fail2ban 不能替代密钥登录,但可以降低扫描和重复尝试带来的日志噪声。

7. 开启自动安全更新

sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades
systemctl status unattended-upgrades

自动更新适合安全补丁;涉及数据库、运行时大版本或内核重启时,仍应安排维护窗口。

8. 检查监听端口和服务

sudo ss -lntup
systemctl --type=service --state=running

不需要的服务应停用。数据库、Redis 和应用调试端口优先监听 127.0.0.1,由 Nginx 或受控网络访问,而不是直接暴露到公网。

9. 建立日志与磁盘巡检

journalctl -p warning --since today
df -h
df -ih
sudo du -xhd1 /var | sort -h

很多“小服务器突然不可用”并不是攻击,而是日志、缓存或备份把磁盘和 inode 写满了。至少应为磁盘使用率、内存和 HTTP 可用性配置提醒。

10. 做一份真正能恢复的备份

备份至少应覆盖:

  • 网站代码和上传文件;
  • 数据库一致性备份;
  • Nginx、证书和服务配置;
  • 恢复步骤及所需版本。

备份文件不要只放在同一块云盘上。定期把它复制到对象存储或另一台设备,并实际做一次恢复演练。

最后的自检

完成后可以从另一网络重新测试:

ssh deploy@example.com
curl -I https://example.com

安全加固不是一次性动作。更现实的目标是:权限尽量小、入口尽量少、更新足够及时、异常能够发现、数据能够恢复。