Cisco IOS Zone Based Policy Firewall

The last days I have been testing Zone Based Policy Firewall in Cisco IOS. It´s a feature much like CBAC. It´s using the same basics of inspection-configuration. The major difference between CBAC and ZBFW is that while the first is built upon inspection at specific interfaces, the latter defines zones of one or many interfaces and then defines inspection in a single direction from one zone to another.

Task 1

To make a somewhat realistic scenario I take a router in my home-lab. It´s preconfigured for basic routing without filtering anything. The goal is to make the router stateful with ZBFW. I want to block all traffic thru the router except from outbound telnet. Lets rock.

Step 1. Define zones

Each interface participating in a Zone Based Firewall-setup needs to be added to a zone. In this basic setup I have 2 zones: INSIDE and OUTSIDE

zone security OUTSIDE
zone security INSIDE

Step 2. Applying zones to interfaces

I have three interfaces in my setup: two internal an one external. The zone-membership is configured on interface-level.

interface FastEthernet0
zone-member security OUTSIDE
interface FastEthernet1
zone-member security INSIDE
interface Vlan13
zone-member security INSIDE

3. Define allowed traffic

Let´s focus on outbound traffic. We want to allow all telnet-traffic from our INSIDE-zone. This is done with a class-map type inspect. This class-map will later be reused for all other outbound traffic to be inspected, so remember to name it wisely.

class-map type inspect match-any class-INSIDE-TO-OUTSIDE
match protocol telnet

4. Decide what do do with it

Next step is configuring the policy-map. Since only one policy-map can be assigned at each function (in this case for traffic from INSIDE to OUTSIDE) it might be reused later. This policy-map will put together all actions we want to take on all traffic in the direction. For now we want to tell our router to inspect all traffic defined by the class-map created in the previous step.

The policy-map is processed in top-down order. At the end of the policy-map there is a class class-default that by default drops “all other” traffic, just the way the implicit deny ip any any does in access-lists.

policy-map type inspect policy-INSIDE-TO-OUTSIDE
class type inspect class-INSIDE-TO-OUTSIDE
class class-default

5. Apply it

Now the final step is to apply this configuration. We have zones, let´s create a zone-pair. It is a definition of traffic from one zone to another, in one direction. Traffic in opposit direction (that is in our case: traffic initiated on OUTSIDE going to INSIDE) needs to be taken care of with another setup of class-map, policy-map and zone-pair.

zone security OUTSIDE
zone security INSIDE
zone-pair security INSIDE-TO-OUTSIDE source INSIDE destination OUTSIDE
service-policy type inspect policy-INSIDE-TO-OUTSIDE

6. Logging

Also, a really good command to remember is the “ip inspect log drop-pkt”. Without it you will not see traffic that gets dropped by the firewall. So remember to add it and maybe remove it as the last step before leaving the building…

ip inspect log drop-pkt

7. Verify

Lets verify that I can telnet from INSIDE to OUTSIDE:

Trying ... Open

User Access Verification

[Connection to closed by foreign host]

Great. It works.

What we have accomplished is to make a chain of “maps” that looks like this on a flow chart:

Task 2. Also allow specific pings outbound

The next task for me is to enable ping from inside hosts to the outside. To make it a bit trickier I decide to make an exception for the internal host who should not be able to ping.

Step 1. Define traffic

First define what traffic will be allowed. Since we need to specify traffic on a per-host-level we cannot just “match protocol icmp” like we did with telnet, but instead do it with an access-list that is referred to in our previous created class-map (which is type match-any which mean that it can have multiple match-statements and it´s enough to match one of them).

ip access-list extended acl-INSIDE-TO-OUTSIDE-inspect
deny icmp host any echo
permit icmp any any echo

2. Add it to the class-map.

class-map type inspect match-any class-INSIDE-TO-OUTSIDE
match protocol telnet (<--- Already there!)
match access-group name acl-INSIDE-TO-OUTSIDE-inspect

3. Verify.

Since the class-map were already in the policy-map with the action “inspect” I dont need to do anything else. We´re all done. Lets verify:


Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to, timeout is 2 seconds:
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms
r3#ping sou lo0

Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to, timeout is 2 seconds:
Packet sent with a source address of
Success rate is 0 percent (0/5)

Yes! We can ping an outside host, but not when sourcing from This is verified by the log-output (remember the ip inspect log drop-pkt-command?):

%FW-6-LOG_SUMMARY: 5 packets were dropped from => (target:class)-(INSIDE-TO-OUTSIDE:class-default)

Now the flow of configuration building-blocks looks like this:

So, why did I specify the telnet-traffic with “match protocol telnet” but the icmp-traffic with an access-list? First of all, the end-result is the same; it will inspect the state of the traffic. Even the pings are inspected and handled in a session-alike fashion.

When doing “match protocol telnet” i rely upon the PAM-table (Port Application Mapping) which by default saids that “telnet” equals tcp/23. If I add a PAM-entry that adds tcp/2323 to the telnet-application, traffic on that port should also have been inspected. But the granularity of just specifying the port or application was not good enough for the ping since we needed to define an exception for a single host.
Of course I could also put the telnet-traffic into the access-list, it would have the exact same end result:

class-map type inspect match-any class-INSIDE-TO-OUTSIDE
no match protocol telnet
ip access-list extended acl-INSIDE-TO-OUTSIDE-inspect
deny icmp host any echo
permit icmp any any echo
permit tcp any any eq 23


  • I have had a REALLY hard time trying to fully understand the concept of class-maps and policy-maps when doing inspection. This simple rule has made it so much easier to understand how to do and not: ALL class-maps and Policy-maps should be “type inspect” when working with inspection. Doing “class-map yadayo” without “type inspect” in between (and the same for policy-maps) just made me confused. Plain (as in not type inspect) policy-maps and class-maps are for other purposes than making the router stateful.
  • Security-zones doesnt cooperate very well with interface access-lists. Actually, the idea behind ZBFW is to replace acls on that router. That means that ZBFW doesn´t make any “holes” in any existing access-lists. Since interface-acls in inbound direction gets processed before zbfw you need to have access-lists “wide-open” enough to make sure that all ZBFW-traffic gets thru. I recommend not applying acls to interfaces when using ZBFW.
  • Traffic to and from the router itself are wide open in this example. There is a self-zone that takes care of this. Hopefully this will be covered in a later post.
  • Traffic between interfaces in the same zone are permitted.


ZBFW is cool if you have to secure a Cisco-router which have many interfaces that can be treated with the same security-policy.

Posted in Cisco Security
One comment on “Cisco IOS Zone Based Policy Firewall
  1. noc-ninja says:

     Thank you this post!


[mc4wp_form id="2457"]
Website Security Test