When designing networks, whether Cisco networks or not, there is one moment when the security of the network, the hosts within the network and the data exchanged through the network need to be addressed.

Network security is a vast subject in itself and encompasses data availability, data integrity and data privacy among others. It is implemented through the use of various systems and devices to ensure availability, integrity and privacy. These devices and systems include firewalls, Intrusion Detection Systems, Intrusion Prevention Systems, etc.

Today’s tutorial will cover one aspect of data security, namely network security with CISCO IOS stateful firewalls. These are made with (or configured on) generic Cisco IOS routers as opposed to deploying specialized devices like the Cisco ASA firewalls thus having one device managing normal routing and basic firewalling.

In this tutorial, we are going to see the use of Context-Based Access Control (also known as CBAC) another advanced use of Access Control Lists. Context-Based Access Control provides for a basic stateful firewall based on the generic Cisco IOS router by adding a true stateful inspection to IOS.

Available only in the CISCO IOS feature set, Context-Based Access Control is another method of access control that works based on the usual Access Control Lists combined with an inspection engine. The inspection engine discovers and manages state information for UDP and TCP sessions so as to be able to open temporary gates on the Cisco’s IOS firewall for identified return traffic.

CBAC provides stateful inspection of traffic and therefore can be used to configure a stateful firewall with a simple Cisco IOS router. In our tutorial, we will configure a simple Cisco IOS router and make it a stateful firewall thus avoiding deploying a specialized device like an Adaptive Security Appliance.

CBAC also includes in its operation the TCP Intercept feature that allowed us to see in a previous tutorial how to fight SYN-flood attacks and prevent malevolent hosts from flooding a victim’s node TCP stack with half-open sessions due to unfinished handshakes.

Contrary to the Reflexive Access Control Lists feature that is not well equipped to handle non-standard TCP/UDP applications traffic, the Context-Based Access Control feature has a better inspection engine for various protocols and applications with one caveat: the traceroute tool. As seen with Reflexive Access Control Lists, anytime the inbound flow is not the exact mirror image of the outbound flow, the traffic will be dropped by the Access Control Lists engine because it doesn’t recognize the flow as a result of the outbound flow generated by legitimate internal hosts.

Stateful inspection like the one in Context Based Access Control provides an inspection engine to every individual protocol so that even when the return traffic is not the exact mirror image of the outbound traffic, the Cisco device configured with CBAC will be able to handle the returning traffic and let it in provided the flow is compliant to the protocol standards.

CBAC does generate logs and audit trails that can be produced on a per-protocol basis. It is best suited for a Cisco IOS stateful firewall with a limited number (two) of interfaces so as to keep the access control lists simple and “manageable”.

One other feature of Context-Based Access Control stateful firewalls is the distinction between transit traffic and self-generated traffic.

CBAC is usually used to protect the inside network from the untrusted outside network. We will keep in mind that a vast portion of attacks are found to originate from within the trusted part of our network. CBAC does not protect against all attack vectors though as there is no such thing as total security.

When the IOS router have three or more interfaces to apply inspect rules to, the flow directions become very important to specify and the access control lists get complex and difficult to manage.

Adding a fourth interface on the CBAC router reveals how quickly the configurations can get complex and requires a good level of understanding of CBAC.


(GNS LAB : CISCO IOS FIREWALL (STATEFUL) – Context-Based Access Control (CBAC) – Clean Slate)

Our initial setup is made of:

  • A two interface CBAC router
  • Static routing everywhere to have basic end to end IP connectivity
  • Loopback interface (lo1) on all three devices
  • Telnet commands are “from” loopback interface lo0.

Context-Based Access Control and Transit Traffic

(GNS LAB : CISCO IOS FIREWALL (STATEFUL) – Context-Based Access Control (CBAC) – Transit traffic)


We want to allow outbound and its return traffic in but not incoming traffic. The inspect rule monitors outbound flow and opens a door in the firewall for compliant return traffic.

We are going to either inspect traffic on the outside interface or the inside interface. Both mean the same since there are only two interfaces the traffic can use to move across the router/firewall.

With some syntactical differences, almost the same Reflexive Access Control Lists logic apply with the CBAC stateful inspection:

  • First, the outbound flows are inspected and state information of the flows is maintained.
  • The restrictive ACL doesn’t directly reference CBAC but CBAC knows how to dynamically apply “open” directives for return traffic based on the state information.

Let’s start configuring CBAC on the … CBAC router:

We configure an inspect rule named CBAC_INTENSE_SCHOOL that inspects TCP, UDP and ICMP.

Afterwards we configure flow inspection for those irregular/atypical protocols. We chose which protocols here but the real choice is yours based on the protocols you expect or know to be running on your network.

Here in our network we also chose to inspect the FTP and TFTP protocols, thus allowing their return traffic to be allowed back in.

