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.
Frequently Asked Questions
Q: What happens to traffic between two interfaces assigned to the same zone?
A: Traffic between interfaces in the same zone passes without inspection by default. ZBF does not apply zone-pair policy to intra-zone traffic. If you need to inspect or restrict traffic within a zone, use interface ACLs or place interfaces in separate zones.
Q: Does ZBF replace the need for interface ACLs entirely?
A: ZBF handles inter-zone stateful inspection and replaces most interface ACL use cases. However, interface ACLs remain valid for intra-zone restrictions, management plane filtering before ZBF processes traffic, or Control Plane Policing (CoPP). The two mechanisms coexist without conflict.
Q: What is the difference between the inspect and pass actions?
A: The inspect action creates a stateful session entry and automatically permits return traffic without requiring a zone-pair in the reverse direction. The pass action permits traffic one-way with no state tracking. For TCP and UDP sessions, always use inspect. Use pass for protocols where stateful tracking is unnecessary or incorrect, such as routing protocol hellos or ICMP responses in the self zone.
Q: Can an interface belong to more than one zone?
A: No. Each interface can be a member of exactly one zone. Issuing a second zone-member security command on an interface replaces the existing zone assignment. Attempting to assign an interface to two zones simultaneously is not supported.
Q: Why did my OSPF adjacency drop immediately after applying self-zone policy?
A: OSPF uses multicast addresses 224.0.0.5 and 224.0.0.6, and the hellos flow between the router's own IP address and its neighbors — traffic that traverses the self zone. Once a class-default drop policy is applied to the self zone, OSPF hellos are dropped unless you explicitly match protocol ospf (or use an ACL permitting IP protocol 89) in a class-map with a pass action in both the zone-to-self and self-to-zone directions.
Q: Does ZBF support IPv6?
A: Yes. IOS-XE ZBF supports IPv6. Class-maps using NBAR2 protocol matching apply to both IPv4 and IPv6 transparently. ACL-based class-map matches can reference named IPv6 ACLs. The zone and zone-pair configuration syntax is identical for both address families.
Q: How do I permit ICMP unreachables generated by the router back to clients?
A: ICMP unreachables generated by the router originate from the self zone. Add a class-map entry matching protocol icmp or an ACL permitting ICMP in your self-to-INSIDE and self-to-OUTSIDE policy-maps with a pass action. Without this, the router silently drops its own ICMP unreachables, which can cause TCP black-holing when PMTUD is in use.
Q: Can ZBF and CBAC coexist on the same router?
A: Cisco does not support running ZBF and CBAC (ip inspect) on the same interface simultaneously. Mixing them on different interfaces of the same router is technically possible in some older IOS releases but produces unpredictable behavior and is not supported. When migrating from CBAC to ZBF, remove all legacy ip inspect configuration from interfaces before applying ZBF zone-member assignments.
Q: How does ZBF handle FTP active and passive modes?
A: FTP uses a control channel on TCP 21 and a separate data channel — TCP 20 for active FTP, or a dynamically negotiated port for passive FTP. ZBF includes an Application Layer Gateway (ALG) for FTP when you match protocol ftp in a class-map with the inspect action. The ALG inspects the control channel, tracks the negotiated data channel port, and automatically creates a dynamic session entry permitting the data connection. No additional policy is required for either active or passive FTP with NBAR-based inspection.
Q: What is the maximum number of concurrent ZBF sessions on ISR 4000 series?
A: Session limits depend on platform, installed DRAM, and IOS-XE version. On an ISR4331 with default memory, the practical limit is in the hundreds of thousands of concurrent sessions with stateful inspection enabled. You can adjust thresholds using parameter-map type inspect global with max-incomplete high and max-incomplete low values. Monitor session pressure with show platform hardware qfp active feature firewall drop on ISR4K platforms to detect table exhaustion before it impacts traffic.
Q: How do I apply ZBF inspection differently for traffic from specific subnets within the same zone?
A: Use ACL-based class-maps within the same zone-pair policy-map to differentiate per-subnet policy. Create separate ACLs for each subnet, match them in distinct class-maps, and stack those class-maps in priority order within a single policy-map applied to the zone-pair. The first matching class wins, so more specific matches should appear before broader ones. This avoids creating additional zones solely for policy differentiation.
Q: Is a parameter-map required for ZBF to function?
A: No. ZBF operates with built-in defaults for session limits, TCP half-open timeouts, and ICMP timeouts. A parameter-map type inspect is optional and used only when you need to override these defaults — for example, to tighten half-open TCP session thresholds to limit SYN-flood impact, or to extend UDP session idle timers for long-lived applications such as SIP or NFS. For most deployments the default parameters are sufficient to start.
