VPS服务器配置与部署

防火墙脚本

JACIN··10 分钟阅读

用一份规则文件,管理 Debian/Ubuntu 上的公网入口防火墙

最近把自己 VPS 上分散的公网端口访问控制收了一遍,目标很明确:

  • 只接管外部入口
  • 不碰 Docker 内部通信
  • 不碰容器之间互访
  • 不依赖某个特定项目结构
  • 能在 Debian / Ubuntu 上重复使用

最后收出来的方案很简单:

仓库页面:

脚本源码页:

模板配置源码页:

适合 wget / curl 的 raw 地址:

比如别人可以直接这样下:

wget https://raw.githubusercontent.com/jacinli/sky-guardwall/main/scripts/firewall/firewall-apply.sh wget https://raw.githubusercontent.com/jacinli/sky-guardwall/main/scripts/firewall/rules.conf.example

  • 一份 rules.conf
  • 一个执行脚本 firewall-apply.sh
  • 脚本自己生成并安装 systemd 服务,负责开机自动恢复

这套东西不是去“重写防火墙”,而是把常见 VPS 场景里真正需要的入口控制抽出来,用更容易维护的方式落地。

为什么要做这件事#

很多机器一开始只是跑几个服务,后面慢慢会变成这样:

  • nginx 暴露 80/443
  • 某些后台服务直接映射到公网
  • Docker 容器通过 ports: 把端口开出来
  • 数据库、面板、调试端口偶尔也直接挂在宿主机上

时间一长,很容易出现两个问题:

  1. 端口到底谁对外开放,自己也记不清
  2. 改规则时容易误伤内部链路

尤其是 Docker 环境里,很多人第一反应是直接在 INPUT 链上做限制,但 Docker 暴露端口并不总是走 INPUT。如果不理解流量路径,很容易出现“规则写了,但没拦住”或者“把容器互访也一起拦了”的情况。

所以这套方案的核心原则是:

  • 宿主机入口管宿主机入口
  • Docker 暴露端口管 Docker 暴露端口
  • 内部通信默认不碰

设计目标#

我想要的不是一套巨大的安全平台,而是一套足够稳定、足够清楚、足够好迁移的规则模型。

最终保留了 3 个配置区块:

txt
[global]
[public]
[inbound]

分别表示:

  • global
    • 全局白名单来源
    • 命中后所有端口都允许
  • public
    • 对所有来源公开的端口
  • inbound
    • 特定端口白名单
    • 比如某个后台端口只允许固定 IP 访问

这种模型有几个好处:

  • 维护时不用每次都去想链顺序
  • 看配置就知道现在的开放面
  • 迁移到别的机器时,只需要换一份规则文件

最重要的一点:只管外部入口,不碰内网通信#

这个方案里最关键的约束,不是“怎么写规则”,而是“哪些流量不应该被这套规则接管”。

我最后明确保留了这条边界:

  • 只接管外部进来的访问
  • 不主动拦截 Docker bridge 内部流量
  • 不把容器之间的调用当成公网访问处理

这是为了避免这类问题:

  • web -> api
  • api -> postgres
  • api -> redis

这些本来都属于内部依赖,如果和公网入口规则混在一起,系统一复杂就很容易把正常业务链路打断。

所以脚本在处理 Docker 暴露端口时,会优先放过常见 Docker bridge 入口,再对外部访问做限制。这样既能管公网入口,又不会把内部服务调用一起误杀。

为什么脚本里还要带 systemd 安装逻辑#

很多人第一次写 iptables 时,规则加上之后觉得已经结束了。其实还差一步:

  • 规则通常只是在当前运行时内核里生效
  • 机器重启后,不一定会自动回来

所以这套方案会在执行脚本时,顺手把一个非常轻量的 systemd 服务安装到系统里:

  • 开机后自动执行一次 firewall-apply.sh

这样做的意义很直接:

  • 规则文件是唯一真实来源
  • 脚本负责把规则下发到系统
  • 脚本自己把 systemd 服务写到系统里
  • systemd 负责在重启后恢复状态

这样你就不用再单独维护一个 service 文件,还是只需要关心:

  • rules.conf
  • firewall-apply.sh

正常使用时,你不需要专门记住:

bash
bash /root/firewall/firewall-apply.sh --install-service

因为你每次执行:

bash
bash /root/firewall/firewall-apply.sh

脚本都会顺手确保 systemd 服务存在并已启用。

现在这套方案适合什么场景#

它适合这样的机器:

  • Debian / Ubuntu VPS
  • 有 Docker,也可能没有 Docker
  • 有 IPv4,也可能有 IPv6
  • 想把公网入口规则统一起来
  • 不想把系统搞成一个很重的安全平台

它不试图解决所有问题,比如:

  • 出站流量控制
  • K8s 深层网络策略
  • 流量审计平台
  • 行为分析和风控

但如果目标只是:

  • 哪些端口公开
  • 哪些端口只给指定来源访问
  • 哪些来源全通
  • 重启后还能恢复

那这套东西已经够用了。

我对这类脚本的判断#

很多时候,不需要一上来做一个复杂面板。

先把规则模型收干净,先把边界想清楚,先保证:

  • 可读
  • 可重复应用
  • 不误伤内部通信
  • 能跨机器迁移

这比“功能很多”重要得多。

真正稳定的方案,往往不是最复杂的那个,而是你过两个月回来还能一眼看懂、还能放心继续改的那个。

评论

还没有评论,来发第一个吧