Tropic Host

VPS 安全入门:SSH 密钥、防火墙与 Fail2ban

阅读约需 10 分钟
Tropic

VPS 安全入门:SSH 密钥、防火墙与 Fail2ban

Ubuntu 安装完成后,新的 VPS 不能直接视为安全。服务器在完成访问控制配置前就已经暴露在扫描器面前:攻击者会尝试 SSH 密码,寻找公开的管理面板,并检查常见漏洞。本指南将从零开始完成 VPS 的基础防护:创建独立用户,配置 SSH 密钥登录,通过 UFW 限制网络端口,并启用 Fail2ban。只要命令由拥有 sudo 权限的用户执行,以下步骤适用于 Ubuntu 22.04 和 24.04。

开始配置前:列出需要使用的端口

不要为了“以防万一”而打开端口。普通 Web 服务器通常只需要:

  • 22/tcp — SSH,最好按 IP 限制;改用其他端口只能作为额外措施;
  • 80/tcp — HTTP,通常用于跳转到 HTTPS 以及验证证书;
  • 443/tcp — HTTPS。

如果前面运行着 Nginx 或 Caddy,300080809000 之类的应用端口不应直接暴露在互联网中。请将应用绑定到 127.0.0.1,或者只允许内网访问该端口。先确认服务器正在监听哪些端口:

sudo ss -tulpn

安装 Docker 后,还要单独检查它添加的 iptables 规则:-p 3000:3000 可能绕过你预期的网络结构,直接开放端口。对于公开服务,更安全的做法是使用 HTTPS 代理,并隐藏内部端口。

第 1 步:更新系统并创建管理员用户

使用服务商提供的账户连接 VPS,然后安装更新:

sudo apt update
sudo apt full-upgrade -y
sudo apt install -y ufw fail2ban unattended-upgrades

创建一个专用的个人用户。将 alex 替换为你自己的用户名:

sudo adduser alex
sudo usermod -aG sudo alex

在单独的终端窗口确认新账户可以正常使用之前,不要删除原有访问方式。这是一条重要规则:当当前会话仍然保持打开时,修复 SSH 配置错误会容易得多。

第 2 步:创建 SSH 密钥并安装到服务器

在自己的 Linux、macOS 或 Windows PowerShell 电脑上执行:

ssh-keygen -t ed25519 -C "alex@my-computer"

按 Enter 将密钥保存到默认文件,并设置 passphrase(密钥口令)。私钥不能发送到聊天中,不能放进代码仓库,也不能复制到 VPS。服务器上只需要传输扩展名为 .pub 的公钥文件:

ssh-copy-id alex@SERVER_IP

如果没有 ssh-copy-id,可以在 PowerShell 中使用 Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub 查看公钥,然后将它添加到服务器:

sudo install -d -m 700 -o alex -g alex /home/alex/.ssh
sudo nano /home/alex/.ssh/authorized_keys
sudo chown alex:alex /home/alex/.ssh/authorized_keys
sudo chmod 600 /home/alex/.ssh/authorized_keys

将公钥粘贴为一行,并在关闭密码登录前验证登录:

ssh alex@SERVER_IP
sudo whoami

最后一条命令的预期结果是 root。如果 SSH 客户端找不到密钥,请明确指定它:ssh -i ~/.ssh/id_ed25519 alex@SERVER_IP

第 3 步:禁止 root 和密码登录

先备份 SSH 配置:

sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo nano /etc/ssh/sshd_config

确认文件中包含以下参数:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
KbdInteractiveAuthentication no
MaxAuthTries 3

