Though Cisco’s Zone-Based Firewall (ZBF) method of securing networks via IOS (a router) has been around for several years I decided it was time to do a through study of the technology and do a write-up.

Introduction

The general premise to ZBF is to put a router’s interfaces into zones and then secure those zones one from another.  This has a huge benefit over the “traditional” way of securing networks on a router via access-lists (ACLs) applied to the interfaces directly because now multiple interfaces can be simultaneously secured with the exact same policy yet without the need to caveat traffic between interfaces of like “type”.  However, the greatest benefit that ZBF gives is the ability to remember a flow’s state.  This means that if a flow is permitted, say from the INSIDE zone to the OUTSIDE zone, then the return traffic for this flow is automatically permitted.  This can be very tricky if just using ACLs applied to interfaces.  ZBFs have several other features that go beyond this and will be discussed later in this write-up.

Describing how to setup ZBF in a linear text format is difficult as it has many parts and each part can be referenced in various locations throughout the configuration.  The essence of the configuration is that ZBF is configured using the Cisco Common Classification Policy Language (C3PL) format.  This is a long techno-jargon name for using class-maps, policy-maps, and service-polices to build the ZBF configuration.  However, ZBF also allows for nested class-maps, nested policy-maps, and advanced inspection features via parameter-maps.  So, to better document the configuration sequence here is a flow-chart describing all these features:

ZBF Flowchart

The picture is a bit unwieldy but you get the idea that ZBF is VERY flexible as well as has a lot of moving parts, depending on how intense of a configuration you want to put together.

Demonstration of Configuration

To demonstration the configuration of ZBF I’ll refer to the following topology:

DualISP-simple

Here we have multiple “outside” interfaces (to ISP1 and IPS2), a guest access network (Public VLAN), a DMZ, and multiple “inside” networks (Phones, User, Server).  The business rules of this network are as follows:

  • The Public network can only access the Internet and that access is limited to HTTP, HTTPS, and DNS protocols.  This network is also to be rate limited to 1MB of throughput.
  • Traffic from the Phones, User, and Server networks can intercommunicate freely.  The User and Server networks also are allowed outbound Internet connections BUT the Phones network is not.
  • The DMZ network has full outbound Internet access as well as limited access to the Server network (not the tightest setup but will work for this demonstration).
  • Traffic originating from the Internet (via ISP1 or ISP2) is only allowed based on which Servers (DMZ or Server networks) that have a static NAT translation and only on those ports that are necessary, such as port 80 for the web server.  (I could go into more detail about which server and which ports but the basic premise for this discussion is that “outside” traffic is denied by default and only permitted selectively.  Oh, and NAT is not a requirement in order to run ZBF but it does have interesting implications which will be discussed later in this write-up.)

C3PL and ZBF commands are picky in that several of the commands require other configuration pieces to exist before you can configure them.  For example, you cannot associate a non-existent class-map to a policy-map (though you can associate a non-existent access-list, ACL, to a class-map).  Also, bear in mind that once an command is applied to the router it takes effect.  Since the default rule is to not allow intercommunication between zones and if you happen to apply the zone-member command to the interfaces before setting up the permission criteria your traffic will not flow between the zones.  (Note: Traffic between interfaces in the same zone is permitted by default.)  So, let’s prepare all the C3PL configuration as required, then create the zones and zone-pairs, and only then apply the zones to the interfaces.

Access Control Lists

To start, create the ACLs that will be referenced by the class-maps.  These ACLs will be necessary as we need to associate the different networks to certain classes of traffic.  For this write-up I’ve tried to have a “business rule” for each network to show one thing or another about ZBF but it isn’t absolutely necessary to identify each network by its own ACL.  For example you may have multiple User networks and they could all be lumped into one ACL.

ip access-list standard DMZVLAN
permit 192.168.2.0 0.0.0.255

ip access-list standard PHONEVLAN
permit 172.17.16.0 0.0.15.255

ip access-list standard PUBLICVLAN
permit 10.255.255.0 0.0.0.255

ip access-list standard SERVERVLAN
permit 172.16.16.0 0.0.15.255

