Cisco's context-based access control allows for the filtering of traffic based on application-layer protocols. CBAC makes use of two components to filter traffic traversing an untrusted interface: a set of inspection rules for traffic egressing the interface and an access list to permit or deny ingress traffic. Traffic originating on the internal network is inspected as it leaves the router and an entry is appended to the incoming access list to allow return traffic from the same session.
One peculiar aspect of CBAC is that the outgoing inspection rules match only traffic passing through the router; traffic generated by the router itself is not inspected. At first this may seem an insignificant detail, but because the router's traffic isn't being inspected, an exception for it in the inbound access list isn't created and the router won't receive any return traffic.
For illustration, let's create a simple inspection rule to match ICMP and apply it to the router's external interface in the outbound direction:
Router(config)# ip inspect name Outbound icmp Router(config)# interface f0/0 Router(config-if)# ip inspect Outbound out
Next, we create a "deny any" access list and apply it inbound on the same interface:
Router(config)# ip access-list extended Inbound Router(config-ext-nacl)# deny ip any any Router(config-ext-nacl)# interface f0/0 Router(config-if)# ip access-group Inbound in
Our CBAC configuration should allow only ICMP traffic originating from within the trusted network to return. We can verify that pinging the external router R1 from R3 succeeds:
R3# ping 10.0.12.1 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 10.0.12.1, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 4/8/16 ms
However, R2 itself cannot reach R1:
R2# ping 10.0.12.1 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 10.0.12.1, timeout is 2 seconds: ..... Success rate is 0 percent (0/5)
This is because, as mentioned, traffic originating from the router itself is not by default included in the inspection rule applied to the external interface. To fix this, we need to append the router-traffic argument to our inspection rule:
R2(config)# ip inspect name Outbound icmp ? alert Turn on/off alert audit-trail Turn on/off audit trail router-traffic Enable inspection of sessions to/from the router timeout Specify the inactivity timeout time R2(config)# ip inspect name Outbound icmp router-traffic
Now R2 can successfully ping R1:
R2# ping 10.0.12.1 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 10.0.12.1, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 4/10/28 ms
router-traffic argument must be appended independently to each inspection rule in a named set.
I had intended to include an IPv6 example of CBAC as well, but it unfortunately appears broken on the versions of IOS I have available.