防火墙和安全组到底有什么区别?我终于搞懂了

预计阅读时间:20 分钟

这是「把自己部署到互联网上」系列的第 13 篇。

上一篇,我处理了服务器安全里的第一件事:不要一直用 root 登录服务器。

我创建了普通用户,给它配置 sudo 权限,并且提醒自己:在确认普通用户能正常 SSH 登录之前,不要急着禁用 root。

用户权限处理完之后,下一步就要面对另一个很容易混淆的问题:

防火墙和安全组到底有什么区别?

这个问题我以前也没有真正分清楚。

很多教程会说:开放 80 端口,开放 443 端口,检查防火墙,检查安全组。

但如果第一次自己搭服务器,就很容易困惑:

安全组不是防火墙吗?

我在云平台放行了端口,为什么服务器里还要配防火墙?

我服务器防火墙放行了端口,为什么外网还是访问不到?

到底应该改哪里?

如果两个地方都要配,那流量到底先经过谁?

这篇就把这个问题讲清楚。

先给结论:

安全组是云平台层面的入口规则,防火墙是服务器系统内部的访问控制。

一个在服务器外面,一个在服务器里面。

它们不是同一个东西,但会共同决定你的端口能不能被外部访问。

可以用一张表来区分:

对比项 安全组 系统防火墙
所在位置 云平台网络层 服务器操作系统内部
配置入口 云厂商控制台 服务器命令行或配置文件
生效范围 云服务器外部入口 进入系统后的访问控制
常见对象 实例、网卡、云资源 本机端口和服务
常见用途 控制公网入站流量 细化系统内部端口规则
排查方式 看云平台规则 看 ufw/firewalld/iptables 状态
谁先拦截 通常更靠前 通常更靠后

为什么这个问题很容易混乱

防火墙和安全组之所以容易混,是因为它们都在做一件看起来很像的事情:控制网络访问。

比如你想让别人访问你的个人博客,就要开放 80 和 443 端口。

你想 SSH 登录服务器,就要开放 SSH 端口。

你不想数据库暴露公网,就不要开放数据库端口。

这些都和「允许谁访问哪个端口」有关。

所以很多人会下意识把安全组和防火墙当成同一个概念。

但真正排查问题时,这种混淆会非常麻烦。

比如,你在服务器里用防火墙放行了 80 端口,但云平台安全组没有放行,外网还是访问不到。

反过来,你在云平台安全组放行了 80 端口,但服务器系统防火墙拦住了,外网同样访问不到。

更麻烦的是,有些服务本身还没监听对应端口。

这时你可能以为是安全组问题,也可能以为是防火墙问题,结果真正的问题是项目根本没启动。

所以端口访问问题,一定要分层看。

不要看到访问失败,就只改一个地方。

先理解一条访问链路

通过域名访问博客或官网,用户在浏览器里打开:

https://blog.aicultiv.com

这个请求大概会经过几层:

  1. DNS 把域名解析到服务器公网 IP
  2. 请求到达云厂商网络入口
  3. 云平台安全组判断这个流量能不能进来
  4. 流量进入服务器系统
  5. 系统防火墙判断这个端口能不能访问
  6. Nginx 接收到 80 或 443 端口请求
  7. Nginx 转发给博客服务或返回静态页面

这条链路里,安全组和防火墙都只是其中一层。

安全组更靠外。

防火墙更靠内。

如果外面的安全组不放行,请求根本到不了服务器系统。

如果安全组放行了,但服务器防火墙不放行,请求到了机器门口也进不去。

如果两者都放行了,但 Nginx 没启动,请求仍然没有服务处理。

所以排查访问问题时,不能只看一个点。

要顺着链路一层一层检查。

安全组:云平台门口的规则

安全组是云厂商提供的网络访问控制能力。

它通常配置在云平台控制台里,不在 Linux 系统内部。

20260609155147733 你可以把它理解成云服务器外面的一层门卫。

请求想进入这台服务器之前,先要经过云平台安全组。

安全组通常可以控制:

  • 入方向规则:外部访问服务器
  • 出方向规则:服务器访问外部
  • 协议:TCP、UDP、ICMP 等
  • 端口:22、80、443、3306 等
  • 来源 IP:允许哪些地址访问

我们详细拆解下每个参数的含义:

优先级(Priority)

  • 当前值:1
  • 含义:安全组规则的执行顺序。数字越小,优先级越高。
  • 作用:当多个规则冲突时,优先级高的规则会生效。
  • 注意:不能重复设置相同优先级,否则可能产生不可预期行为。
  • 示例:
  • 优先级为 1 的规则是“允许从 xx.16.4x.2x 访问 3306 端口”;
  • 如果有另一条优先级为 2 的规则拒绝所有访问,则这条规则会被覆盖。