ip access-list standard USERVLAN
permit 172.18.16.0 0.0.15.255

ip access-list extended OUTSIDE2INSIDE
permit tcp any host 192.168.2.2 eq 443
permit tcp any host 192.168.2.2 eq www
permit tcp any host 172.16.19.213 eq smtp
permit tcp any host 172.16.19.213 eq 443
permit tcp any host 192.168.2.129 eq 4400
permit tcp any host 192.168.2.129 eq 5800
permit tcp any host 192.168.2.129 eq 5900
permit tcp any host 192.168.2.129 eq www

ip access-list extended OUTSIDE2self
permit tcp host x.y.z.w any eq 22

ip access-list extended OUTSIDE2self-ICMP
permit icmp host 8.8.8.8 host a.b.c.d
permit icmp host 8.8.8.8 host e.f.g.h

The last three ACLs are describing what is allowed from the outside world inbound, either to or through the router.  Notice that the OUTSIDE2INSIDE ACL uses a destination IP address in its statements from either the Server or DMZ networks.  This is because of the order of operations in the router as to when ZBF is handled vs. when NAT performs its translations.  As you might guess, NAT performed the translation from the Public IP address to the Private IP address prior to ZBF’s traffic inspection ACLs (this is different from assigning an ACL to an interface directly for filtering as ACLs on interfaces are checked prior to NAT translations).  This means that even though this ACL will eventually be associated with the “outside” interfaces (indirectly via ZBF) we need to reference the “inside” IPs as the destination addresses.

The last two ACLs introduce the concept of the “self” zone.  ZBF has a special zone built in.  It is the “self” zone.  This zone is used to permit/deny traffic to the router instead of through the router.  These ACLs should reference Public IPs but I’ve replaced them to protect the real network from which this configuration is gleaned.  For clarity, x.y.z.w is my company’s public IP (so I can SSH to the router from the outside), a.b.c.d is the router’s ISP1 facing public IP, and e.f.g.h is the router’s IPS2 facing Public IP.

I’d also like to point out the naming of these last 3 ACLs infer a certain level of knowledge about how they will eventually be used.  Their names, programatically speaking, are completely arbitrary.  I could have called any of these ACLs by some other word, such as C3PU or DarkMatter9999 or any other alphanumeric construct.  However, naming the ACLs such that their name “means” something helps us as network engineers know what that ACL’s purpose is or will be.  So, don’t feel you need to use this same naming convention but I find it very useful when I come back to a router weeks/months/years later and try to figure out what is going on and why.

Class Maps

It is now time to create the class-maps and associate the appropriate ACL with them.  Take note how each class-map is of “type inspect”.  The “type inspect” is a way to let the IOS know that this class-map will be used for ZBF.  There are a select set of features that are available in C3PL related to ZBF and the IOS ensures you do it correctly.

class-map type inspect match-all cmSERVER
match access-group name SERVERVLAN

class-map type inspect match-all cmPUBLIC
match access-group name PUBLICVLAN

class-map type inspect match-all cmUSER
match access-group name USERVLAN

class-map type inspect match-all cmOUTSIDE2self-ICMP
match access-group name OUTSIDE2self-ICMP

class-map type inspect match-all cmPHONE
match access-group name PHONEVLAN

class-map type inspect match-all cmDMZ
match access-group name DMZVLAN

class-map type inspect match-all cmOUTSIDE2self
match access-group name OUTSIDE2self

class-map type inspect match-all cmOUTSIDE2INSIDE
match access-group name OUTSIDE2INSIDE

Here is the list of things that a ZBF class-map can do.

Router(config)#class-map type inspect daxm
Router(config-cmap)#match ?
access-group        Access group
class-map              Class map
protocol                 PAM Protocol
security-group    Security Group
user-group            User Group

Nothing fancy was done in the class-maps used in this demonstration but you can match on some sophisticated settings such as another class-map (nested class-map), nbar, user-group, and security-group.  These advanced features require configuration topics beyond the scope of this write-up, however if you’d like assistance in creating a configuration using these features feel free to contact us for our professional services.

