【安全基线 02】VPS 防火墙加固:ufw / firewalld 与防爆破实战

一台裸 VPS 暴露公网几小时就会被扫。从改端口、禁密码登录、ufw/firewalld 防火墙、fail2ban 防爆破,到自动更新与定期审计,给你一份开箱即用的 VPS 安全加固清单。

一台刚开通的 VPS,从你拿到 IP 的那一刻起就挂在公网上。这不是“过几天再弄安全也行”,而是机器人扫描器几分钟就能摸到你的 22 端口。很多人第一次登录看到 /var/log/auth.log(CentOS 上是 /var/log/secure)里几千条 root 登录失败记录时,才意识到“原来我被盯上了”。本文给你一套开箱即用的 VPS 安全基线,照着做至少能挡掉 90% 的自动化扫描和脚本小子。哪怕你只是花几十块买了台便宜年付入门机,这套基线同样值得做——机器越便宜越容易被扫,守好基础反而最划算。

延伸阅读

更多相关攻略推荐:Ollama AI系列(2):VPS上的AI推理与API应用Ollama AI系列(2):VPS上的AI推理与API应用【CPU选型 01】搭载 AMD Ryzen 9950X 的 VPSARM / Ampere 席卷 VPS:性价比真香还是兼容陷阱?Ollama AI系列(2):VPS上的AI推理与API应用

一、公网攻击面:你的 VPS 一开机就在挨打

公网上的攻击可以分成三类,理解它们才能知道后面每一步在防什么:

  • 端口扫描:机器人全网扫 IP 段,看哪个 IP 的哪个端口开着。22、80、443、3306、5432 都是重点目标。
  • 暴力破解:对着 SSH 或面板用户名密码一轮轮试,弱密码几秒就被拿下。这是 fail2ban 要对付的主力。
  • 漏洞利用:你跑的旧版 OpenSSH、有 CVE 的 nginx、没更新的 WordPress 插件,都会被自动化武器库直接打。

结论很简单:能不暴露的端口一律不暴露,必须暴露的就锁死认证方式。安全不是装一个神器,而是把攻击面一层层收小。

实战里有个直观感受:一台开着默认 22 端口、允许密码登录的机器,auth.log 里每天几千条 root 失败记录是常态;改成密钥登录加高位端口后,这类骚扰量往往能掉一两个数量级。这不是说攻击消失了,而是把无意义的噪音和绝大多数脚本挡在门外,让你能专注盯真正可疑的日志。顺带一提,扫描器也常顺手探测 Redis 未授权访问、Docker 2375 端口暴露、MySQL 弱密码这类“送分题”,所以下面讲的最小暴露原则对它们一样有效。

二、登录层(SSH 密钥 + Fail2ban):详见本系列第 1 篇

SSH 密钥登录、禁用密码、改高位端口、限制来源 IP,以及用 Fail2ban 专守 SSH 监狱——这些登录层的加固,本系列第 1 篇《加固 SSH 与 Fail2ban》已一步一步讲透,含命令与踩坑。本文把篇幅留给更常被低估的网络层:防火墙本身怎么配才不算"开了个洞"。若还没做登录层加固,请先按第 1 篇把门锁好,再回来读下面的防火墙进阶。

三、改端口 / 限来源 IP:躲开自动扫描的枪口

把 SSH 从 22 换成高位端口(比如 2222),本身不是加密意义上的安全,但能过滤掉绝大多数只扫 22 的脚本,日志瞬间清静。在 sshd_config 里加一行:

Port 2222

重要提醒:改端口前,先在另一个终端窗口用新端口试登录成功,再重启 sshd;千万别关掉当前会话去赌新端口能通,否则只能进厂商的 VNC/救援模式救场。如果 SSH 只允许你公司或家里的固定 IP 访问,那就更稳:

# 仅允许特定来源(在 sshd_config 或防火墙层做)
AllowUsers user
# 配合防火墙:只放行你家 IP 的 2222 端口

对运维型机器,限制来源 IP 是最硬的一层防护——扫描器根本连不到端口,自然无从爆破。动态 IP 用户可以用 ddns 配合脚本定时更新防火墙白名单,或者退一步只做密钥登录,也已经挡掉了绝大多数自动化攻击。

四、ufw 与 firewalld:两款防火墙怎么选怎么配

Ubuntu/Debian 系默认用 ufw(Uncomplicated Firewall,iptables 的前端封装,主打好上手);CentOS/AlmaLinux/Rocky 系用 firewalld(基于 nftables/iptables,按“区域+服务”管理)。两者本质都是帮你写底层防火墙规则,选哪个看发行版,别混用。

黄金法则:默认拒绝所有入站,只放行真正需要的端口。一个普通网站服务器通常只需要三个入站端口——SSH(自定义端口)、80(HTTP)、443(HTTPS)。数据库 3306、5432 绝不该直接暴露在公网,要么只监听 127.0.0.1,要么走内网或 SSH 隧道。很多被拖库的事故,根因就是 3306 误开在 0.0.0.0 上,等于把家门钥匙插在锁上还贴了纸条。

ufw 示例:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp   # SSH 自定义端口
sudo ufw allow 80/tcp     # HTTP
sudo ufw allow 443/tcp    # HTTPS
sudo ufw enable
sudo ufw status numbered

firewalld 示例:

sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

