Cisco's Context-Based Access Control (CBAC) is a component of the IOS firewall feature set. Similar to reflexive ACLs, CBAC enables dynamic modification of access lists to allow certain incoming flows by first inspecting and recording flows initiated from the protected internal network. However, whereas reflexive ACLs act solely on L2-L4 protocol attributes, CBAC is able to inspect all the way to the application layer, taking into consideration characteristics of a flow on a per-protocol basis (or context).
Rather than over-analyzing CBAC operation in this article, I offer a simple scenario: a router with exactly two interfaces (one internal and one external) placed between two networks, one trusted (internal) and one untrusted (external). Our goal is to configure the router to protect the trusted network (typically a LAN or enterprise network) from the untrusted network (in our example, the Internet).
From the conceptual illustration, we see that there are four logical points (marked in blue) at which the router can inspect traffic:
- Inbound on the internal interface
- Outbound on the external interface
- Inbound on the external interface
- Outbound on the internal interface
While we can deploy independent, static ACLs at one, some, or all of these points simultaneously, CBAC is configured and operates per interface, dynamically modifying ACL entries facing one direction based on the traffic it sees flowing in the opposite direction.
For example, let's assume we first want to allow by default all traffic traversing the router from the internal LAN (192.168.0.0/24) toward the Internet (for our purposes, 10.0.0.0/8). This is already the case, as the router will of course forward all routable traffic when no access restrictions have been applied. We also want to deny by default all traffic flowing from the Internet toward the LAN; to accomplish this we can use a simple ACL to deny all IP traffic. We'll apply it to the external interface in the inbound direction (versus the internal interface outbound) so that the router itself is protected from untrusted traffic as well.
R1(config)# ip access-list extended DENY_ALL R1(config-ext-nacl)# deny ip any any R1(config-ext-nacl)# exit R1(config)# interface f0/0 R1(config-if)# ip access-group DENY_ALL in
Note that an extended ACL is used here; more on that in a bit.
At this point, traffic can flow uninhibited from our trusted network to the untrusted network, but is completely blocked in the opposite direction. Not great if you favor bidirectional communication.
For instance, assume we now want to allow web access initiated from the internal network to return. One option would be to configure a more granular ACL in place of DENY_ALL, but that would not provide stateful tracking and may open a security hole. Another option would be to implement a reflexive ACL, but that would provide only limited state tracking. A more powerful solution is CBAC.
CBAC allows us to define an inspection rule for each protocol we want to monitor. In this case, we want to track HTTP and HTTPS sessions, so we create the following rule named "Web":
R1(config)# ip inspect name Web http R1(config)# ip inspect name Web https
There are additional options per protocol, but for now we'll accept their defaults. Next we need to apply our inspection rule to an interface and in a particular direction. We apply the rule outbound on the external interface because:
- We want to inspect traffic originating from the trusted network, and
- We want to dynamically adjust the ACL restricting traffic inbound on the external interface.
This is done with the
ip inspect command at interface configuration:
R1(config)# interface f0/0 R1(config-if)# ip inspect Web out
The CBAC configuration can be verified with
show ip inspect all:
R1# show ip inspect all Session audit trail is enabled Session alert is enabled one-minute (sampling period) thresholds are [400:500] connections max-incomplete sessions thresholds are [400:500] max-incomplete tcp connections per host is 50. Block-time 0 minute. tcp synwait-time is 30 sec -- tcp finwait-time is 5 sec tcp idle-time is 3600 sec -- udp idle-time is 30 sec dns-timeout is 5 sec Inspection Rule Configuration Inspection name WEB http alert is on audit-trail is on timeout 3600 https alert is on audit-trail is on timeout 3600 Inspection name Web http alert is on audit-trail is on timeout 3600 https alert is on audit-trail is on timeout 3600 Interface Configuration Interface FastEthernet0/0 Inbound inspection rule is not set Outgoing inspection rule is Web http alert is on audit-trail is on timeout 3600 https alert is on audit-trail is on timeout 3600 Inbound access list is DENY_ALL Outgoing access list is not set
We've now enabled CBAC in one direction for HTTP and HTTPS traffic on this interface. Outbound traffic (going toward the Internet) is tracked as CBAC sessions, and the DENY_ALL extended ACL restricting inbound traffic is automatically modified to accommodate legitimate return traffic. We can see CBAC in action when a host and the trusted network initiates an HTTP connection to a web server on the Internet:
R1# show ip inspect sessions Established Sessions Session 66E4E40C (192.168.0.2:12078)=>(10.0.0.2:80) http SIS_OPEN
From the output of
show ip inspect sessions we can see that the trusted host 192.168.0.2 has opened an HTTP connection to 10.0.0.2. CBAC will continue to track this session until it is closed by either end, or the configured idle timer is reached.
When the session was initiated, CBAC automatically created an entry at the top of the DENY_ALL ACL in preparation for the legitimate return traffic.
We can enable audit trails to generate syslog messages for each CBAC session creation and deletion:
R1(config)# ip inspect audit-trail R1(config)# %FW-6-SESS_AUDIT_TRAIL_START: Start http session: initiator (192.168.0.2:12078) -- responder (10.0.0.2:80)
Or, for even more verbosity, we can debug CBAC object creation:
R1# debug ip inspect object-creation INSPECT Object Creations debugging is on R1# CBAC* OBJ_CREATE: Pak 6621F7A0 sis 66E4E154 initiator_addr (192.168.0.2:12078) responder_addr (10.0.0.2:80) initiator_alt_addr (192.168.0.2:12078) responder_alt_addr (10.0.0.2:80) CBAC OBJ-CREATE: sid 66E684B0 acl DENY_ALL Prot: tcp Src 10.0.0.2 Port [80:80] Dst 192.168.0.2 Port [12078:12078] CBAC OBJ_CREATE: create host entry 66E568DC addr 10.0.0.2 bucket 8 (vrf 0:0) insp_cb 0x66B61C0C
Of course there's far more to CBAC than we've covered here, but hopefully this example provides a decent illustration of the concept.