Policy Maps

Now that the class-maps are created it is time to build the policy-maps.  Again notice the “type inspect” associated with each policy-map and the class(es) that are associated with it.

policy-map type inspect pmPUBLIC2OUTSIDE
class type inspect cmPUBLIC
inspect
police rate 1000000 burst 100000
class class-default
drop

policy-map type inspect pmOUTSIDE2INSIDE
class type inspect cmOUTSIDE2INSIDE
inspect
class class-default
drop

policy-map type inspect pmOUTSIDE2self
class type inspect cmOUTSIDE2self-ICMP
pass
class type inspect cmOUTSIDE2self
inspect
class class-default
drop

policy-map type inspect pmINSIDE2OUTSIDE
class type inspect cmPHONE
drop
class type inspect cmUSER
inspect
class type inspect cmSERVER
inspect
class class-default
drop

policy-map type inspect pmDMZ2OUTSIDE
class type inspect cmDMZ
inspect
class class-default
drop

These policy-maps show off some of the features of ZBF.  First, each class under the policy-map are either using “inspect, pass, or drop”.  The keyword “inspect” means that the traffic’s flow will be registered and the return traffic will be permitted.  The keyword “pass” will allow the traffic through but will not register the traffic flow.  This means that return traffic will have to be dealt with somehow separately.  The keyword “drop”, as you might expect, drops the matched traffic.  Lastly, “police” allows the ability to rate limit certain classes of traffic.  Note that the “police” keyword can only be used in conjunction with the “inspect” keyword.

If you reference the bulleted business rules discussed earlier in this Demonstration of Configuration section you should start to see some of those rules being met.  For example, the Public network’s IP range is referenced in the PUBLICVLAN ACL which is referenced in the cmPUBLIC class-map which is finally referenced in the policy-map pmPUBLIC2OUTSIDE.  In there you’ll see that we are rate limiting the traffic to 1MB.  Additionally, in the pmINSIDE2OUTSIDE policy-map the cmPHONE class is set to drop all traffic (which the cmPHONE class-map references the PHONEVLAN ACL which references the Phone network).

As with the class-map shown above there are more advanced features, such as nested service-policies and parameter-maps, that are beyond the scope of this write-up but are available via our professional consulting services if you need that level of help.

Router(config)#policy-map type inspect daxm
Router(config-pmap)#class type inspect daxm
Router(config-pmap-c)#?
Policy-map class configuration commands:
drop                      Drop the packet
exit                        Exit from class action configuration mode
inspect                 Context-based Access Control Engine
no                          Negate or set default values of a command
pass                      Pass the packet
police                   Police
service-policy  Deep Packet Inspection Engine

Zones

Okay, so where are we?  We’ve created ACLs and associated them with class-maps which in turn have been associated with policy-maps.  In order for this hierarchy to work it needs to be applied somewhere.  In comes the zone configuration.  Before we can apply the above configuration we need to create the zones.  In this design we need 4 zones: “INSIDE”, “OUTSIDE”, “DMZ”, and “PUBLIC”.

zone security PUBLIC
description Public VLAN

zone security INSIDE
description Internal VLANs

zone security OUTSIDE
description ISP VLANs

zone security OUTSIDE
description DMZ VLANs

As discussed before, the naming of these zones (or policy-map/class-map/access-list) is completely arbitrary.  However having some sort of naming convention to your configuration goes a long way considering how my nested references are in play with ZBF.  Take a moment and refer back up to the policy-maps and notice how I named the policy-maps to “align” with the zones.  (Not only align but also describe a direction, which is important in the next section.)  Not that the names need to match but it helps when you come back to this configuration several weeks/months/years later and need to remember how everything works.  Plan your work and work your plan.

Zone Pairs

With the zones created we can now associate the policy-maps to the zones.  This is done with the “zone-pair” command.

zone-pair security PUBLIC2OUTSIDE source PUBLIC destination OUTSIDE
service-policy type inspect pmPUBLIC2OUTSIDE

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

zone-pair security OUTSIDE2self source OUTSIDE destination self
service-policy type inspect pmOUTSIDE2self

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