策略(Action)

  • 当前值:允许
  • 含义:决定是否放行该规则匹配的流量。
  • 可选项:
  • 允许:放行符合条件的流量。
  • 拒绝:阻止符合条件的流量。
  • 在你的场景中选择“允许”,表示允许来自指定 IP 的访问。

协议类型(Protocol)

  • 当前值:TCP
  • 含义:指定要控制的网络协议。
  • 常见选项:
  • TCP:传输层协议,常用于网页、数据库、SSH 等需要可靠连接的服务。
  • UDP:无连接协议,用于视频、语音、DNS 查询等。
  • ICMP:用于网络诊断(如 ping)。
  • ALL:允许所有协议(不推荐,安全性低)。
  • MySQL 使用 TCP 协议通信。

源地址(Source Address)

  • 当前值:IPv4 → 111.11.11.11

  • 含义:允许访问本 ECS 的来源 IP 地址或网段。

  • 支持格式:

  • 单个 IP:111.11.11.11

  • CIDR 网段:111.11.11.0/24(表示整个子网)
  • 任意 IP:0.0.0.0/0(危险!相当于开放给所有人)

  • 当前配置为 111.11.11.11,意味着只有这台机器能通过此规则访问你的 ECS。

  • 安全建议:不要使用 0.0.0.0/0 开放数据库端口!

CIDR 网络范围 主机数量 作用
/32 只包含一个 IP 地址(即它自己) 1 个 表示单个主机,常用于服务器、虚拟机等精确绑定
/31 包含两个 IP 地址 2 个 通常用于点对点连接(如专线)
/30 包含 4 个 IP 地址 4 个 小型子网,如局域网段

端口范围(Port Range)

  • 当前值:3306
  • 含义:指定允许访问的端口号或端口范围。
  • MySQL 默认使用 3306 端口进行通信。
  • 支持格式:
  • 单个端口:3306
  • 范围:80-8080(允许 80 到 8080 所有端口)
  • 注意:如果你没在 ECS 上开启防火墙(如 iptables),还需要检查操作系统层面的防火墙设置(如 ufw, firewalld)。

描述(Description)

  • 当前值:MySQL 数据库
  • 含义:对这条规则的文字说明,方便后续管理和维护。
  • 推荐做法:写清楚用途,比如“允许内网应用服务器访问 MySQL”、“开发机 SSH 登录”等。
  • 这不是必须字段,但建议填写,避免日后忘记了。

开放建议

项目 建议
不要开放 0.0.0.0/0 到数据库端口 极易被扫描攻击
尽量使用具体 IP 或内网网段 提高安全性
配合 ECS 内部防火墙(如 iptables)双重防护 更安全
添加清晰描述 方便团队协作与审计
定期审查安全组规则 删除不再使用的规则

安全组的特点是:它在云平台层面生效。

哪怕你的服务器系统里没有配置防火墙,只要安全组没放行,外部也访问不到。

这也是为什么很多人本地服务启动了,但公网访问失败。

服务可能没问题,系统也没问题,只是云平台入口没开。

防火墙:服务器系统内部的规则

防火墙是服务器系统内部的访问控制。

  1. 确定服务器环境信息 cat /etc/os-release 会看到如下信息

bash xxxx@iv-xxxx:~# cat /etc/os-release PRETTY_NAME="Ubuntu 24.04 LTS" NAME="Ubuntu" VERSION_ID="24.04" VERSION="24.04 LTS (Noble Numbat)" VERSION_CODENAME=noble ID=ubuntu ID_LIKE=debian HOME_URL="https://www.ubuntu.com/" SUPPORT_URL="https://help.ubuntu.com/" BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" UBUNTU_CODENAME=noble LOGO=ubuntu-logo

  1. 云服务器为了减少镜像包的大小,打包镜像时,只保留必要的安装包,所有我们需要安装一些常用的 package

```bash sudo apt install -y curl wget git vim unzip zip htop tree net-tools ca-certificates gnupg lsb-release software-properties-common ufw fail2ban chrony

```

执行命令之后, 安静的等待就可以了。

  1. 设置服务器时区,代码中的相关日期函数,都会基于服务器的时区配置

bash # 设置时区 sudo timedatectl set-timezone Asia/Shanghai # 查看时区 timedatectl

  1. 开放防火墙(服务器默认关闭)