The summary of the inspect rules configured so far is displayed by the show running-config | include inspect command and we can see the five protocols (TCP, UDP, ICMP, FTP and TFTP).

I have just discovered through this exercise that the name of my inspect rule CBAC_INTENSE_SCHOOL was truncated by the IOS to CBAC_INTENSE_SCH. This has to do with a probable limit on the name length of an inspect rule.

The following is an example list of protocols you can configure your stateful cisco IOS firewall to inspect.

Visibly there are plenty of protocols to manage with the CBAC stateful firewall.

Now that we are done configuring the inspection engine on the CBAC router, we need to make the extended ACL apply to the outside inbound flow. That extended access control list would just deny all incoming flows that are not triggered by outbound traffic from inside our network. Legitimate flows would be determined by the CBAC inspection engine configured with the ip inspect command.

Additional permit statements on that extended Access Control List can be made by the administrator at his/her own discretion based on whether there are demands for incoming connections generated from the outside world. In our example scenario there are no such demands for “permit” statements because we don’t have connection requirements from outside our network. The blanket deny any any is enough.

On the outside interface of the CBAC router, we need to apply:

– The ACL in the inward direction to reject all non-return traffic;

– The ip inspect in the outward direction so as to maintain the state information for the protocols we want to open return gates for.

This means that CBAC only needs to inspect out and the IOS firewall will know what to dynamically open for inbound flows. The ACL in is only for unsolicited incoming flows and irregular protocols like traceroute that still need some quick and dirty fixes because they don’t yet fit in the protocols the CBAC can handle properly.

These are enough configurations for the basic traffic inspection we want for our example case.

We try telnet-ing from the inside router (TCP traffic) and it’s successful:

We try to ping (ICMP traffic) and it is also successful:

We will keep in mind that unsolicited incoming flows that are not part of any return traffic are still blocked at the CBAC router. The following telnet and ping below, done from the outside router, is a testimony to that effect.

Notice that in the two cases above (ping and telnet) the error logs are complaining about host unreachable (the UUUUU for five packets) and “destination unreachable”. This is an indication (or a hint) of what happened to the packets sent by the outside router. Here the packets (TCP and ICMP) are sent to the inside router but once they reach the CBAC, they are not identified as a return flow corresponding to legitimate flows from inside and they are refused and rejected by the access control list on the CBAC router. In those situations, refused packets warrant an error message to the sender so as to let the sender, here the outside router, know that the destination was unreachable. It’s a polite way, for a router, to say the packet was rejected.

Side Note:

Error messages and their interpretations are very important in troubleshooting because of the cues that they can give. In production environments and time-metered labs they altogether become critical and can prove to be the key to a quick solution keeping a crisis from becoming a disaster.

The official explanation of these rejects is found on the console logs found on the CBAC router where we can see the denied TCP and ICMP flows.

We can see that the CBAC_INTENSE_SCHOOL_OUTSIDE_IN access control list is rejecting ICMP and, later, TCP connections going from the outside router’s interfaces FE0/0 ( and Lo1 ( to the inside router’s Lo1 (

Let’s remove the TCP clause in the inspect rule and see what happens with the previous telnet and ping tests:

The telnet test fails twice with a “remote host not responding” complaint. If we look at the CBAC router console we can see two error logs telling us that the access control list named CBAC_INTENSE_SCHOOL_OUTSIDE_IN has denied a TCP packet twice. These packets are the return flow of the telnet flow initiated by the inside router.

At the same time, ping is still working because ping is an ICMP protocol and we know that ICMP is still inspected correctly.

To explain this situation, let’s remember that the CBAC_INTENSE_SCHOOL inspect rule is made to open temporary gates for the return flows of the configured protocols. Since we removed TCP among the inspected flows, any traffic bound to our network that is of TCP type will be left to negotiate with the CBAC_INTENSE_SCHOOL_OUTSIDE_IN access control list that was just configured to “deny any any” and log it. Thus any protocol not inspected is left to normal access control lists to decide whether to allow or deny.

To reverse this behavior, let’s remove ICMP from the inspected protocols and instead insert the TCP protocol. The telnet should start working correctly while the pings fail.

Even the one ping done with the lo1 as the source will fail.

The CBAC router is still logging at the console the denied return traffic that was not included in the inspect rule:

At this moment in our tutorial we started from a clean slate with basic full IP connectivity enabled and we have configured a basic Cisco IOS stateful firewall with the Context-Based Access Control feature. The setup was tested and we did troubleshooting for both the TCP and ICMP protocols from all areas and to all directions. The traffic tested however was only a traffic transiting the CBAC router, from outside router to inside router and also the other way round.

In the next tutorial, we will see the CBAC router’s own generated traffic and how to also have it be managed by the inspection engine. We will also fix the traceroute problem since as of now it can’t be managed by the inspection engine.

Until then watch this space for the next installment of CBAC.