zone-pair security DMZ2OUTSIDE source DMZ destination OUTSIDE
service-policy type inspect pmDMZ2OUTSIDE

The zone-pairs have a directionality to them.  They specify a “from” and “to” zone.  Be sure to build your ACLs such that they are working in the direction you apply the policy.

Zone Membership

The last thing to do is apply the zones to the appropriate interfaces.  In my case g0/0 has subinterfaces for the internal, DMZ, and Public networks while g0/0 and g0/1 are connected to the appropriate ISP.

g0/0.100
desc ServerVLAN
zone-member security INSIDE

g0/0.101
desc PhoneVLAN
zone-member security INSIDE

g0/0.102
desc UserVLAN
zone-member security INSIDE

g0/0.103
desc DMZVLAN
zone-member security DMZ

g0/0.104
desc PublicVLAN
zone-member security PUBLIC

g0/0
desc ISP1
zone-member security OUTSIDE

g0/1
desc ISP2
zone-member security OUTSIDE

As we are now applying ZBF to the interfaces this means that the “rubber has met the road”.  ZBF will immediately start to take action (permit/deny/rate limit/etc).  Also, there is another key caveat/feature of ZBF to point out here, ZBF does not allow traffic to pass from a non-zone assigned interface with any interface associated with a zone.  This implies that the vast majority of the time you’ll need to assign all the router’s interfaces to one zone or another.  If for some reason you have a set of interfaces that can’t be assigned to one particular zone or another you’ll have to create a “catch-all” zone and apply those interfaces to that zone.  Within this zone you would probably “pass” all the traffic but any other ZBF feature could be used if needed.

Demonstration Verification

No configuration set up is good without the ability to verify how it is configured!  Lets first see what zone is associated with what interface with the “show zone security” command:

Router#show zone security
zone self
Description: System Defined Zone

zone PUBLIC
Description: Public VLAN
Member Interfaces:
GigabitEthernet0/0.4

zone INSIDE
Description: Buck Internal VLANs
Member Interfaces:
GigabitEthernet0/0.5

zone OUTSIDE
Description: ISP VLANs
Member Interfaces:
GigabitEthernet0/2
GigabitEthernet0/1

Next check to see how the zones are paired with the “show zone-pair security”

Router#show zone-pair security
Zone-pair name PUBLIC2OUTSIDE
Source-Zone PUBLIC Destination-Zone OUTSIDE
service-policy pmPUBLIC2OUTSIDE
Zone-pair name INSIDE2OUTSIDE
Source-Zone INSIDE Destination-Zone OUTSIDE
service-policy pmINSIDE2OUTSIDE
Zone-pair name OUTSIDE2self
Source-Zone OUTSIDE Destination-Zone self
service-policy pmOUTSIDE2self
Zone-pair name OUTSIDE2INSIDE
Source-Zone OUTSIDE Destination-Zone INSIDE
service-policy pmOUTSIDE2INSIDE

As you might guess we now will look at the policy-maps.  The tricky part here is to remember to check the “type inspect” policy-maps.  If you just issue the “show policy-map” command you’ll miss out on any “type inspect” policy-maps.  For example:

Router#show policy-map
Router#

versus

Router#show policy-map type inspect
Policy Map type inspect pmPUBLIC2OUTSIDE
Class cmPUBLIC
Inspect
Police rate 1000000 burst 100000
Class class-default
Drop

Policy Map type inspect pmOUTSIDE2INSIDE
Class cmOUTSIDE2INSIDE
Inspect
Class class-default
Drop

Policy Map type inspect pmINSIDE2OUTSIDE
Class cmPHONE
Drop
Class cmUSER
Inspect
Class cmSERVER
Inspect
Class cmDMZ
Inspect
Class class-default
Drop

Policy Map type inspect pmOUTSIDE2self
Class cmOUTSIDE2self-ICMP
Pass
Class cmOUTSIDE2self
Inspect
Class class-default
Drop

The same thing happens when looking at the class-maps used for ZBF.

