资讯动态

ACL访问控制列表从原理到实操:配置方法与排障指南

发布时间:2026/9/16 3:43:27 来源:尧图企业网站定制
到今天为止我的网络学习日志已经写到第26篇了。前面几篇一直在折腾路由协议、接口调试和基础排障这篇终于轮到 ACL。ACL 全称 Access Control List翻译过来就是访问控制列表网工圈子里基本都直接叫“ACL”。它不是某个厂商的私有功能而是几乎所有网络设备都支持的通用机制主要用来做流量过滤、访问限制、远程管理白名单甚至还能配合策略路由、QoS 使用。这篇文章我会从原理讲到配置再讲配置过程中最容易踩的坑最后聊一下这个思路在 Linux、Redis、对象存储里的变体把这些内容串起来之后你会发现 ACL 远比你想象的更通用。我在刚接触网络设备时觉得 ACL 背完编号范围就完事了标准 ACL 是 2000 到 2999高级 ACL 是 3000 到 3999二层 ACL 是 4000 到 4999。但真正到了设备上一配发现问题一个接一个通配符掩码写反、规则顺序不对、接口方向选错、隐式拒绝导致断网这些我都踩过。这篇文章不是念概念而是把原理、配置、排障经验一起写清楚适合刚入行的网工、准备认证考试的同学还有那些做了几年运维但没系统性摸过 ACL 的人。1. ACL到底是什么解决什么问题1.1 用小区门禁来理解ACLACL 的本质是一张带顺序的名单。你可以把它想象成小区门口保安手里的门禁表上面写着几号楼几单元的业主可以进外卖车辆某个时间段不能进访客需要登记后才能进。网络设备收到报文后也会按照这张“名单”逐条核对。名单上写了 permit就放行写了 deny就丢弃如果报文条件哪一条都不匹配那最终结果就是默认拒绝。这个“默认拒绝”非常关键。很多人配置 ACL 时以为只影响自己写的那几条规则实际上只要把这个 ACL 绑到接口上而规则里又没有最后兜底的 permit那所有没被明确允许的流量都会被丢弃。用门禁来类比就是保安手里的名单只写了几个放行的名字那么名单之外的所有人都进不了门。理解这一点你后面配置的时候就不会犯“一绑ACL就断网”的错。1.2 ACL在网络设备中处于什么位置ACL 不是一个独立协议它本身不参与路由计算也不像 OSPF、BGP 那样有邻居关系。它只是一张规则表被接口、VLAN、VTY、QoS 分类等模块调用。设备收到报文后如果发现接口上绑定了 ACL就会进入匹配流程。匹配通过则继续转发或交给后续处理匹配失败则直接丢弃。这里有个容易忽略的细节ACL 通常只过滤“穿越设备”的流量也就是从一个接口进、再从另一个接口出的流量。对于设备自身发起的流量比如路由器自己 ping 出去的探测报文或者自己主动发起的 SSH 连接你在普通接口上绑 ACL 不一定管得住。要限制远程管理得把 ACL 绑到 VTY 用户界面或者用控制平面策略去做。这个细节在实际项目中很常见我在后面配置部分也会讲。1.3 常见ACL分类和编号范围不同厂商的 ACL 分类基本一致只是在编号范围和关键字上有细微差异。以华三H3C设备为例常见的 ACL 类型如下表。ACL类型编号范围匹配依据典型场景标准 ACL2000-2999源 IP 地址控制“哪个网段能进来”高级 ACL3000-3999源/目的 IP、协议、端口、TCP 标志、ICMP 类型业务精细化访问控制二层 ACL4000-4999源/目的 MAC、VLAN、802.1p 优先级局域网内部过滤IPv6 ACL2000-2999 等IPv6 地址和高级匹配项下一代网络环境标准 ACL 的特点是简单粗暴只看源 IP。比如你想拒绝某个内网网段访问公司服务器那标准 ACL 就够了。但如果你希望“只拒绝某个网段访问服务器的 Web 服务但允许它访问 SSH 服务”标准 ACL 就没法做到必须用高级 ACL 去同时匹配目的 IP 和端口。二层 ACL 在交换机上用得比较多比如按终端 MAC 地址做准入控制防止有人乱改 IP 接入内网。IPv6 ACL 的匹配能力和 IPv4 的高级 ACL 类似只是地址格式和命令写法不同。2. ACL的工作原理报文的匹配过程2.1 从匹配到执行ACL的工作流程ACL 的匹配流程可以概括为“顺序匹配命中即停”。设备从第一条规则开始拿当前报文特征和规则条件做比对只要有一条规则匹配就立刻执行这条规则对应的动作也就是 permit 或者 deny后面所有规则都不再看。为什么要这样设计一方面是为了性能硬件转发的流水线希望匹配过程尽量短不能每条报文都翻完整张 ACL 表另一方面是让规则结果可预期。工程师只要按照“先特殊、后一般”的顺序编排规则就能精确控制哪些流量先命中。整个过程很像站在一排安检通道前第一个通道放行所有带登机牌的人第二个通道拒绝携带液体的人只要被第一个通道拦下就不会再走到第二个通道。如果整个规则表从头到尾都没有匹配项设备会执行一个看不见的“隐式拒绝”。换句话说ACL 的默认动作是 deny all。这也是为什么很多人在配置完 ACL 之后发现网络不通十有八九是没有加一条兜底 permit。2.2 通配符掩码最容易被用错的一个点ACL 在做地址匹配时使用的是通配符掩码也有人叫反掩码。它和子网掩码长得像但含义正好相反。子网掩码里的“1”表示网络位必须匹配“0”表示主机位可以不同。通配符掩码正好反过来“0”表示这一位必须精确匹配“1”表示这一位不需要关心。以最常见的网段为例配置规则“source 192.168.1.0 0.0.0.255”意思是前三个数字 192、168、1 必须完全一致最后一个数字可以是 0 到 255 之间的任意值。这正好等价于匹配 192.168.1.0/24 这个网段。计算通配符掩码有一个很简单的办法把子网掩码的每一段都用 255 去减一下。比如 255.255.255.0 对应的通配符掩码是 0.0.0.255255.255.255.240 对应的通配符掩码是 0.0.0.15。目标范围子网掩码通配符掩码192.168.1.0/24255.255.255.00.0.0.255192.168.1.0/25255.255.255.1280.0.0.127192.168.1.0/28255.255.255.2400.0.0.15单个主机 192.168.1.10255.255.255.2550.0.0.0所有地址0.0.0.0255.255.255.255我见过很多人在配置时报错或匹配不到预期地址就是因为把子网掩码直接当成了通配符掩码。比如你想匹配 192.168.1.0/24结果写了“source 192.168.1.0 255.255.255.0”。设备不会报语法错误但它会按通配符的规则去解释前 24 位被置为“1”完全不关心最后 8 位被置为“0”必须等于 0。最后得到的匹配范围其实是“任意 IP 地址且最后一位是 0”跟你想要的 192.168.1.x 差了十万八千里。2.3 规则顺序和默认动作ACL 里的每一条规则都带一个规则编号设备默认按编号从小到大依次匹配。华三设备上如果你不手动指定编号系统会自动分配通常起始编号是 0步长是 5也就是先产生 0、5、10、15 这样的编号。如果你希望某条规则排到更前面可以手动指定一个更小的编号比如 rule 1、rule 2这些规则会自动插入到合适的位置。规则顺序对最终效果影响极大。同一个 ACL 里如果前面先写了一条“deny ip”把所有流量全部拒绝那么后面写的任何“permit tcp”规则都不会生效因为报文在第一条就被丢掉了。正确的编排习惯一般是先放行最需要的、最具体的流量再拒绝不想要的流量最后再加一条宽松的兜底规则。这有点像写防火墙策略先精确放行再拒绝例外最后做默认策略。2.4 标准ACL和高级ACL的匹配能力标准 ACL 的匹配能力非常有限它只关心源 IP 地址所以只能做粗粒度的控制。使用场景一般是“这个网段能不能访问某个区域”这种简单需求。但它的优点也很明显规则少、性能开销小、容易理解适合在核心链路入口处先做一层粗过滤。高级 ACL 的匹配项丰富得多源 IP、目的 IP、协议类型TCP、UDP、ICMP、IP 等、源端口、目的端口、TCP 标志位、ICMP 类型。这意味着你可以写出类似“拒绝 192.168.20.0/24 访问服务器 192.168.100.10 的 TCP 80 端口但允许它 ping 通服务器”这样的精确规则。这也是生产环境中用得最多的 ACL 类型。规则越精细对转发性能的要求通常也越高但现代设备基本都能扛得住关键是规则数量不要膨胀到失控。3. 基础配置实操H3C MSR路由器上的ACL实验3.1 一个具体的需求场景纸上谈兵没意思我直接拿一个实际场景来讲。假设我手里有一台 H3C MSR20-20 路由器GigabitEthernet0/0 接口连接内部办公网GigabitEthernet0/1 接口连接服务器区。内部办公网有两个网段研发网段 192.168.10.0/24 和测试网段 192.168.20.0/24。服务器区有一台 Web 服务器地址是 192.168.100.10。现在需求是研发网段可以正常访问 Web 服务器的 80 端口。测试网段不能访问 Web 服务器的 80 端口。测试网段可以 ping 通 Web 服务器。其他流量按照正常路由转发不做额外限制。这个需求用标准 ACL 无法实现因为必须要匹配目的地址和目的端口所以得用高级 ACL编号选 3000。3.2 标准ACL配置最简单的过滤虽然上面的需求要用高级 ACL但标准 ACL 依然是入门必学的配置。它适合做粗粒度过滤。比如我只想拒绝 192.168.20.0/24 访问任何服务器那可以用标准 ACL 2000。system-view acl basic 2000 rule 5 permit source 192.168.10.0 0.0.0.255 rule 10 deny source 192.168.20.0 0.0.0.255 rule 15 permit quit这里有个细节要注意我最后加了一条rule 15 permit没有任何源地址限制等价于“放行其他所有流量”。如果不加这一条ACL 的默认行为会把所有未匹配的流量全部丢掉到时候不仅上面两个网段受影响其他所有业务都会断。很多人第一次配标准 ACL 时只写了 deny结果整个网络瘫痪就是这个原因。配置完成后可以用display acl 2000查看规则。如果规则命中计数在增长说明流量确实被匹配到了如果计数不增长就要思考是不是报文压根没走到这个 ACL或者方向选错了。3.3 高级ACL配置精确到端口回到刚才的需求我需要在系统视图下创建一个高级 ACL编号 3000。system-view acl advanced 3000 rule 5 permit tcp source 192.168.10.0 0.0.0.255 destination 192.168.100.10 0 destination-port eq 80 rule 10 deny tcp source 192.168.20.0 0.0.0.255 destination 192.168.100.10 0 destination-port eq 80 rule 15 permit icmp source 192.168.20.0 0.0.0.255 destination 192.168.100.10 0 rule 20 permit ip quit逐条解释一下。rule 5表示允许源地址是 192.168.10.0/24 的 TCP 报文访问 192.168.100.10 的 80 端口。这里destination 192.168.100.10 0表示目的地址精确匹配单台主机destination-port eq 80表示目的端口等于 80。rule 10的作用正好相反把测试网段访问 Web 服务的流量拒绝掉。rule 15是允许测试网段 ping Web 服务器因为 ping 用的协议是 ICMP为什么能 ping 通服务器而不受影响。最后我写了rule 20 permit ip把其他所有 IPv4 流量都放行避免隐式拒绝把自己网断掉。这条高级 ACL 已经能覆盖需求里的前三点。如果你希望更严格可以把最后一条去掉这样除研发网段访问 Web 服务、测试网段 ping 服务器之外所有流量都会被拒绝。但在没有充分把握之前建议先保留兜底 permit观察业务正常后再收紧。3.4 把ACL绑定到接口inbound和outbound选择ACL 创建好之后不会自动起作用必须绑定到接口上。以华三设备的现代版本为例绑定命令是traffic-filter。我选择的绑定位置是内网入口的 GigabitEthernet0/0方向是 inbound。interface GigabitEthernet0/0 traffic-filter inbound acl 3000 quit这样配置的含义是所有从 GigabitEthernet0/0 进入路由器的报文都要先经过 ACL 3000 的匹配。如果源地址是 192.168.20.0/24目的端口是 80就直接被丢弃。之所以选择 inbound是因为在靠近发起方的入接口做过滤更高效报文刚进来就被处理掉不会白白占用到服务器侧接口的带宽。如果你用的是老版本的 MSR 设备接口下可能不是traffic-filter而是firewall packet-filter之类的命令。可以在接口视图下打一个问号看支持哪些命令不同平台差异确实存在。配置完成后用display traffic-filter applied record可以确认 ACL 是否成功下发。关于方向的判断可以这样记站在你绑定的这个接口上看数据包的流动方向。数据包从外部进入接口对应 inbound数据包从设备内部发出接口对应 outbound。如果方向选错了就会出现“为什么我绑了 ACL 一点反应都没有”或者“为什么服务器无法主动访问外网”这种让人摸不着头脑的问题。3.5 管理接口场景和IPv6场景的ACL配置除了普通数据口ACL 还可以绑定到 VTY 用户界面用来限制谁可以远程登录设备。这个在实际运维中非常实用。比如我只允许 192.168.10.0/24 这个管理网段通过 Telnet 或 SSH 登录路由器其他地址统统拒绝可以这样配acl basic 2001 rule 5 permit source 192.168.10.0 0.0.0.255 rule 10 deny quit user-interface vty 0 4 acl 2001 inbound quit这里的user-interface vty 0 4表示虚拟终端线路SSH、Telnet 登录都会落到这些线路上面。绑定 ACL 后只有源地址匹配的请求才能建立远程会话。这个操作比直接在接口上 ACL 更精准因为它控制的是“管理面”而不是数据转发面。IPv6 环境下ACL 的结构和 IPv4 类似但命令关键字不同。华三设备上要使用acl ipv6 basic或者acl ipv6 advanced来创建 IPv6 ACL。配置示例acl ipv6 basic 2000 rule 5 permit source 2001:db8:1::/64 rule 10 deny quit interface GigabitEthernet0/0 traffic-filter inbound ipv6 acl 2000 quit注意接口下绑定 IPv6 ACL 时要多写一个 ipv6 关键字否则设备会把acl 2000当成 IPv4 ACL 去匹配 IPv4 报文IPv6 流量就不会被过滤。这个坑我在学习 IPv6 安全实验时踩过排查了半天才发现是绑定命令里少了 ipv6 关键字。4. ACL配置中的常见问题与排查4.1 通配符掩码错误为什么规则总匹配不上热词里有一条特别典型叫“acl 有通配符 无法匹配掩码”。很多新手在配 ACL 时会把高级路由里的子网掩码习惯直接带过来。比如想匹配 192.168.1.0/24在路由协议里写192.168.1.0 255.255.255.0没问题但 ACL 里这样写就会出问题。前面已经说过ACL 里255.255.255.0会被当成通配符掩码来解析它的含义是“前 24 位不关心最后 8 位必须等于 0”于是这条规则实际上匹配的是任意地址最后一位为 0 的报文而不是 192.168.1.x。设备不会报错但流量就是匹配不上或者匹配到了完全出乎意料的流量。排查方法其实很简单用display acl all查看规则内容看看“source”后面的反掩码是不是你预期的0.0.0.255。如果显示的是255.255.255.0就说明写反了。我记得自己在一次割接中就是因为这个低级错误导致测试网段一直能访问服务器最后把 ACL 规则调出来一看source 掩码写成了子网掩码改过来之后一切正常。4.2 规则顺序问题先deny后permit的坑ACL 在执行时是顺序匹配、命中即停。如果你写了一条大范围的 deny放在所有 permit 前面那么后续 permit 永远没有机会执行。举个极端例子acl advanced 3000 rule 5 deny ip rule 10 permit tcp source 192.168.10.0 0.0.0.255 destination 192.168.100.10 0 destination-port eq 80这条规则会导致所有 IP 报文在rule 5直接被丢弃rule 10形同虚设。从逻辑上看rule 10是想放行研发网段访问 Web 服务器但因为它排在 deny 后面根本不会被执行到。解决办法有两个一是调整顺序把具体放行规则放到前面二是临时插入一条编号在中间的规则比如rule 8让它排在rule 5和rule 10之间。调整之后一定要用display acl 3000确认规则的实际顺序不要只看命令行输入顺序。规则上如果带有计数器还可以通过匹配计数的增长判断流量到底命中了哪一条。4.3 方向搞反inbound和outbound的区分ACL 绑到接口上时方向选错是非常常见的故障来源。很多人看到内网要访问服务器就顺手把 ACL 绑到服务器接口上结果方向选成了 inbound。这个方向处理的是“从服务器进入路由器的流量”也就是服务器主动发往外部的流量和你本来想控制的“内网到服务器”方向正好相反。正确的做法是先认清数据流向。内网 PC 访问服务器数据包从 PC 出发经过路由器连接内网的接口进入路由器再从连接服务器的接口出去。你可以把 ACL 绑在内网接口的 inbound 方向也可以绑在服务器接口的 outbound 方向。两个方向的效果在某些场景下可能不完全一样因为 outbound 方向的过滤发生在路由查询之后如果你还想做策略路由等操作要提前考虑规则的生效顺序。我在实验环境里通常会绑在靠近源端的入方向这样过滤效率更高也不会影响服务器侧接口上可能存在的其他策略。排查方向问题时用display traffic-filter applied record查看绑定情况再结合display acl的计数就能定位。4.4 隐式拒绝一配ACL就断网这个话题值得单独拿出来说。ACL 默认有一条看不见的规则那就是“所有未匹配流量全部拒绝”。很多人只写了 deny 规则没有写兜底 permit结果一绑接口整个网络马上断掉。我自己的习惯是配置 ACL 之前先画一张表把要放行的流量、要拒绝的流量都列出来最后确认需不需要放行其他流量。如果不需要放行其他流量那也要意识到“默认拒绝”就是你想要的效果如果需要放行那就必须显式加一条 permit 规则。远程管理设备时尤其要小心如果管理地址不在 permit 规则里ACL 一旦绑上接口你可能瞬间失去设备访问权限。这时候只能靠 console 口重新登录或者等待设备上的管理保护机制生效。4.5 命令速查表排错时拿来就用下面这张表是我在实际排障中会用到的高频命令你可以保存下来做参考。命令作用使用建议display acl all查看所有 ACL 规则和命中计数先看规则顺序再看计数增长display acl 3000查看指定 ACL确认通配符掩码、端口是否写对display traffic-filter applied record查看 ACL 在接口上的下发情况解决“绑了没生效”问题display packet-filter查看接口包过滤状态老版本设备上用得多reset acl counter 3000清空 ACL 计数重新验证前先清零避免被旧数据误导display ip interface brief查看接口 IP 和状态确认你要绑的接口名字是否写错排障的顺序一般是先确认 ACL 是否创建成功再确认 ACL 是否绑定到了正确的接口和方向最后用命中计数验证。只要这三步查完90% 的问题都能定位出来。5. ACL思想在网络之外的延伸5.1 Linux中的文件ACLsetfacl与getfaclACL 的思想不止存在于网络设备。Linux 文件系统里也有一套访问控制列表用来弥补传统 ugo 权限的不足。大家都知道 Linux 文件权限分属主、属组和其他用户三类但如果想给某个特定用户单独授权又不希望把他加进某个组里传统权限就很麻烦。这时候就要用文件 ACL。比如我有个目录/data属主是 root属组是 root其他用户没有任何权限。现在要让用户 zhangsan 能读写这个目录可以这样操作setfacl -m u:zhangsan:rw /data getfacl /data执行完之后ls -l /data的结果最后会出现一个号表示这个目录上存在 ACL 条目。getfacl可以看到具体权限明细。这套机制和网络 ACL 的“在通用权限之外再单独加一条规则”思路几乎一模一样理解了网络 ACL再学 Linux ACL 会非常快。5.2 Redis里的ACL账号与命令权限控制Redis 从 6.0 开始引入 ACL 功能到了 Redis 7 已经非常成熟。它允许你创建多个账号给每个账号分配不同的密码、可执行的命令和可访问的 key 前缀。比如我创建一个应用账号只允许读写app:*前缀的 key只能执行 get、set、ttl 这类命令可以这样写ACL SETUSER appuser on appPass123 ~app:* get set ttl如果是在 Docker 里部署 Redis 7可以通过挂载 redis.conf 和独立的 aclfile 来管理账号避免每次容器重启后配置丢失。简单做法是在 redis.conf 里设置aclfile /etc/redis/users.acl然后把账号规则写入 users.acl再通过 volume 挂载进去。这套做法的价值在于即使同一个 Redis 实例被多个业务共用也能把数据可见性和命令权限隔离开来。5.3 对象存储OSS的ACL报错处理对象存储里的 ACL 概念也一样。资源有私有、公共读、公共读写等几种权限级别。有时候上传文件会报错提示AccessDenied: Put Object ACL is not allowed。这个报错并不是说上传这个动作本身被拒绝而是指你试图修改 Object 的 ACL但当前 Bucket 的权限策略或账号权限不允许这样做。遇到这个报错时先不要急着改代码。第一步打开 Bucket 的权限设置看看是不是关闭了 Object 级别的 ACL 修改第二步检查使用的子账号或临时凭证是否被授予了PutObjectAcl权限比如 OSS 的oss:PutObjectAcl。如果业务上根本不需要修改文件 ACL那就在上传请求里去掉了 ACL 相关参数问题一般就解决了。ACL 这个东西如果只把它当成命令来背很容易越学越乱。我自己在实际项目里养成的一个习惯是不管在哪种设备或系统上操作动手前都会把“谁、对什么资源、做什么动作、允许还是拒绝”先列成表格再转换成对应的规则。网络设备上的 ACL、Linux 里的 setfacl、Redis 里的 ACL 账号本质上都是同一套思路。把这层底层逻辑想通了换到任何平台都只是换一种命令行写法而已。这篇日志写到这我也该去把实验环境里的规则再清理一遍了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价