配完服务器却发现外网连不上,或者明明关了端口却还能被访问——这类问题十有八九和安全组、网络 ACL 这两层访问控制有关。它们都是云上常见的"防火墙",都用来决定"哪些流量能进、哪些能出",但作用的位置、工作的层次、规则的写法完全不同。搞混它们的后果很直接:要么安全上留了口子,要么业务被莫名挡住。
这篇文章把安全组和网络 ACL 的区别讲清楚:它们分别作用在哪一层、有状态和无状态差在哪、规则优先级怎么算、什么时候用哪个、怎么组合,以及新手最常犯的几个配置错误。看完你应该能设计出一套清晰的两层访问控制策略。
一、两层访问控制的位置
理解这两者的第一步,是搞清楚它们在网络路径上的位置。
云上典型的数据流向是:公网流量经过 Internet 网关进入虚拟私有网络(VPC),到达某个子网,再到达子网内的云服务器。在这条路径上有两道"关卡":
网络 ACL(Network ACL)是第一道关,作用在子网层面。 它检查所有进出该子网的流量,不管是哪台实例、哪个协议,只要跨越子网边界就要过这一关。它是"子网的门禁"。
安全组(Security Group)是第二道关,作用在实例层面。 它只负责绑定到它身上的那些云服务器,决定这些实例允许哪些流量进出。它是"每台机器的门禁"。
一句话概括:网络 ACL 管一个子网里所有机器的进出,安全组管指定机器的进出。流量要到达一台云服务器,必须同时通过子网的网络 ACL 和这台机器的安全组。两道关卡是"与"的关系,任何一道不放行,流量都到不了。
理解这个位置关系后,很多现象就好解释了。比如"安全组明明开了端口还是不通",很可能是因为子网的网络 ACL 没放行;反过来"网络 ACL 全放开了但服务还是不可访问",往往是安全组没配。
二、核心区别对比
把两者的关键差异整理成一张表,这是本文最重要的部分。
| 对比项 | 安全组 | 网络 ACL |
|---|---|---|
| 作用层级 | 实例级(云服务器) | 子网级 |
| 生效对象 | 绑定的实例 | 子网内所有实例 |
| 状态 | 有状态 | 无状态 |
| 默认策略 | 默认拒绝入站、允许出站 | 默认放行全部(各平台有差异) |
| 规则方向 | 一套规则,出站入站分别定义 | 入站、出站规则分开定义 |
| 规则优先级 | 规则合并后取允许/拒绝结果,无编号 | 按规则号从小到大匹配,命中即停 |
| 规则类型 | 只有允许规则(白名单) | 允许 + 拒绝都有 |
| 跨可用区 | 可被多个可用区的实例复用 | 绑定到子网,同 VPC 内可复用 |
| 生效时机 | 绑定即生效,调整即时 | 调整后对新建连接生效 |
| 典型用途 | 精细控制单个实例的访问 | 子网级别的粗粒度隔离 |
这张表里最需要展开的是"有状态/无状态"和"规则优先级"两点,下面单独讲。
三、有状态 vs 无状态:这是最大的坑
安全组是有状态的(Stateful)。 意思是:如果你配了一条入站规则允许某个 IP 访问 22 端口,那么这台实例响应该连接、把数据发出去时,出方向会自动放行,不需要你再配一条出站规则。系统会"记住"这个连接,属于同一连接的回程流量自动通过。
网络 ACL 是无状态的(Stateless)。 意思是:它不记得任何连接。你放行了入方向的流量,还必须单独配置出方向的规则,让回程流量也能出去,否则请求进来了,响应却出不去,表现为"能连上但收不到数据""连接超时"。
这个差异导致了最常见的网络 ACL 配置错误:只配了入站规则,忘了配出站。比如你允许外部访问子网内实例的 443 端口,入站规则写好了,但出站规则没放行 443 或高位端口的回程流量,结果 HTTPS 连接建立不起来。
还要注意端口范围的问题。TCP 连接中,客户端发起连接时用的是临时端口(通常是一个高位端口范围),服务器的响应会发回这个端口。所以网络 ACL 的出站规则通常要放行这个高位端口范围,而不仅仅是服务端口本身。安全组因为是有状态的,就没这个烦恼。
| 特性 | 安全组(有状态) | 网络 ACL(无状态) |
|---|---|---|
| 回程流量 | 自动放行 | 必须显式配置出站规则 |
| 配置复杂度 | 低,只需关注请求方向 | 高,入站出站都要配 |
| 常见错误 | 入站不放行导致不通 | 忘配出站导致"连上但无数据" |
| 高位端口 | 无需关心 | 需放行临时端口范围 |
四、规则优先级:谁说了算
安全组和网络 ACL 判断规则的方式不一样,这也是容易搞混的地方。
安全组没有规则编号,没有优先级先后。 它把所有规则合并起来评估:只要有任何一条规则允许这个流量,就通过;如果没有允许规则,就拒绝(白名单模型)。你不能在安全组里写一条"拒绝某 IP"的规则去覆盖允许规则——因为安全组只有允许规则。要屏蔽某个 IP,办法是不给它允许规则,而不是写拒绝规则。
网络 ACL 有规则编号,按编号从小到大匹配,命中即停止。 比如规则 100 是"拒绝 1.2.3.4",规则 200 是"允许全部",那么来自 1.2.3.4 的流量会命中规则 100 被拒绝,不会再往下看。这种机制的好处是可以精确写"拒绝某段、允许其余"。
正因为网络 ACL 支持拒绝规则,它常被用来做黑名单:发现某个 IP 在扫描或攻击,直接在网络 ACL 里加一条拒绝规则,挡住整个子网。而安全组只能做白名单,要屏蔽 IP 得挨个实例调整。
规则编号通常留出间隔(比如 100、200、300),方便之后在中间插入新规则。用连续编号(100、101、102)后期插入会很难受。
五、怎么组合使用
两者配合的正确姿势是"分层防御、各司其职"。
网络 ACL 做子网级的粗粒度隔离。 按子网的用途划分:公网子网只放需要对外提供服务的实例,私有子网不允许从公网直接访问。网络 ACL 层面上,公网子网放行 80/443,私有子网只允许来自内部网段的流量,其余一律拒绝。同时在网络 ACL 层做黑名单,快速封禁攻击来源 IP。
安全组做实例级的精细控制。 每类服务用一组安全组。Web 服务器只放行 80/443 和来自运维网段的 22;数据库只放行来自 Web 服务器安全组的 3306,不允许任何公网访问;跳板机放行 22 但限制来源 IP。
最小权限原则。 只开放业务必需的端口,来源限制到具体网段或安全组,而不是 0.0.0.0/0。安全组之间可以互相引用("允许来自 Web 安全组的流量"),这种方式比写死 IP 更灵活,实例增减时不用改规则。
安全组默认拒绝入站。 新建安全组默认不放行任何入站流量,需要什么开什么。这比"默认全开再关掉"安全得多。很多事故就是图省事默认放行全部,结果数据库、缓存、管理端口全部暴露在公网。
# 查看本机监听端口与连接,辅助确认访问控制是否放行了正确的端口
ss -tlnp
# 查看防火墙状态(本机防火墙与云安全组是两回事,别搞混)
# RHEL/CentOS/Rocky(firewalld)
sudo firewall-cmd --list-all
# Debian/Ubuntu(ufw)
sudo ufw status verbose
六、常见配置错误
错误一:只在安全组放行,忽略网络 ACL。 表现为"规则都配了还是不通"。排查时要两层一起看。
错误二:网络 ACL 忘配出站规则。 表现为"能建立连接但收不到数据"或"超时"。无状态机制下,入站和出站必须成对配置。
错误三:安全组来源写成 0.0.0.0/0 放行了管理端口。 把 22、3389 暴露给全网,是暴力破解的头号目标。管理端口应限制到运维网段或走跳板机/VPN。
错误四:把安全组当黑名单用。 安全组只能允许,屏蔽 IP 要用网络 ACL 的拒绝规则。
错误五:改完规则不验证。 云上访问控制规则改动大多是即时的,但测试时要考虑已有连接的状态。改完用 telnet、nc 或 curl 从真实来源测一遍。
错误六:忽略本机防火墙。 云安全组放行了,但实例里的 firewalld/ufw 或 iptables 规则挡着,一样不通。三层(网络 ACL、安全组、本机防火墙)都要检查。
# 从外部测试端口是否可达(需目标已放行)
# telnet 测试 TCP 端口
telnet 10.0.0.10 3306
# 或用 nc
nc -zv 10.0.0.10 3306
# HTTP 类测试
curl -v http://10.0.0.10/
# 若要在实例内部确认规则,可查看 iptables 规则
sudo iptables -L -n -v
七、排障思路
访问不通时,按"从外到内"的顺序排查,效率最高:
- 确认服务本身在监听。在实例上用
ss -tlnp看端口是否 LISTEN,进程是否存活。 - 检查本机防火墙。firewalld/ufw/iptables 是否放行。
- 检查安全组。入站规则是否放行了来源 IP 和目标端口。
- 检查网络 ACL。入站和出站规则是否都放行。
- 检查路由。子网路由表是否有到目标的路由,网关配置是否正确。
- 检查来源侧。发起访问的一侧是否也有出站限制(尤其是跨 VPC、跨网络时)。
按这个顺序排查,能快速定位是哪一层挡住的。
| 现象 | 可能原因 | 排查点 |
|---|---|---|
| 完全连不上、超时 | 安全组未放行 / 网络 ACL 未放行入站 | 安全组入站、ACL 入站 |
| 能建立连接但无数据 | 网络 ACL 未放行出站 | ACL 出站规则、临时端口范围 |
| 部分来源能连、部分不能 | 来源 IP 限制过严 | 安全组来源网段 |
| 屏蔽某 IP 不生效 | 用了安全组而非网络 ACL | 改用 ACL 拒绝规则 |
| 突然全部不通 | 规则被误改 / 默认拒绝 | 检查最近变更 |
常见问题
Q:安全组和网络 ACL 必须都配吗?
不一定。很多场景只用安全组就够,因为安全组已经能控制实例级访问。网络 ACL 是额外的、子网级的加固层,在需要子网隔离或黑名单时会用上。最小化配置是"只用安全组",更严谨的做法是"两层都配"。
Q:为什么安全组只能允许不能拒绝?
这是白名单模型的设计:默认拒绝,只放行明确允许的。好处是不会因为漏配拒绝规则而意外放行流量。要屏蔽流量,用网络 ACL 的拒绝规则,或不给它允许规则。
Q:网络 ACL 改了规则会断开已有连接吗?
无状态的 ACL 对新建连接即时生效,对已经建立的连接通常不影响,除非连接的空闲超时到期。安全组调整也类似,主要影响新建连接。
Q:安全组的入站默认拒绝,为什么出站默认允许?
这是为了方便(实例默认能访问外网更新、拉取依赖)同时保证安全(外部默认进不来)。但出站默认全放行也存在数据外泄风险,高安全场景应改为默认拒绝出站、按需放行。
Q:同一个安全组能用在多个可用区的实例上吗?
可以。安全组是 VPC 级别的资源,能绑定到同一 VPC 内任意子网、任意可用区的实例,这正是它比网络 ACL(绑定子网)更灵活的地方。
总结
安全组和网络 ACL 是云上两层访问控制,作用位置和机制都不同。
- 安全组在实例级、有状态、白名单(只有允许规则)、默认拒绝入站,负责精细控制单台机器的访问。
- 网络 ACL 在子网级、无状态、支持允许和拒绝、按规则号匹配,负责子网级隔离和黑名单。
- 有状态和无状态决定了:安全组不用管回程流量,网络 ACL 必须成对配置入站和出站,否则会出现"连上但无数据"。
- 组合思路是网络 ACL 做粗粒度隔离、安全组做精细控制,遵循最小权限,管理端口限制来源。
- 排障按"服务监听 → 本机防火墙 → 安全组 → 网络 ACL → 路由"的顺序查,能快速定位问题层。
企业QQ咨询




