2、ACL工作原理:匹配顺序、隐式拒绝与路由器交互
ACL这东西,说白了就是一张规则表。但规则怎么查、查到以后怎么办、路由器内部到底干了啥——这些才是真正容易出坑的地方。我带过不少新人,配置ACL时语法全对,结果流量就是不通,十有八九是没搞懂工作原理。
2.1 ACL匹配顺序:从上到下,命中即停
ACL的匹配规则很简单:从上往下逐条检查,一旦匹配就立即执行动作,不再继续往下看。这个机制叫"顺序匹配,首次命中"。
举个例子,你写了这么几条规则:
access-list 100 permit ip 192.168.1.0 0.0.0.255 any
access-list 100 deny ip 10.0.0.0 0.255.255.255 any
access-list 100 permit ip any any
当一个来自192.168.1.10的包到达时,路由器先看第一条——匹配了,直接放行,后面两条根本不会检查。但如果来的是10.1.1.1,第一条不匹配,接着看第二条——匹配了,直接丢弃,第三条permit any any也救不了它。
核心要点:ACL的规则顺序就是执行顺序。把最精确、最常用的规则放在前面,把范围大的规则放在后面。我见过有人把deny any any放在第一条,结果所有流量都被干掉,排查了半天才发现是顺序问题。
这里有个容易忽略的细节:标准ACL只能检查源IP,扩展ACL可以检查源IP、目的IP、端口、协议等。但匹配顺序的逻辑是一样的——逐条匹配,命中即停。
2.2 隐式拒绝规则:看不见的"最后一道墙"
每条ACL的末尾,都藏着一条看不见的规则:deny any any(标准ACL)或deny ip any any(扩展ACL)。这就是所谓的"隐式拒绝"。
为什么会这样?你想想看,如果ACL匹配完所有规则都没命中,路由器该怎么办?总得有个默认动作吧。思科的设计哲学是"默认拒绝一切",这样更安全。
注意:隐式拒绝规则是自动添加的,你看不到也删不掉。这意味着:
- 如果你只写了permit规则,没写deny规则,没匹配到的流量照样会被拒绝
- 如果你想让所有流量都通过,必须在末尾显式加上
permit ip any any - 隐式拒绝会记录日志吗?默认不会。但你可以用
log关键字让显式规则记录日志
我在项目中遇到过这么个事:某公司新上了一台路由器,运维配了ACL只允许内网访问服务器,结果外网用户全连不上。查了半天,发现ACL里只写了permit tcp 10.0.0.0 0.255.255.255 host 192.168.1.100 eq 80,没写deny any any——但隐式拒绝已经帮他们干了这件事。他们以为没写deny就是允许,其实正好相反。
避坑指南:我曾经在配置远程管理ACL时,只允许了特定管理IP的SSH流量,忘了加permit ip any any,结果把自己也锁在外面了。后来我养成了一个习惯:在ACL末尾显式写一条deny ip any any log,这样既能明确拒绝动作,又能记录被拒绝的流量,方便排障。
2.3 ACL与路由器的交互:数据包处理流程
ACL不是独立工作的,它和路由器的转发流程紧密耦合。搞清楚这个流程,你才能知道ACL该放在哪个接口、哪个方向。
路由器处理一个数据包时,大致走这么几步:
- 接收数据包:从入接口收到帧,检查CRC,解封装
- 入方向ACL检查:如果入接口配置了入方向ACL,先匹配。拒绝就直接丢弃
- 路由查找:查路由表,决定出接口和下一跳
- 出方向ACL检查:如果出接口配置了出方向ACL,再匹配。拒绝就丢弃
- 封装转发:重新封装帧,从出接口发出去
你看,ACL可以在两个位置介入:入接口(inbound)和出接口(outbound)。方向搞错了,ACL就不起作用。
经验之谈:我个人习惯把ACL尽量放在入方向。原因很简单——流量一进来就过滤掉,省得路由器白费力气查路由表。特别是拒绝大量非法流量时,入方向ACL能显著降低CPU负载。
但也不是所有场景都适合入方向。比如你想控制从内网访问外网的流量,但内网有多个网段,入方向ACL要写很多条。这时候放在出方向可能更清晰。
下面这张图展示了ACL在路由器转发流程中的位置:
2.4 方向选择实战:入方向 vs 出方向
很多新手搞不清ACL该放哪个方向。我总结了一个简单判断方法:
| 场景 | 推荐方向 | 理由 |
|---|---|---|
| 过滤外部非法访问 | 入方向 | 流量一进来就拒绝,省路由查找 |
| 控制内网访问外网 | 出方向 | 可以基于目的IP/端口精确控制 |
| 限制特定用户访问服务器 | 入方向(服务器接口) | 在服务器接口入方向过滤,不影响其他流量 |
| 记录被拒绝的流量 | 入方向 | 拒绝发生在早期,日志更完整 |
一个小技巧:配置ACL时,先想清楚"我要控制谁访问谁"。如果控制的是"谁进来",用入方向;如果控制的是"谁出去",用出方向。记住这个口诀:入控进,出控出。
2.5 常见误区与排障思路
最后分享几个我踩过的坑,你遇到了可以直接对照排查:
- ACL没应用到接口:配置了ACL但忘了
ip access-group,等于没配。用show running-config interface检查 - 方向搞反了:入方向写成出方向,流量照常通过。用
show ip access-list查看匹配计数,如果一直是0,大概率方向错了 - 隐式拒绝导致意外断网:只写了permit没写deny,以为其他流量能过。记住:ACL默认拒绝一切
- 规则顺序不对:精确规则放在后面,被前面的宽泛规则覆盖了。检查顺序,把最具体的规则放前面
- ACL没考虑回程流量:只配了入方向ACL允许流量进来,但出方向没配允许回包,导致单向通信。双向ACL都要考虑