注意:改了 SSH 端口后,防火墙一定要先放行新端口再重启 sshd,顺序反了就把自己挡在门外。另外不要在同一台机器上同时跑 ufw 和 firewalld,规则会打架。

4.4 速率限制:挡住爆破与刷接口的噪音

默认拒绝只解决"端口开没开",但 SSH、Web 登录这类必须对外的端口,光靠 fail2ban 还不够快。可以在防火墙层直接做速率限制:进阶玩法是用 nftables 的 meter 做"同一 IP 每秒最多 N 个新连接";对 Web 服务,更推荐在 CDN(如 Cloudflare)或反向代理层限流,把脏流量挡在到达源站之前。原则:能限速的入口尽量限速,宁可误杀重试也不放洪水

4.5 Docker 与防火墙的坑(最容易翻车)

很多人配好 ufw 默认拒绝,却发现 Docker 容器该拦的端口还是能被扫到——因为 Docker 默认直接写 iptables 的 FORWARD 链,绕过 ufw 规则。表现就是:你 ufw deny 了 3306,容器里的 MySQL 映射出去照样暴露。正确做法:① 启动容器用 -p 127.0.0.1:3306:3306 只绑本机,而不是 -p 3306:3306 暴露全网;② 或给 Docker 单独建 bridge 网络并配规则;③ 新版本 Docker 可在 daemon.json 设 "iptables": false 后自己接管(进阶,慎做)。铁律:容器端口暴露用"只绑本机 + 反向代理转发",别图省事直接 -p 全网

五、Fail2ban 不止守 SSH:应用层监狱

第 1 篇讲过如何用 Fail2ban 专守 SSH。这里补一点防火墙视角下更实用的玩法:Fail2ban 的 jail 是通用的,可以为任何写日志的服务建监狱——比如 WordPress 登录页暴破、Nginx 404 扫描、Postfix 发信尝试。思路一致:选过滤器(filter)、定阈值(maxretry / findtime)、套动作(往防火墙插封禁规则)。例如给网站登录页加 jail,10 分钟内同 IP 错 10 次就封 1 小时,比纯应用层限流更硬。注意:Fail2ban 防不了分布式(肉鸡从不同 IP),所以它只是纵深防御的一环。

六、自动安全更新:别等漏洞被爆才打补丁

再好的配置,跑着有 CVE 的旧软件也是筛子。人总会忘,所以让系统自己打安全补丁。Debian/Ubuntu 用 unattended-upgrades:

sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades

AlmaLinux/Rocky 用 dnf-automatic:

sudo dnf install -y dnf-automatic
sudo systemctl enable --now dnf-automatic-install.timer

策略上建议:操作系统级安全更新全自动,应用级大版本(比如 PHP 主版本、数据库大升级)手动控,避免一次自动更新把业务搞挂。同时养成习惯,手动跑一次全量更新清掉积压:

sudo apt update && sudo apt upgrade -y    # Debian/Ubuntu
sudo dnf update -y                        # RHEL 系

七、最小权限与定期审计:把臃肿收一收

每个跑着的服务、开着的端口都是潜在入口。几条动作清单:

  • 建一个普通用户加 sudo,日常不用 root。创建好后用新用户在另一个窗口试登成功,再考虑 PermitRootLogin no。
  • 列一遍开机自启服务,用不上的关掉:systemctl list-unit-files --type=service --state=enabled,然后 sudo systemctl disable 服务名。
  • 只本机用的服务绑定 127.0.0.1,而不是 0.0.0.0。数据库如此,Redis 如此,监控面板也如此。
  • 定期看 fail2ban 状态和 auth 日志,留意是不是有某个国家/段在猛扫;必要时把那一段加长封或丢进防火墙黑名单。
  • 敏感文件权限收好,网站目录给 web 用户读权限即可,别给写权限。

另外建议把 SSH 登录和 sudo 使用都纳入日常审查,必要时接一个轻量监控(比如 Uptime Kuma,或 Node Exporter 配 Prometheus)盯着 CPU、内存和异常进程,比出事后再救火强得多。安全是持续动作,不是一次性开关。

八、一张开箱即用的安全清单

新机器到手,按顺序勾完这几项,基本就站住了:

  1. 系统先全量更新一遍;
  2. 建普通 sudo 用户,本机生成 ed25519 密钥并 ssh-copy-id 推上去;
  3. sshd_config 改 Port、PermitRootLogin no、PasswordAuthentication no,先验证新端口能登再重启;
  4. 防火墙默认拒绝入站,只放行 2222/80/443;数据库端口不暴露;
  5. 装 fail2ban,写 jail.local,bantime 1h、maxretry 3、加白名单;
  6. 开 unattended-upgrades / dnf-automatic 自动安全更新;
  7. 关掉用不上的服务,绑定本机服务到 127.0.0.1;
  8. 配好定期备份(快照或 rsync 到异地),并真机演练一次恢复。

安全没有“一劳永逸”,但把上面这条线走完,你的 VPS 就已经甩开了绝大多数裸奔上线的机器。剩下的是持续审计和备份——真出事时,能回滚的备份才是最后的底线。哪怕只是入门机,这套动作花半小时做完,换来的是长期安心。

💡 延伸阅读:关于架构与基础设施的更多深潜指南,请前往 VPS 主题导读中心 (Hub) 获取全盘策略。