Router#show class-map
Class Map match-any class-default (id 0)
Match any

versus

Router#show class-map type inspect
Class Map type inspect match-all cmSERVER (id 1)
Description: Match Server VLAN IPs for ZBF
Match access-group name SERVERVLAN

Class Map type inspect match-all cmPUBLIC (id 2)
Description: Match Public VLAN IPs for ZBF
Match access-group name PUBLICVLAN

Class Map type inspect match-all cmUSER (id 3)
Description: Match USER VLAN IPs for ZBF
Match access-group name USERVLAN

Class Map type inspect match-all cmOUTSIDE2self-ICMP (id 4)
Match access-group name OUTSIDE2self-ICMP

Class Map type inspect match-all cmPHONE (id 5)
Description: Match PHONE VLAN IPs for ZBF
Match access-group name PHONEVLAN

Class Map type inspect match-all cmDMZ (id 6)
Description: Match DMZ VLAN IPs for ZBF
Match access-group name DMZVLAN

Class Map type inspect match-all cmOUTSIDE2self (id 7)
Match access-group name OUTSIDE2self

Class Map type inspect match-all cmOUTSIDE2INSIDE (id 8)
Match access-group name OUTSIDE2INSIDE

Now let’s see the details of the access-lists.  Differently than the class-map and policy-maps show commands listed above the “show access-lists” command will show ALL the configured access-lists in the router’s config.  I this config’s case it just so happens there are no “other” access-lists configured.

Router#show access-lists
Standard IP access list DMZVLAN
10 permit 192.168.2.0, wildcard bits 0.0.0.255 (485 matches)
Standard IP access list PHONEVLAN
10 permit 172.17.16.0, wildcard bits 0.0.15.255
Standard IP access list PUBLICVLAN
10 permit 10.255.255.0, wildcard bits 0.0.0.255
Standard IP access list SERVERVLAN
10 permit 172.16.16.0, wildcard bits 0.0.15.255 (565469 matches)
Standard IP access list USERVLAN
10 permit 172.18.16.0, wildcard bits 0.0.15.255
Extended IP access list OUTSIDE2INSIDE
10 permit tcp any host 192.168.2.2 eq 443 (3 matches)
20 permit tcp any host 192.168.2.2 eq www (148 matches)
30 permit tcp any host 172.16.19.213 eq 443 (7906 matches)
40 permit tcp any host 192.168.2.129 eq 4400
50 permit tcp any host 192.168.2.129 eq 5800 (1 match)
60 permit tcp any host 192.168.2.129 eq 5900 (590 matches)
70 permit tcp any host 192.168.2.129 eq www (77 matches)
80 permit tcp any host 192.168.2.4 eq 443 (274 matches)
90 permit tcp any host 192.168.2.4 eq 444
Extended IP access list OUTSIDE2self
10 permit tcp host x.y.z.w any eq 22 (1 match)
Extended IP access list OUTSIDE2self-ICMP
10 permit icmp host 8.8.8.8 host a.b.c.d (7381 matches)
20 permit icmp host 8.8.8.8 host e.f.g.h (471 matches)

But is it working?  Well, the only show command listed above that even gives a hint as to whether it is working or not is the “show access-lists” and this barely the case as it only shows whether that ACL line has been matched at some point in time!  What if that particular ACL is used somewhere else in the router’s configuration?  Or, what if that match was from a previous use case of that ACL and it was just repurposed for ZBF.  We need bigger guns here!

How about trying this command.  The output is a bit long as I’m not filtering down on any particular policy-map BUT I wanted to show the whole of it so you could compare against the aforementioned commands’ output.

Router#show policy-map type inspect zone-pair

policy exists on zp PUBLIC2OUTSIDE
Zone-pair: PUBLIC2OUTSIDE

Service-policy inspect : pmPUBLIC2OUTSIDE

Class-map: cmPUBLIC (match-all)
Match: access-group name PUBLICVLAN

Inspect
Session creations since subsystem startup or last reset 0
Current session counts (estab/half-open/terminating) [0:0:0]
Maxever session counts (estab/half-open/terminating) [0:0:0]
Last session created never
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 0
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0

