1. 从双向ACL写到吐说起CBAC到底在解决什么问题前阵子有人在技术群里问内网到外网的ACL写了出方向回来的方向也补上了为什么DNS时好时坏、FTP能登录却列不出目录、SIP能注册却听不到声音。这个问题我在早年做园区网出口的时候撞过不止一次本质是拿一张无状态的规则表去描述有状态的通信过程。网络安全中的CBACContext-Based Access Control基于上下文的访问控制与认证代理技术正好就是治这个病的两味药一味管连接上下文一味管人的身份。这篇文章想讲清楚三件事CBAC是怎么靠一张会话表把单向放行变成有来有回的认证代理是怎么让一次浏览器里的登录动作变成一段临时准入规则的这两套东西拼到一起之后配置怎么落、坑在哪、什么时候该换方案。适合已经能看懂基础ACL、摸过防火墙特性集、但被多通道协议和非标准端口折磨过的朋友也适合还在用纯ACL扛出口的新手看完至少能知道自己的方案缺了哪块。我先把结论摆出来无状态ACL的问题不在于写得不够多而在于它压根不记事儿。它像一个只认名单的门卫名单上没写的人一律拦下至于这个人刚刚是不是从里面出来的、出来时带没带东西、什么时候该回来门卫一概不关心。你要让返回流量通过就得提前把回来的门也开着而返回流量的源端口在很多协议里根本是随机的于是你就只能开一个大范围的端口段安全性瞬间归零。1.1 无状态ACL在真实协议面前的三种塌方我把这些年遇到的翻车情况归了三类基本能覆盖大部分场景。第一类是端口不固定。DNS查询从UDP高端口出去回包的源端口是53、目的端口是你那个随机高端口ACL如果只放行udp any eq 53 any这种写法回来那一下就被拍死了。SIP、RTP、各种P2P协议、游戏联机协议全是这个路子。第二类是多通道协议。FTP是最典型的控制连接走21端口数据连接在主动模式下由服务器反向连客户端在被动模式下由客户端连服务器的一个随机高端口而这个端口号是在控制连接的应用层报文里协商出来的。ACL看不懂应用层内容自然没法提前开这个口子。第三类是时序敏感。TCP三次握手、FIN/RST的收尾、连接复用这些东西在无状态ACL眼里都是一个个孤立的包。你放行了SYN回包的SYN-ACK因为源端口不对被拦连接就卡死了。场景纯ACL表现根因DNS查询请求发出响应被丢弃响应目的端口是随机高端口FTP被动模式列目录能登录ls卡死超时数据端口由应用层协商ACL不可见SIP语音注册成功无声音RTP端口在SDP报文里协商长连接业务偶发中断无会话跟踪FIN/RST被误拦1.2 CBAC的本质把规则表升级成记录表CBAC做的事情说穿了很简单它盯着从受信侧往非受信侧发出的每一个包把五元组、协议状态、时间戳记到一张会话表里然后在反向的ACL上动态地开一个只对这条会话有效的洞。这个洞业内叫pinhole中文常翻成穿孔。等会话结束或者超时了这个洞自动收回。所以你在外部接口上看到的ACL永远只有一条deny ip any any但实际上流量是通的——因为会话表里有记录设备会临时把permit条目插到ACL最前面。这个思路的价值在于安全边界从我允许哪些地址和端口变成了我允许哪些会话。前者是静态的、粗粒度的、需要人肉维护的后者是动态的、细粒度的、跟着协议走的。你可以把外部接口的入向ACL写成全拒绝理论上攻击面比那种开了一大段端口的配置小得多。提示CBAC 只处理它看得见的会话。如果流量路径不对称去和回走了不同设备会话表就对不上回来那半截照样被丢。这一点在双出口、策略路由、链路负载均衡的环境里必须提前想清楚。2. CBAC会话表的建立与老化状态化过滤的真实运转过程要真正用好CBAC光知道它会记会话是不够的得知道这张表里存了什么、什么时候生、什么时候死。因为绝大部分配置看起来没问题但不通的故障根子都在会话表的生命周期上。2.1 一条TCP会话从SYN到FIN会话表里发生了什么假设内网10.10.10.20访问外网198.51.100.80的80端口。第一个SYN包从内网接口进入设备入向ACL先过一遍通过后进入检查引擎inspect。检查引擎发现这是一条新会话的起始包于是在会话表里建一条记录字段大致包括源IP、源端口、目的IP、目的端口、协议号、当前状态SYN_SENT、已经过的时间、剩余超时时间。包正常转发出去。回程的SYN-ACK从外部接口进来外部接口的入向ACL本来是deny ip any any但设备在匹配ACL之前会先查会话表发现这条流属于一条已知会话于是直接放行同时顺手在外部的动态ACL里插一条permit。这就是为什么你在show ip access-lists里能看到带(dynamic)标记的条目。连接建立后进入ESTABLISHED状态。数据来回传会话表里的计时器不断刷新。等到一方发FIN状态转成FIN_WAIT等另一方也FIN或者超时条目才被删除动态ACL条目同时收回。整个过程里管理员完全不需要关心端口号是多少。这就是状态化过滤相比无状态ACL最核心的优势——它把端口协商这件事从管理员手里接过去了。2.2 超时参数直接决定会话和穿孔的存活时间默认超时值对很多业务来说是不够的尤其是一些长连接的业务系统数据库连接池、监控上报、MQ长轮询。我见过最典型的故障是某个后台服务每5分钟发一次心跳但TCP空闲超时被设成了很短的值会话提前老化回来的时候被拦业务表现为每隔一段时间断一次重连就好。常用的调优命令大致是这些ip inspect tcp synwait-time 30 ip inspect tcp idle-time 3600 ip inspect tcp finwait-time 5 ip inspect udp idle-time 30 ip inspect dns-timeout 5参数默认量级调整建议影响tcp idle-time3600秒长连接业务可上调至7200调太大占会话表调太小误断udp idle-time30秒视业务心跳周期定UDP无连接状态只能靠时间猜dns-timeout5秒一般不动DNS是单问单答短超时合理synwait-time30秒内网可下调至10缩短半开连接占用时间finwait-time5秒一般不动影响连接关闭后的残留时间这几个值没有标准答案得按业务特征来。我的习惯是先按默认跑一周用show ip inspect sessions观察实际会话的存活分布再针对性调整而不是一上来就凭感觉改。2.3 半开连接才是真正的杀手DoS阈值怎么算CBAC有一组参数专门用来防SYN洪泛逻辑是当半开连接数或者每秒新建连接数超过高水位设备开始主动删除最老的半开连接甚至临时拒绝新连接等降到低水位以下再恢复。相关命令ip inspect max-incomplete high 1000 ip inspect max-incomplete low 800 ip inspect one-minute high 1000 ip inspect one-minute low 800 ip inspect tcp max-incomplete host 50 block-time 0高低水位之间要留出足够的回差我一般按1:0.8来设。回差太小会导致设备在阈值附近反复横跳表现是业务时通时不通比直接拒绝还难查。tcp max-incomplete host这个参数特别值得说。它限制的是单个源IP能占用的半开连接数默认50。有些老旧的打印服务、扫描器、或者被感染的终端会瞬间发起几百个连接把整台设备的会话资源吃光导致其他所有人上不了网。这个参数就是用来把这种单个坏邻居关进笼子里的。注意block-time设为0意味着不封禁源IP只是拒绝新连接。设成非0会在一段时间内完全阻断该源副作用是如果误判了正常业务恢复要等封禁期结束。3. 应用层协议识别pinhole动态开放才是CBAC的核心价值如果CBAC只会看IP和端口那它和一个普通的会话跟踪模块没区别。它真正值钱的地方在于能解析一部分应用层协议从报文内容里读出后续要用的端口号提前把洞开好。这个能力业内一般叫ALGApplication Layer Gateway或者协议检测。3.1 为什么FTP必须开检测才列得出目录拿FTP被动模式举例。客户端连上服务器的21端口输入用户名密码一切正常。然后客户端敲ls客户端发一条PASV命令服务器回一个227 Entering Passive Mode (198,51,100,80,195,44)。这串数字里前四段是服务器IP后两段是端口的高字节和低字节195×2564449964。也就是说接下来客户端要去连198.51.100.80的49964端口。没有FTP检测的时候设备看到的是一个全新的、目的端口49964的连接请求出方向可能放行了但回来的包在入向ACL上被deny ip any any拦掉于是ls卡住直到超时。开启ip inspect name CBAC-OUT ftp之后检查引擎会解析这条227响应把198.51.100.80:49964这个信息提取出来预先在动态ACL里开好口子。后续的数据连接就能正常建立。同样的逻辑适用于一大票协议。我把常见的检测项整理了一下检测项解决的核心问题是否建议常开tcp/udp基础状态跟踪必须ftp数据连接端口协商有FTP业务时开tftpUDP侧端口协商有网络设备备份需求时开smtp/esmtp邮件内容检查与命令过滤有自建邮件网关时开httpURL过滤、Java Applet阻断按需sipSDP中的RTP端口协商有语音业务时开h323/rtsp多媒体信令与媒体流按需dns查询响应的短超时处理建议开rpc/sunrpc端口映射器查询有NFS需求时开netshow/realaudio流媒体老方案才需要3.2 检测开得越多越安全这是个误解新手容易犯的错是把ip inspect name能加的都加上觉得覆盖面越广越好。实际上每个检测项都在消耗CPU和内存而且检测引擎本身也是攻击面。历史上不止一次出现过因为某个ALG解析畸形报文导致设备异常的例子。我的做法是默认只开tcp、udp、dns这三项作为基线其余按实际业务逐个添加并且每加一项就记录一次添加理由和业务归属。半年后回看通常能砍掉三分之一——很多业务早就下线了检测项还挂着。ip inspect name CBAC-OUT tcp ip inspect name CBAC-OUT udp ip inspect name CBAC-OUT dns ip inspect name CBAC-OUT ftp ip inspect name CBAC-OUT sip这份清单看起来朴素但足够撑起一个中型园区的出口。真要跑满几十个检测项那说明业务复杂度已经超出CBAC的舒适区了该考虑上更专业的设备。3.3 检测和ACL的配合关系要说清楚有一件事必须讲明白CBAC的检测不能替代ACL它是ACL的补充。入向ACL该拦的还是要拦检测只是在ACL的基础上针对已建立的会话临时放行。所以正确的写法是内部接口入向挂ACL做源地址管控哪些网段能出去同时挂inspect做会话跟踪外部接口入向挂一条最终的deny做兜底让所有未命中会话表的流量全部丢弃。access-list 110 permit ip 10.10.10.0 0.0.0.255 any access-list 110 deny ip any any access-list 120 deny ip any any这条access-list 120 deny ip any any看起来像废话其实是整套方案的安全底座。没有它外部接口默认是全放行的CBAC开不开都一样。4. 认证代理的工作链路一次浏览器访问背后发生了什么CBAC解决的是连接的问题认证代理解决的是人的问题。这两件事在网络准入里经常被混为一谈实际上层次完全不同。CBAC回答这个会话该不该放行认证代理回答这个终端背后的用户是谁他能访问什么。典型场景是这样的公司有一批外来访客或者自带设备接入你不想给他们开固定网段的白名单也不想让他们直接连内网。做法是让这些人先通过浏览器登录一次凭据校验通过后动态下发一段只属于他的访问权限时间到了自动失效。4.1 从HTTP请求被拦截到重定向登录页用户在浏览器里敲一个外网地址请求到达设备的内部接口。接口上挂了ip auth-proxy检查引擎发现这个源IP当前没有通过认证于是把这个HTTP请求截下来返回一个302重定向指向设备自己的认证页面。浏览器跳转到认证页用户输入账号密码页面通过HTTP POST把凭据提交给设备。设备拿这组凭据去问AAA服务器RADIUS或TACACS验证通过后把这个源IP标记为已认证并根据服务器返回的属性决定给他什么权限。从这一刻起这个IP的流量才开始走正常的CBAC流程。之前被拦下的那个原始请求用户需要手动刷新一次——这个细节很多文档不写但实际体验里就是登录成功后页面是空白的得再点一下。相关配置大致长这样ip auth-proxy name AUTH-HTTP http auth-cache-time 5 interface GigabitEthernet0/1 ip auth-proxy AUTH-HTTPauth-cache-time的单位是分钟指的是认证成功后多久内不需要重复认证。设太短用户频繁重登设太长权限回收不及时我一般按工作时段来定比如480分钟覆盖一个班次。4.2 RADIUS返回的Filter-Id怎么变成用户的专属ACL这是整个认证代理最容易被忽略、也最容易配错的一环。用户认证通过只是拿到了通行证真正决定他能去哪的是AAA服务器返回的授权属性。最常用的是Filter-Id属性属性号11值填一个ACL的名字或者编号。设备收到之后会把这个ACL应用到该用户的会话上替代默认的放行策略。ip access-list extended USER-LIMITED permit tcp any host 203.0.113.10 eq 443 permit udp any host 10.10.10.53 eq 53 deny ip any any aaa authorization auth-proxy default group radius服务器端给不同用户组返回不同的Filter-Id比如USER-LIMITED、USER-FULL、USER-GUEST。这样一来权限管理就从设备配置搬到了AAA服务器上几百个用户的分级授权不用在每台设备上改配置这是认证代理相比静态ACL最大的运维价值。提示设备上必须提前把Filter-Id对应的ACL定义好。如果服务器返回了一个设备上不存在的ACL名字不同版本行为不一致有的直接拒绝所有有的干脆放行所有——后者是实打实的安全事故。4.3 认证缓存、空闲超时、绝对超时三者的区别这三个计时器经常被搞混我用一张表说清楚计时器作用对象触发后果典型值auth-cache-time认证结果到期后下次访问需重新认证5~480分钟inactivity-timer会话活跃度空闲超时后强制注销900秒absolute-timer整个认证周期无论是否活跃到点强制注销28800秒inactivity-timer负责回收人走了但没点退出的会话absolute-timer负责兜住人一直在用但权限该刷新了的情况。两个都要设只设一个都有漏洞。ip auth-proxy inactivity-timer 900 ip auth-proxy absolute-timer 28800 ip auth-proxy auth-proxy-bannerauth-proxy-banner这个选项会在登录页显示一段自定义提示我一般用来写本网络仅限授权人员使用所有访问行为将被记录这类合规提示比默认页面正规得多。5. 一套能跑起来的组合配置CBAC 认证代理落地步骤前面讲原理这节讲顺序。配置顺序错了最典型的症状是命令敲进去了但没生效因为很多特性依赖前置对象存在。5.1 先把地址、路由、基础ACL立起来任何防火墙特性都必须建立在正确的三层转发之上。先确认接口地址、默认路由、内网回程路由都是通的用一个最简单的ping或者telnet验证一下。这一步不做后面所有排查都是在错误的前提上瞎猜。然后定义ACL。顺序很重要先定义ACL对象再往接口上挂。设备不允许挂一个不存在的ACL。access-list 110 permit ip 10.10.10.0 0.0.0.255 any access-list 110 deny ip any any access-list 120 deny ip any anyACL 110放行内网网段出方向ACL 120全拒绝作为外部入向的兜底。5.2 定义检查规则然后挂到正确的接口和方向ip inspect name CBAC-OUT tcp ip inspect name CBAC-OUT udp ip inspect name CBAC-OUT dns ip inspect name CBAC-OUT ftp挂接口的时候要记住一个口诀inspect 挂在流量进入设备的那一侧。内网流量从内网接口进来往外走所以inspect挂在内网接口的in方向。interface GigabitEthernet0/1 description INSIDE ip address 10.10.10.1 255.255.255.0 ip inspect CBAC-OUT in ip access-group 110 in interface GigabitEthernet0/0 description OUTSIDE ip address 203.0.113.1 255.255.255.252 ip access-group 120 in这个方向搞反是最常见的错误。挂成out方向的话会话表里记的是反过来的五元组回程匹配不上症状就是一个包都出不去。5.3 AAA与认证代理的对接aaa new-model aaa authentication login default local aaa authentication login AUTH-LOGIN group radius aaa authorization auth-proxy default group radius radius server RAD-A address ipv4 10.10.10.50 auth-port 1812 acct-port 1813 key 替换成你的密钥aaa new-model这一条要慎用它会改变整个设备的登录认证行为。在执行之前务必确认本地账号可用、console口有备份路径否则很容易把自己锁在设备外面。我见过不止一次远程升级AAA配置结果失联的案例。然后在需要认证的接口上挂认证代理策略interface GigabitEthernet0/1 ip auth-proxy AUTH-HTTP如果内网既有需要认证的网段又有免认证的服务器区通常会用独立的子接口或者VLAN接口来做隔离只在访客VLAN上挂ip auth-proxy避免把正常业务也拦进认证流程。5.4 验证命令和预期输出配完必须逐层验证不能只看命令没报错。show ip inspect config show ip inspect interfaces show ip inspect sessions show ip auth-proxy config show ip auth-proxy cache show ip access-lists 120show ip inspect sessions看到条目说明会话表在正常工作show ip access-lists 120里看到带(dynamic)标记的permit条目说明穿孔生效show ip auth-proxy cache里看到源IP和剩余时间说明认证状态被正确记录。这三条命令是我每次上线必查的缺一条心里都不踏实。6. 实测翻车点清单从上不了网到认证页打不开的排查链路配置写得再漂亮上线还是要出问题。这一节我把踩过的坑按排查顺序排一遍遇到故障照着走就行。6.1 排查顺序会话表 → ACL → AAA先看show ip inspect sessions。一条会话都没有说明流量压根没进检查引擎问题在接口方向、ACL拦截或者路由上跟CBAC本身无关。这一步能砍掉一半的排查工作量。如果有会话但业务不通看show ip access-lists确认动态条目有没有生成。有会话没条目往往是ACL挂的位置不对或者动态条目被前面的deny语句提前匹配掉了。如果动态条目正常但用户还是上不了才轮到查AAA。debug aaa authentication、debug ip auth-proxy这两个调试开关在排查阶段很有用但必须在业务低峰期开并且设好定时关闭否则日志量能把设备拖垮。6.2 认证代理最常见的五个坑现象根因处理登录页打不开浏览器一直转圈重定向目标不可达或DNS解析失败认证页地址用IP别用域名登录成功但页面空白原始请求已被丢弃提示用户手动刷新一次用户反馈我明明登录了还是上不了网Filter-Id对应的ACL在设备上不存在补齐ACL定义部分用户永远弹不出登录页浏览器配置了上级代理让代理绕过认证网段认证通过后权限过大RADIUS返回了空属性设备按默认放行在AAA侧强制配置fallback第一条我吃过亏。认证页面的URL如果是域名用户还没认证DNS请求大概率也被拦着直接死循环。后来统一改成设备的接口IP地址问题消失。第四条也很隐蔽。公司统一配了出口代理的终端HTTP请求直接发给代理服务器根本不经过设备的应用层自然不会触发重定向。解决办法是在代理客户端的例外列表里加上认证网段。6.3 CBAC这边的高频坑非对称路由。前面提过这里再强调一次。做了双出口或者策略路由的环境去和回走不同路径会话表必然对不上。要么把路径固定下来要么在两台设备上做状态同步后者在CBAC这个层级基本做不到只能换方案。MTU和分片。大包被分片之后后续分片里没有完整的传输层头部检查引擎没法关联到已有会话容易被丢弃。表现是小文件能下大文件卡死或者网页能开附件传不上去。这种情况下需要在接口上调MTU或者配置分片重组。NAT顺序。CBAC和NAT同时开启时检查引擎看到的是NAT转换前还是转换后的地址取决于平台的处理顺序。地址对不上会话表就建不起来。排查方法是同时看show ip nat translations和show ip inspect sessions比对两边的地址。动态条目被静态ACL覆盖。如果外部接口的入向ACL里有一条范围更大的permit写在前面CBAC的动态条目就永远不会被匹配到等于白配。排查时用show ip access-lists看清楚条目顺序动态条目理论上应该排在最前。提示排查这类问题我习惯先把外部接口的ACL临时改成只留deny ip any any把干扰项全部清掉确认CBAC能独立工作再一条条把静态规则加回去。这个过程虽然土但定位效率最高。7. 能力边界与替代方案什么时候不该用CBAC写了这么多配置和技巧最后得说点泼冷水的话。CBAC这套东西是特定年代的产物它的设计目标是在资源受限的设备上提供基础的状态化过滤。放到今天的网络环境里有些场景它确实力不从心了。7.1 CBAC绕不过去的三个硬伤第一是应用识别的深度有限。它能认出FTP、SIP这些经典协议但对加密流量、私有协议、以及大量现代Web应用无能为力。端口早就不代表应用了443上跑的可能是视频会议、可能是文件同步、也可能是隧道工具。CBAC的检测项清单停在了上一个时代。第二是策略模型的粒度不够。CBAC是接口级的、单向的策略表达力大概相当于从这个口进来的、到这个口出去的、属于这些协议的流量放行。它没有区域zone的概念也没有基于用户身份和应用的统一策略视图。配置量上去之后可维护性会急剧下降。第三是和NAT、QoS、策略路由的耦合问题。这些特性在同一台设备上共存时处理顺序和地址视图的差异会带来大量难以复现的边界问题前面提到的非对称路由只是其中一种。7.2 区域化防火墙和CBAC的思路差异后来的区域防火墙Zone-Based Policy Firewall把模型换了个思路不再按接口配inspect而是把接口划进区域然后定义区域对区域的策略。这个变化听起来只是语法不同实际上是策略思维方式的转变。维度CBAC区域化防火墙策略单位接口方向区域对状态跟踪全局检查规则策略内建状态默认行为需显式兜底ACL未定义策略即拒绝可读性规则散落在各接口策略集中一目了然扩展性接口多了容易乱区域数量可控最关键的差别是默认拒绝。区域化方案里两个区域之间没定义策略就是不通不需要你额外写一条deny ip any any兜底。这个设计把忘记写兜底这个高频人为失误从根上消掉了。认证代理这边也类似。现在的准入控制主流做法是802.1X加集中策略服务器或者干脆用Web门户认证网关把认证、授权、审计打包成一套。原来那套HTTP重定向 RADIUS返回Filter-Id的思路还在用但已经下沉成了整套体系里的一个环节而不是独立方案。7.3 老设备上还得用怎么用得稳一点现实情况是很多存量设备还在跑这些特性短期内换不掉。这种情况下我的建议是三条。一是把复杂度收拢。CBAC只用来处理最基础的出向访问多通道协议尽量在应用层做代理或者走专线别指望防火墙特性集去解所有协议问题。检测项能少开就少开每开一项都要有明确业务归属。二是把认证代理的权限控制外移。设备上只保留最粗的几档ACL细粒度权限交给AAA服务器这样改策略不用动设备配置风险小得多。三是把监控做起来。会话数、半开连接数、认证在线人数这几个指标要有基线出现异常波动能第一时间发现。很多事故不是配置错了而是容量被慢慢吃掉了没人注意。我在实际运维里的体会是这类老特性的价值不在于功能多强而在于行为可预期。它没有花哨的能力但只要你把超时、阈值、ACL顺序这几件事钉死它能稳定跑很多年。真正容易出事的地方往往是为了解决一个新需求往上叠了一个它本来就不擅长的功能。判断标准很简单当你发现自己需要为某个协议反复调试检测项、或者ACL数量超过两屏的时候就该考虑把这块业务迁到更合适的设备上去了硬撑下去只会让后面接手的人骂娘。
阅读完成 · 觉得有帮助?