在 Ubuntu 中,设置也可能位于 /etc/ssh/sshd_config.d/*.conf,所以请检查最终生效的配置:

sudo sshd -t
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|pubkeyauthentication|maxauthtries'

如果 sshd -t 报错,在修复语法前不要重启服务。检查成功后应用设置:

sudo systemctl reload ssh

保留旧的 SSH 连接处于打开状态,并在新窗口中使用密钥验证登录。没有验证过密钥就关闭密码登录,是最常见的服务器失去访问权限的原因。

第 4 步:配置 UFW,同时避免锁死 SSH

UFW 是 Linux 网络规则的便捷封装。先设置安全的默认策略,再允许 SSH 和 Web 端口:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment 'SSH'
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
sudo ufw enable

只有在 SSH 规则已经添加后,才确认启用防火墙。查看结果:

sudo ufw status verbose
sudo ufw status numbered

如果办公室使用固定的公网 IP,可以将 SSH 限制到该地址:

sudo ufw delete allow 22/tcp
sudo ufw allow from YOUR.PUBLIC.IP to any port 22 proto tcp comment 'SSH office'

只有在 IP 固定且拥有服务商控制台的情况下才使用这种方式:地址变化后,你可能会把自己挡在服务器之外。

如何临时开放应用端口

如果需要直接检查服务,可以创建限制来源地址的规则:

sudo ufw allow from YOUR.PUBLIC.IP to any port 8080 proto tcp

测试完成后,根据 ufw status numbered 显示的编号删除它:

sudo ufw delete RULE_NUMBER

不要使用 sudo ufw allow 1:65535/tcp:这条规则会让防火墙变成形式上的摆设。

第 5 步:为 SSH 启用 Fail2ban

Fail2ban 会分析日志,并在多次登录失败后添加临时封禁规则。它不能替代 SSH 密钥和防火墙,但可以减少自动化密码尝试造成的噪声。

创建本地配置,避免软件包更新覆盖你的设置:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

[DEFAULT] 部分设置合理的值:

[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
banaction = ufw

[sshd]
enabled = true
port = 22

启动服务并检查 jail:

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

sshd 的输出中查看失败尝试次数和已封禁的地址。不要把自己的 IP 加入封禁列表。如需永久排除某个地址,可在 [DEFAULT] 中使用参数 ignoreip = 127.0.0.1/8 YOUR.PUBLIC.IP

第 6 步:启用自动更新

自动更新对安全软件包很有帮助,但内核重启仍然需要人工控制:

sudo dpkg-reconfigure -plow unattended-upgrades
sudo systemctl status unattended-upgrades

每周检查一次是否需要重启:

test -f /var/run/reboot-required && echo 'Требуется перезапуск'

手动重启前,确认你有可用的密钥以及 VPS 控制台访问权限。重启后检查应用服务、Nginx、UFW 和 Fail2ban 是否正常运行。

第 7 步:从外部验证结果

请从另一台电脑检查防护,不要只根据配置文件的内容判断:

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no alex@SERVER_IP

这条命令应该以拒绝连接结束。单独验证密钥登录:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519 alex@SERVER_IP

在 VPS 上检查监听地址和规则:

sudo ss -lntup
sudo ufw status numbered
sudo fail2ban-client status sshd

如果应用不需要直接访问,应用端口应该监听 127.0.0.1。你可以从外部节点使用 nmap SERVER_IP,但只能扫描自己的服务器:未经允许检查他人基础设施,可能违反法律和服务商规则。

备份与恢复

SSH 防护无法防止数据被删除、管理员操作失误或应用遭到入侵。请将数据库、配置文件和用户文件的副本保存在 VPS 之外。最基本的方案是每天备份,保留前几天的多个版本,并定期验证能否恢复。

不要把密码和令牌以明文写入脚本。一旦发生泄露,应立即撤销该秘密并创建新的秘密。

如何为安全项目选择 VPS

安全始于对基础设施的控制。使用 VPS 时,你可以自行选择操作系统、防火墙规则、访问方式、备份方案以及服务的部署位置。对于小型网站或 API,稳定的网络、SSD 和恢复控制台通常比过多的虚拟 CPU 核心更重要。

tropic.host 上启动 VPS 项目时,先明确项目对外提供的入口:多数情况下 SSH、HTTP 和 HTTPS 就足够了。数据库和管理面板应保留在内部网络中。随着项目增长,可以将应用、数据库和监控分别部署到不同的 VPS,以隔离故障影响范围。选择稳定的网络、便捷的控制台和适合扩展的资源配置,能让安全策略更容易长期执行。

常见错误

  • 未验证密钥登录就关闭密码。保留当前会话,并单独测试新的登录方式。
  • 在可以限制可信地址的情况下,仍让全世界都能访问 22/tcp
  • 直接发布 Docker 端口。应先检查 Docker 和 UFW 的规则。
  • 安装 Fail2ban 后就再也不查看日志。每次修改后都应检查 journalctl -u ssh 和 jail 状态。

总结

只要按照正确顺序操作,VPS 的基础防护并不需要太多时间:创建独立用户,安装 SSH 密钥,验证访问,禁止 root 和密码登录,启用 UFW,配置 Fail2ban 及自动更新。之后再加入备份、日志记录和外部监控。

这些步骤不能让服务器绝对不可入侵,但可以解决初始配置中最常见的错误。下一步应根据具体应用调整安全配置:更新依赖,限制服务权限,保护管理面板,并定期检查开放端口。

FAQ

需要修改 SSH 的默认端口吗?

不一定。修改端口可以减少自动化扫描的噪声,但不能替代密钥、禁用密码、UFW 和 Fail2ban。如果修改端口,请同时更新防火墙规则和 Fail2ban jail 中的 port 参数。

配置 UFW 后失去访问权限怎么办?

使用服务商提供的 Web 控制台或救援控制台,检查 SSH 规则和 sshd 配置。在新登录方式确认可用之前,不要关闭旧的工作会话。

Fail2ban 足够保护 SSH 吗?

不够。Fail2ban 只能对已经发生的登录失败做出反应。基础防护应包括 SSH 密钥、关闭密码认证、为用户设置最小权限,以及限制访问范围的防火墙。

可以只允许一个 IP 连接 SSH 吗?

可以,只要该地址固定:在 UFW 中添加针对该 IP 的 allow from 规则。请提前准备服务商控制台或备用访问方式,因为 IP 变更后连接会被阻断。

应该多久检查一次 VPS 安全性?

每次修改 SSH、防火墙或 Docker 端口发布规则后,都应检查端口并测试登录。日常至少每周查看一次更新和日志,并定期进行备份恢复测试。