Police
rate 1000000 bps,100000 limit
conformed 0 packets, 0 bytes; actions: transmit
exceeded 0 packets, 0 bytes; actions: drop
conformed 0 bps, exceed 0 bps

Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes

policy exists on zp INSIDE2OUTSIDE
Zone-pair: INSIDE2OUTSIDE

Service-policy inspect : pmINSIDE2OUTSIDE

Class-map: cmPHONE (match-all)
Match: access-group name PHONEVLAN
Drop
0 packets, 0 bytes

Class-map: cmUSER (match-all)
Match: access-group name USERVLAN

Inspect
Session creations since subsystem startup or last reset 0
Current session counts (estab/half-open/terminating) [0:0:0]
Maxever session counts (estab/half-open/terminating) [0:0:0]
Last session created never
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 0
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0
Class-map: cmSERVER (match-all)
Match: access-group name SERVERVLAN

Inspect
Packet inspection statistics [process switch:fast switch]
tcp packets: [97887:189859023]
udp packets: [127333:306584]
icmp packets: [38:87]

Session creations since subsystem startup or last reset 199350
Current session counts (estab/half-open/terminating) [46:0:0]
Maxever session counts (estab/half-open/terminating) [1210:306:73]
Last session created 00:00:00
Last statistic reset never
Last session creation rate 15
Maxever session creation rate 1191
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0
Class-map: cmDMZ (match-all)
Match: access-group name DMZVLAN

Inspect
Packet inspection statistics [process switch:fast switch]
tcp packets: [0:1235]
udp packets: [0:311]

Session creations since subsystem startup or last reset 485
Current session counts (estab/half-open/terminating) [0:0:0]
Maxever session counts (estab/half-open/terminating) [2:3:0]
Last session created 00:33:59
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 4
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0
Class-map: class-default (match-any)
Match: any
Drop
0 packets, 0 bytes

policy exists on zp OUTSIDE2self
Zone-pair: OUTSIDE2self

Service-policy inspect : pmOUTSIDE2self

Class-map: cmOUTSIDE2self-ICMP (match-all)
Match: access-group name OUTSIDE2self-ICMP
Pass
8779 packets, 396122 bytes

Class-map: cmOUTSIDE2self (match-all)
Match: access-group name OUTSIDE2self

Inspect
Packet inspection statistics [process switch:fast switch]
tcp packets: [750:742]

Session creations since subsystem startup or last reset 1
Current session counts (estab/half-open/terminating) [1:0:0]
Maxever session counts (estab/half-open/terminating) [1:1:0]
Last session created 00:47:45
Last statistic reset never
Last session creation rate 0
Maxever session creation rate 1
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0
Class-map: class-default (match-any)
Match: any
Drop
16652 packets, 1757676 bytes

policy exists on zp OUTSIDE2INSIDE
Zone-pair: OUTSIDE2INSIDE

Service-policy inspect : pmOUTSIDE2INSIDE

Class-map: cmOUTSIDE2INSIDE (match-all)
Match: access-group name OUTSIDE2INSIDE

Inspect
Packet inspection statistics [process switch:fast switch]
tcp packets: [6881:1128338]

Session creations since subsystem startup or last reset 15643
Current session counts (estab/half-open/terminating) [21:0:0]
Maxever session counts (estab/half-open/terminating) [39:15:18]
Last session created 00:00:22
Last statistic reset never
Last session creation rate 4
Maxever session creation rate 92
Last half-open session total 0
TCP reassembly statistics
received 0 packets out-of-order; dropped 0
peak memory usage 0 KB; current usage: 0 KB
peak queue length 0
Class-map: class-default (match-any)
Match: any
Drop
9611 packets, 402075 bytes

Wow!  What a plethora of information.  You can see how well/poorly the police policy is doing on the PUBLIC2OUTSIDE policy-map.  You can see the number of TCP/UDP packets that matched a particular class under a particular policy-map.  You can even see when was the last “inspect” function created a session (flow) on a particular class on a particular policy-map.

