What Is Cisco Zone-Based Firewall?
Cisco Zone-Based Policy Firewall (ZBF or ZBPF) is the modern stateful inspection firewall engine built natively into IOS and IOS-XE. It supersedes the older Context-Based Access Control (CBAC) framework by organizing router interfaces into named security zones and enforcing directional traffic policies between zone-pairs. ZBF runs on ISR G2, ISR 4000, ASR 1000, Catalyst 8000v, and CSR1000v platforms. No additional license is required on most IOS-XE 16.x and 17.x releases.
The foundational rule is simple: traffic between different zones is denied by default. Traffic within the same zone passes freely without inspection. Traffic to or from the router itself flows through the special self zone, which also requires explicit policy when hardening is needed. This default-deny posture makes ZBF an effective baseline for perimeter enforcement and internal network segmentation.
ZBF vs. Classic IOS CBAC
CBAC applied ip inspect per interface per direction. As the number of interfaces grows, the policy becomes fragmented and hard to audit. ZBF introduces a centralized, policy-map-driven model with clear separation of concerns:
- Interfaces belong to exactly one named zone
- Policy lives in zone-pair definitions, not on individual interfaces
- Class-maps of type inspect classify traffic by protocol or ACL
- Policy-maps of type inspect assign actions: inspect, pass, or drop
- Zone-pairs bind a directional policy-map to a source/destination zone tuple
The inspect action creates stateful session tracking and automatically permits return traffic. The pass action permits one direction without state. The drop action silently discards. Append log to either drop or pass for syslog visibility.
Lab Topology
All configurations in this run book apply to rtr-infrarunbook-01, an ISR4331 running IOS-XE 17.x, with three security zones:
- OUTSIDE — GigabitEthernet0/0/0, WAN uplink, IP 172.16.0.2/30
- INSIDE — GigabitEthernet0/0/1, LAN segment, IP 192.168.10.1/24
- DMZ — GigabitEthernet0/0/2, server segment, IP 192.168.20.1/24
Policy objectives for this deployment:
- INSIDE users can initiate HTTP, HTTPS, DNS, and ICMP outbound to OUTSIDE
- INSIDE users can initiate HTTP and HTTPS inbound to DMZ servers
- DMZ servers can initiate HTTP/HTTPS outbound to OUTSIDE for patching
- No unsolicited inbound connections from OUTSIDE reach INSIDE or DMZ
- SSH management to the router is permitted only from 192.168.10.0/24
- All dropped traffic is logged to syslog
Step 1: Define Security Zones
Zones are logical containers for interfaces sharing the same trust level. Zone names are case-sensitive. Create one zone per security boundary.
rtr-infrarunbook-01# configure terminal
! Create the three security zones
zone security OUTSIDE
description WAN uplink - untrusted
!
zone security INSIDE
description LAN - trusted internal users
!
zone security DMZ
description Server segment - semi-trusted
!
Step 2: Assign Interfaces to Zones
Each interface must be assigned to exactly one zone using zone-member security. An interface without a zone assignment is excluded from all ZBF inter-zone policy but still participates in self-zone processing for router-destined traffic.
interface GigabitEthernet0/0/0
description WAN uplink
ip address 172.16.0.2 255.255.255.252
zone-member security OUTSIDE
no shutdown
!
interface GigabitEthernet0/0/1
description LAN
ip address 192.168.10.1 255.255.255.0
zone-member security INSIDE
no shutdown
!
interface GigabitEthernet0/0/2
description DMZ servers
ip address 192.168.20.1 255.255.255.0
zone-member security DMZ
no shutdown
!
Important: The moment you assign an interface to a zone, all inter-zone traffic through that interface is denied until a matching zone-pair policy with an inspect or pass action is in place. Plan and stage your zone-pair policies before assigning interfaces in production.
Step 3: Configure Class-Maps for Traffic Classification
Class-maps of type inspect identify traffic you want to act on. Match by NBAR2 protocol name, ACL, or both. Use match-any so any matched condition triggers the class; use match-all only when all conditions must be simultaneously true.
! ACL for SSH management to the router
ip access-list extended ACL-MGMT-SSH
permit tcp 192.168.10.0 0.0.0.255 any eq 22
!
! ACL for NTP from LAN to the router
ip access-list extended ACL-NTP-TO-SELF
permit udp 192.168.10.0 0.0.0.255 any eq 123
!
! Class-map: common user outbound protocols
class-map type inspect match-any CM-INSIDE-TO-OUTSIDE
match protocol http
match protocol https
match protocol dns
match protocol icmp
!
! Class-map: DMZ outbound for patching
class-map type inspect match-any CM-DMZ-TO-OUTSIDE
match protocol http
match protocol https
match protocol dns
!
! Class-map: INSIDE accessing DMZ web servers
class-map type inspect match-any CM-INSIDE-TO-DMZ
match protocol http
match protocol https
!
! Class-map: SSH and NTP to self zone (management)
class-map type inspect match-any CM-INSIDE-TO-SELF
match access-group name ACL-MGMT-SSH
match access-group name ACL-NTP-TO-SELF
!
NBAR2 protocol names such as http, https, and dns enable deep packet inspection and application-layer awareness beyond simple port matching. Use show ip nbar protocol-pack to confirm available protocol definitions on your platform.
Step 4: Configure Policy-Maps with Inspect Actions
Policy-maps of type inspect define what happens to classified traffic. Always configure class class-default explicitly at the bottom of each policy-map so unmatched traffic generates a log entry rather than failing silently.
! Policy: drop everything (reusable for block-all zone-pairs)
policy-map type inspect PM-DROP-ALL
class class-default
drop log
!
! Policy: INSIDE initiates to OUTSIDE
policy-map type inspect PM-INSIDE-TO-OUTSIDE
class type inspect CM-INSIDE-TO-OUTSIDE
inspect
class class-default
drop log
!
! Policy: DMZ initiates to OUTSIDE
policy-map type inspect PM-DMZ-TO-OUTSIDE
class type inspect CM-DMZ-TO-OUTSIDE
inspect
class class-default
drop log
!
! Policy: INSIDE to DMZ web access
policy-map type inspect PM-INSIDE-TO-DMZ
class type inspect CM-INSIDE-TO-DMZ
inspect
class class-default
drop log
!
! Policy: management access to self zone from INSIDE
policy-map type inspect PM-INSIDE-TO-SELF
class type inspect CM-INSIDE-TO-SELF
pass
class class-default
drop log
!
Note: Use inspect for TCP/UDP sessions requiring automatic return-traffic permission. The inspect action maintains a state table and inserts a dynamic ACL entry for the reply flow. Use pass for traffic flows where stateful tracking is unnecessary — for example, OSPF hellos or ICMP in the self zone.
Step 5: Create Zone-Pairs and Apply Service Policies
Zone-pairs are directional. A pair from INSIDE to OUTSIDE is entirely separate from OUTSIDE to INSIDE. The inspect action handles return traffic automatically for established sessions, so you do not need a reverse zone-pair solely for return flows — but you should define it explicitly with drop log to capture unsolicited inbound attempts.
! INSIDE initiates outbound to OUTSIDE
zone-pair security ZP-INSIDE-TO-OUTSIDE source INSIDE destination OUTSIDE
service-policy type inspect PM-INSIDE-TO-OUTSIDE
!
! OUTSIDE to INSIDE — block all unsolicited inbound
zone-pair security ZP-OUTSIDE-TO-INSIDE source OUTSIDE destination INSIDE
service-policy type inspect PM-DROP-ALL
!
! DMZ initiates outbound to OUTSIDE
zone-pair security ZP-DMZ-TO-OUTSIDE source DMZ destination OUTSIDE
service-policy type inspect PM-DMZ-TO-OUTSIDE
!
! OUTSIDE to DMZ — block all unsolicited inbound
zone-pair security ZP-OUTSIDE-TO-DMZ source OUTSIDE destination DMZ
service-policy type inspect PM-DROP-ALL
!
! INSIDE accesses DMZ web servers
zone-pair security ZP-INSIDE-TO-DMZ source INSIDE destination DMZ
service-policy type inspect PM-INSIDE-TO-DMZ
!
! DMZ to INSIDE — no zone-pair defined = implicit deny
! Explicit version for logging:
zone-pair security ZP-DMZ-TO-INSIDE source DMZ destination INSIDE
service-policy type inspect PM-DROP-ALL
!
Step 6: Protect the Router — Self Zone Configuration
The self zone represents the router itself. Without an explicit self-zone policy, ZBF allows all zone-to-self traffic by default. Hardening the self zone blocks unsolicited management access from untrusted zones while preserving routing protocols and legitimate management from the LAN.
! Class-map: routing protocols and keepalives from self to INSIDE
ip access-list extended ACL-ROUTING-PROTO
permit ospf any any
permit eigrp any any
!
class-map type inspect match-any CM-SELF-TO-INSIDE
match access-group name ACL-ROUTING-PROTO
match protocol ntp
!
policy-map type inspect PM-SELF-TO-INSIDE
class type inspect CM-SELF-TO-INSIDE
pass
class class-default
drop log
!
! Zone-pairs for self zone
zone-pair security ZP-INSIDE-TO-SELF source INSIDE destination self
service-policy type inspect PM-INSIDE-TO-SELF
!
zone-pair security ZP-SELF-TO-INSIDE source self destination INSIDE
service-policy type inspect PM-SELF-TO-INSIDE
!
! Block everything from OUTSIDE to self
zone-pair security ZP-OUTSIDE-TO-SELF source OUTSIDE destination self
service-policy type inspect PM-DROP-ALL
!
! Block everything from DMZ to self
zone-pair security ZP-DMZ-TO-SELF source DMZ destination self
service-policy type inspect PM-DROP-ALL
!
Caution: Before applying self-zone policy in production, inventory every protocol the router originates or receives: routing adjacencies (OSPF, BGP, EIGRP), HSRP/VRRP hellos, NTP, SNMP, and syslog. A missing protocol in the self-zone class-map will immediately break the adjacency. Apply during a maintenance window and verify routing table stability afterward.
Step 7: Verify Zone Assignments and Policy Binding
After completing configuration, use the following commands to confirm zone assignments and zone-pair policy bindings before generating test traffic:
! Confirm interfaces are zone-assigned
rtr-infrarunbook-01# show zone security
zone self
Description: System defined zone
zone OUTSIDE
Description: WAN uplink - untrusted
Member Interfaces:
GigabitEthernet0/0/0
zone INSIDE
Description: LAN - trusted internal users
Member Interfaces:
GigabitEthernet0/0/1
zone DMZ
Description: Server segment - semi-trusted
Member Interfaces:
GigabitEthernet0/0/2
! Confirm zone-pair to policy binding
rtr-infrarunbook-01# show zone-pair security
Zone-pair name ZP-INSIDE-TO-OUTSIDE (INSIDE -> OUTSIDE)
Service-policy inspect : PM-INSIDE-TO-OUTSIDE
Zone-pair name ZP-OUTSIDE-TO-INSIDE (OUTSIDE -> INSIDE)
Service-policy inspect : PM-DROP-ALL
Zone-pair name ZP-DMZ-TO-OUTSIDE (DMZ -> OUTSIDE)
Service-policy inspect : PM-DMZ-TO-OUTSIDE
Zone-pair name ZP-OUTSIDE-TO-DMZ (OUTSIDE -> DMZ)
Service-policy inspect : PM-DROP-ALL
Zone-pair name ZP-INSIDE-TO-DMZ (INSIDE -> DMZ)
Service-policy inspect : PM-INSIDE-TO-DMZ
Zone-pair name ZP-INSIDE-TO-SELF (INSIDE -> self)
Service-policy inspect : PM-INSIDE-TO-SELF
Zone-pair name ZP-OUTSIDE-TO-SELF (OUTSIDE -> self)
Service-policy inspect : PM-DROP-ALL
Step 8: Monitor Active Sessions and Hit Counts
ZBF maintains a per-zone-pair session table for stateful tracking. Use the commands below to verify policies are matching expected traffic and to monitor active session counts:
! View hit counts and active sessions per zone-pair
rtr-infrarunbook-01# show policy-map type inspect zone-pair ZP-INSIDE-TO-OUTSIDE sessions
Zone-pair : ZP-INSIDE-TO-OUTSIDE
Service-policy inspect : PM-INSIDE-TO-OUTSIDE
Class-map: CM-INSIDE-TO-OUTSIDE (match-any)
Match: protocol http
2547 packets, 1854320 bytes
Match: protocol https
8923 packets, 12048776 bytes
Match: protocol dns
1204 packets, 89432 bytes
Match: protocol icmp
84 packets, 6720 bytes
Inspect
Session creations since subsystem startup or last reset 3102
Current session counts (estab/half-open/terminating) [3:0:0]
Class-map: class-default (match-any)
0 packets, 0 bytes
Drop
! View all active firewall sessions across all zone-pairs
rtr-infrarunbook-01# show policy-map type inspect zone-pair sessions
! Detailed view with 5-tuple session information
rtr-infrarunbook-01# show policy-map type inspect zone-pair ZP-INSIDE-TO-OUTSIDE detail
Applying ZBF Alongside NAT/PAT
When NAT or PAT is also configured on the router, ZBF inspection occurs on the pre-NAT source address for inside-to-outside traffic and the post-NAT address for outside-to-inside traffic. Class-map ACLs referencing inside hosts should use the pre-NAT (RFC 1918) address ranges. No special ZBF configuration is required — ZBF and NAT coexist natively on IOS-XE.
! NAT overload alongside ZBF
ip access-list standard ACL-NAT-INSIDE
permit 192.168.10.0 0.0.0.255
permit 192.168.20.0 0.0.0.255
!
ip nat inside source list ACL-NAT-INSIDE interface GigabitEthernet0/0/0 overload
!
! Interface NAT role and ZBF zone are independent settings
interface GigabitEthernet0/0/0
ip nat outside
zone-member security OUTSIDE
!
interface GigabitEthernet0/0/1
ip nat inside
zone-member security INSIDE
!
Troubleshooting Zone-Based Firewall
ZBF provides targeted debugging that can be scoped to a specific zone-pair without impacting all traffic on the platform:
! Check per-zone-pair drop counters
rtr-infrarunbook-01# show policy-map type inspect zone-pair ZP-OUTSIDE-TO-INSIDE
! Check NBAR protocol identification on a specific interface
rtr-infrarunbook-01# show ip nbar protocol-discovery interface GigabitEthernet0/0/1
! Verify NBAR2 protocol pack version
rtr-infrarunbook-01# show ip nbar version
! View QFP hardware firewall drop reasons (ISR4K/ASR1K)
rtr-infrarunbook-01# show platform hardware qfp active feature firewall drop
! Clear sessions for a specific zone-pair
rtr-infrarunbook-01# clear policy-firewall session zone-pair ZP-INSIDE-TO-OUTSIDE
! Clear all ZBF sessions globally
rtr-infrarunbook-01# clear policy-firewall session
Common issues and resolutions:
- Traffic dropped after interface zone assignment: Confirm a zone-pair exists for the direction with an inspect or pass policy. Check class-map hit counters with show policy-map type inspect zone-pair.
- Routing adjacency drops after self-zone lockdown: Add the routing protocol (ospf, eigrp, bgp) to both the zone-to-self and self-to-zone class-maps with a pass action.
- NBAR protocol not matching: Confirm the protocol pack is loaded with show ip nbar version. Some older packs lack updated HTTPS/QUIC signatures. Update the pack or fall back to ACL-based matching.
- SSH to router fails after ZBF deployment: Ensure a zone-pair from INSIDE to self with a pass action for TCP/22 exists. Also verify ip ssh version 2 and VTY transport input ssh are configured.
- Asymmetric routing causes stateful inspection failures: ZBF requires symmetric routing. If return traffic arrives on a different interface, the session lookup fails and packets are dropped. Verify the routing table and ensure ECMP or policy-based routing does not split flows across different interfaces.
- Half-open session count climbing: Elevated half-open TCP counts visible in zone-pair session output may indicate SYN-flood activity. Tune thresholds in a parameter-map type inspect and consider enabling TCP SYN cookies.
Production Best Practices
- Always define class-default explicitly with drop log in every policy-map. Silent drops make troubleshooting unnecessarily difficult.
- Use NBAR2 protocol matching instead of port-based ACL matching wherever possible. Protocol-aware inspection catches traffic on non-standard ports and provides accurate application identification.
- Lock down the self zone on any router with an untrusted-facing interface. Document every protocol required before applying restrictions.
- Name all ZBF objects consistently: CM-<source>-TO-<destination>, PM-<source>-TO-<destination>, ZP-<source>-TO-<destination>. Consistent naming makes large configurations auditable and reduces misapplication risk.
- Log dropped packets to a SIEM. Set logging buffered informational and configure a remote syslog destination to capture ZBF drop events for security correlation.
- Create explicit drop zone-pairs even where implicit deny would suffice. Explicit drop log entries give visibility into scanning and reconnaissance attempts that would otherwise be invisible.
- Tune session table thresholds for high-throughput deployments using parameter-map type inspect global to configure max-incomplete high/low watermarks and TCP syn-wait times appropriate for your traffic profile.
- Test all policy changes in a maintenance window. A misconfigured class-default or missing zone-pair immediately drops live sessions. There is no graceful degradation.
Related Articles
- [Cisco] Cisco ACL Configuration: Standard, Extended, Named, and Time-Based Access Lists on IOS/IOS-XE
- [Cisco] Cisco NAT/PAT Configuration: Complete Run Book for Static NAT, Dynamic NAT, PAT Overload, and Policy NAT on IOS/IOS-XE
- [Cisco] Cisco SNMP Configuration: Complete Run Book for SNMPv2c, SNMPv3, Traps, and Polling on IOS/IOS-XE
- [Cisco] Cisco NTP Configuration: Complete Run Book for NTP Server, Client, Authentication, and Stratum Hierarchy on IOS/IOS-XE