```bash # 查看状态 sudo ufw status verbose # 结果 Status: inactive

# 查看编号,方便删除规则 sudo ufw status numbered

# 防火墙未开启,需要开启防火墙, 为防止原有的ssh链接断掉,先放行 ssh sudo ufw allow OpenSSH

# 如果你的 SSH 不是默认 22 端口,比如 2222,就额外执行: sudo ufw allow 2222/tcp

# 然后放行网站端口;其他外网需要访问的端口,也这样进行开放 sudo ufw allow 80/tcp sudo ufw allow 443/tcp

# 启用服务器防火墙 sudo ufw enable

# 他会提示, 输入 y 即可 Command may disrupt existing ssh connections. Proceed with operation (y|n)? y

# 按编号删除某条规则(例如删除第 2 条) sudo ufw delete 2 ```

  1. 检查防火墙和端口配置

```bash xxxx@iv-xxxx:~# sudo ufw status verbose Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), disabled (routed) New profiles: skip

To Action From -- ------ ---- 22/tcp (OpenSSH) ALLOW IN Anywhere 80/tcp ALLOW IN Anywhere 443/tcp ALLOW IN Anywhere 22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6) 80/tcp (v6) ALLOW IN Anywhere (v6) 443/tcp (v6) ALLOW IN Anywhere (v6)

其他端口,比如数据库 3306、Redis 6379,一般不要对公网开放。需要访问时优先用内网、安全组白名单、VPN 或 SSH 隧道。

```

所以启用系统防火墙前,至少要确认:

  • 当前 SSH 端口已经放行
  • 云平台安全组也允许 SSH 访问

防火墙不是不能开,而是要有顺序地开。

为什么两层都需要

有人可能会问:既然安全组已经能控制端口,为什么还要系统防火墙?

我的理解是:它们不是互相替代,而是双层保护。

安全组在外层,适合控制公网入口。

系统防火墙在内层,适合给服务器自身再加一道边界。

对个人服务器来说,不一定要一开始配置得特别复杂,但至少要知道两层都存在。

如果只依赖安全组,一旦云平台规则误开,服务器内部没有第二层限制。

如果只依赖系统防火墙,但安全组乱开,也会增加暴露面和排查复杂度。

更实际一点说,很多访问问题都要同时看这两层。

你不能只说「我防火墙开了」,也不能只说「我安全组开了」。

端口能不能被访问,取决于整条链路。

一个简单的端口开放原则

我给自己的原则是:

公网只开放必须开放的端口。

对个人博客来说,初期大概就是:

  • SSH 管理端口:用于自己登录维护
  • 80:用于 HTTP 和证书相关流程
  • 443:用于 HTTPS 正式访问

其他端口默认不开放。

数据库不开放。

内部服务不开放。

调试端口不开放。

临时端口用完就关。

如果确实需要远程连接数据库,也要优先考虑更安全的方式,比如 SSH 隧道、VPN、内网连接或临时限制来源 IP,而不是直接把数据库端口暴露给全网。

这不是强迫症。

这是减少攻击面。

服务器暴露得越少,后面要担心的东西就越少。

常见误区

安全组放行了就万事大吉

安全组放行只是第一步。

它只说明云平台入口允许这个流量进来。

但服务器内部是否允许,服务是否启动,端口是否监听,Nginx 是否配置正确,都还要继续检查。

所以如果你在安全组里开放了 80,但网站仍然打不开,不要马上怀疑云厂商。

先继续看系统防火墙和服务状态。

防火墙关掉最省事

很多人排查端口问题时,会直接关闭防火墙。

短期看,这确实可能让问题消失。

但这不是解决问题,而是移除了一层保护。

更好的做法是搞清楚具体拦截了哪个端口,然后只放行需要的端口。

个人服务器不需要复杂到不可维护,但也不能因为图省事就完全不设边界。

数据库端口随手开放

这个坑非常常见。

本地想连数据库,发现连不上,于是直接在安全组里开放 3306 或 5432。

这样确实方便,但也把数据库暴露给了公网。

对个人博客来说,数据库通常不需要被公网直接访问。

开发过程中一般都使用 Navicat 之类工具临时连接数据库,也应该谨慎处理:限制来源 IP、使用 SSH 隧道,或者只在必要时临时放行,用完再关闭。

后面我会单独写一篇:为什么不要随便开放数据库端口。

因为这件事看起来只是方便调试,实际上风险很高。

写在最后

防火墙和安全组到底有什么区别?

我的理解是:

安全组在云平台层面,控制流量能不能到服务器门口。

防火墙在系统内部,控制流量进入服务器后能不能访问对应服务。

两者不是一回事,但会共同影响端口访问。

以后排查问题时,会按照链路一层一层看:DNS、安全组、防火墙、端口监听、Nginx、项目服务。

这比凭感觉乱改配置要稳得多。

下一篇,我会继续讲端口安全里最容易被忽略、也最容易图省事的一件事:

为什么不要随便开放数据库端口?

因为数据库不是普通入口,它一旦暴露,风险比页面打不开要大得多。


本文由 楸木 原创,转载请注明出处。

相关推荐

发现更多