What about actual connections/flows?  Well, issue the command “show policy-map type inspect zone-pair <zone-pair> sessions” command.

Router#show policy-map type inspect zone-pair OUTSIDE2INSIDE sessions

policy exists on zp OUTSIDE2INSIDE
Zone-pair: OUTSIDE2INSIDE

Service-policy inspect : pmOUTSIDE2INSIDE

Class-map: cmOUTSIDE2INSIDE (match-all)
Match: access-group name OUTSIDE2INSIDE

Inspect

Number of Established Sessions = 18
Established Sessions
Session 3D7B2920 (x.x.x.x:1612)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:47:24, Last heard 00:24:30
Bytes sent (initiator:responder) [1938:15899]
Session 39D03340 (y.y.y.y:56123)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:21:18, Last heard 00:21:17
Bytes sent (initiator:responder) [950:2559]
Session 3E5C9C20 (z.z.z.z:7708)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:16:34, Last heard 00:16:33
Bytes sent (initiator:responder) [1051:2559]
Session 22CE00E0 (w.w.w.w:9185)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:13:33, Last heard 00:13:32
Bytes sent (initiator:responder) [1081:2559]
Session 3E5C9FA0 (a.a.a.a:55526)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:13:10, Last heard 00:00:16
Bytes sent (initiator:responder) [6474:22470]
Session 3E5D24A0 (b.b.b.b:4966)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:11:29, Last heard 00:11:28
Bytes sent (initiator:responder) [995:2559]
Session 3E566220 (c.c.c.c:48036)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:10:51, Last heard 00:10:51
Bytes sent (initiator:responder) [1021:145]
Session 3E58BE20 (d.d.d.d:11172)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:08:40, Last heard 00:08:29
Bytes sent (initiator:responder) [1198:470]
Session 21F0FAA0 (e.e.e.e:3247)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:07:29, Last heard 00:07:28
Bytes sent (initiator:responder) [1027:2559]
Session 22D30360 (f.f.f.f:3341)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:06:56, Last heard 00:06:53
Bytes sent (initiator:responder) [1357:326]
Session 3E56D220 (g.g.g.g:40106)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:04:11, Last heard 00:04:10
Bytes sent (initiator:responder) [964:2559]
Session 21F147A0 (h.h.h.h:1735)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:03:10, Last heard 00:03:10
Bytes sent (initiator:responder) [853:145]
Session 22D33460 (i.i.i.i:31099)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:02:51, Last heard 00:02:46
Bytes sent (initiator:responder) [950:2559]
Session 3E608320 (j.j.j.j:4713)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:02:12, Last heard 00:02:10
Bytes sent (initiator:responder) [731:145]
Session 3E5AB020 (k.k.k.k:41499)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:01:59, Last heard 00:01:37
Bytes sent (initiator:responder) [3378:3685]
Session 3E5A6DA0 (l.l.l.l:37643)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:01:59, Last heard 00:01:59
Bytes sent (initiator:responder) [298:145]
Session 3D7B1420 (m.m.m.m:1817)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:01:40, Last heard 00:00:13
Bytes sent (initiator:responder) [729:470]
Session 21F098A0 (n.n.n.n:1821)=>(172.16.19.213:443) tcp SIS_OPEN/TCP_ESTAB
Created 00:00:13, Last heard 00:00:12
Bytes sent (initiator:responder) [1480:5382]

Class-map: class-default (match-any)
Match: any
Drop
12213 packets, 508316 bytes

I prefer using the above mentioned show commands to verify ZBF configuration.  However, there is a “new” suite of commands you can use.  Check out the “show policy-firewall” set of commands and you be the judge which is better.

Router#show policy-firewall ?
config       Show policy-firewall config
mib          Policy Firewall MIB specific show commands
session      Show policy-firewall session details
stats        Show policy-firewall stats
summary-log  show ZBFW summary logs

Thanks for your time and I hope you were able to learn something.  If you find an error please feel free to reach out and we will fix it promptly.  Lastly, I’d like to put forth one last plug for our professional/consulting services.  If you find this write-up useful and need help with your network’s configuration or design please contact us.