Study Notes – IOS Zone-Based Firewall

This is a post in a series of “stream-of-study” content where I post loosely-structured notes taken while labbing various scenarios and technologies.

ZBFW troubleshootinghttps://www.cisco.com/c/en/us/support/docs/security/ios-firewall/117721-technote-iosfirewall-00.html

Note about self-zonehttps://community.cisco.com/t5/security-knowledge-base/zbfw-self-zone-integration/ta-p/3154572

!-----------------------------!
!   IOS Zone-based Firewall   !
!-----------------------------!
!
! Lets configure a ZBFW with the following arbitrary requirements:
!
!1. all inside hosts must be allowed to send http, https, and icmp traffic to outside
!2. all inside hosts must be allowed to send dns, dhcp, https, smtp, kerberos, and icmp traffic to the dmz
!3. vlan 102 hosts must be allowed to send SIP and RTP traffic to the DMZ
!4. vlan 101 hosts must be allowed to send RDP traffic to the DMZ
!5. DMZ hosts must be allowed to send http, https, icmp, ntp, sip, rtp, and ftp traffic outside
!6. outside hosts must be allowed to send https, ftp, and smtp traffic to the DMZ
!7. only external peer 100.248.101.96 should be able to form an IPSec-ISAKMP tunnel with the router
!
!first lets configure basic interfaces
!
int gig0/2
 ip add 198.18.253.172 255.255.255.128
 ip nat outside
!
int gig0/1
 ip add 10.255.10.1 255.255.255.0
 ip nat inside
!
int gig0/0.101
 encap dot1q 101
 ip add 10.255.101.1 255.255.255.0
 ip nat inside
 ip helper-address 10.255.10.100
!
int gig0/0.102
 encap dot1q 102
 ip add 10.255.102.1 255.255.255.0
 ip nat inside
 ip helper-address 10.255.10.100
!
ip route 0.0.0.0 0.0.0.0 198.18.253.129
access-list 1 permit any 
ip nat inside source list 1 interface gig0/2 overload
!
!since we have hosts within the inside zone which need different access based on their subnet, lets start by defining access lists for the Inside -> DMZ traffic
!
ip access-list extended 101 
 permit ip 10.255.101.0 0.0.0.255 10.255.10.0 0.0.0.255
ip access-list extended 102 
 permit ip 10.255.102.0 0.0.0.255 10.255.10.0 0.0.0.255
!
!we also know the router itself needs to talk to 100.248.101.96 for VPN, so lets match that with an ACL too, and lets be specific about it because, fun fact, the "match protocol" command, which performs DPI and header inspection, can only be used for the self-zone if the policy map action is set to "Pass", not inspect, which means we can't rely on being able to do header inspection for the ISAKMP/ESP traffic and need to allow it via port identification if we want to let it be stateful
!
ip access-list extended 103 
 permit udp host 100.248.101.96 any eq isakmp
 permit udp any eq isakmp host 100.248.101.96
 permit esp host 100.248.101.96 any
 permit esp any host 100.248.101.96
!
!now lets define zones
!
zone security inside
zone security outside
zone security dmz
!
!lets start classifying the traffic we need, starting with requirement #1
!
class-map type inspect match-any CM-WEB-ICMP
 match protocol http
 match protocol https
 match protocol icmp
!
class-map type inspect match-any CM-DMZ-SVC
 match protocol dns
 match protocol bootpc
 match protocol https
 match protocol smtp
 match protocol kerberos
 match protocol icmp
!
class-map type inspect match-any CM-VOIP
 match protocol sip
 match protocol rtp
!
!there is no prebuilt protocol inspection for RDP, so, we need a manual port-map - this MUST start with "user-"
!
ip port-map user-RDP tcp port 3389
!
class-map type inspect CM-RDP
 match protocol user-RDP
!
!now for the requirements #3 and #4, we can make our first nested class-maps, note the "match-all", this is an "AND" which includes the "match-any" (OR) class map for VOIP traffic, so effectively this is says match the access list AND SIP OR RTP.  Same logic for the RDP map.
!
class-map type inspect match-all CM-INSIDE102-TO-DMZ
 match access-group 102
 match class-map CM-VOIP
!
class-map type inspect match-all CM-INSIDE101-TO-DMZ
 match access-group 101
 match class-map CM-RDP
!
!now we can continue with the requirements for #5 and #6
!
class-map type inspect match-any CM-DMZ-OUT
 match protocol http
 match protocol https
 match protocol icmp
 match protocol ntp
 match protocol sip
 match protocol rtp
 match protocol ftp
!
class-map type inspect match-any CM-OUT-TO-DMZ
 match protocol https
 match protocol ftp
 match protocol smtp
!
!finally, for #7, we create a class to just match on the ACL we created earlier. we also need to configure an "ip any" CMAP here to allow the router to talk to anything else it wants to since altering the self-zone from the default, which allows all traffic, will cause it to block traffic for anything not explicitly defined, and in this case we have no other requirements so lets assume we want to let the router do what it wants besides outside sone filtering
!
class-map type inspect CM-SELF-TO-OUT
 match access-group 103
!
class-map type inspect CM-ANY
 match access-group 1
!
!now, lets create our policy maps to facilitate these requirements - this defines the inspection policy
!
policy-map type inspect IN-TO-OUT
 class type inspect CM-WEB-ICMP
  inspect
!
policy-map type inspect IN-TO-DMZ
 class type inspect CM-DMZ-SVC
  inspect
 class type inspect CM-INSIDE102-TO-DMZ
  inspect
 class type inspect CM-INSIDE101-TO-DMZ
  inspect
!
policy-map type inspect DMZ-TO-OUT
 class type inspect CM-DMZ-OUT
  inspect
!
policy-map type inspect OUT-TO-DMZ
  class type inspect CM-OUT-TO-DMZ
   inspect
!
policy-map type inspect SELF-TO-OUT
  class type inspect CM-SELF-TO-OUT
   inspect
!
policy-map type inspect SELF-TO-ANY
 class type inspect CM-ANY
  inspect
!
policy-map type inspect ANY-TO-SELF
 class type inspect CM-ANY
  inspect
!
!now, we can define our zone-pair policies where we call the policy-map and add directionality to our inspection
!
zone-pair security IN-TO-OUT source inside destination outside
 service-policy type inspect IN-TO-OUT
!
zone-pair security IN-TO-DMZ source inside destination dmz
 service-policy type inspect IN-TO-DMZ
!
zone-pair security DMZ-TO-OUT source dmz destination outside
 service-policy type inspect DMZ-TO-OUT
!
zone-pair security OUT-TO-DMZ source outside destination dmz
 service-policy type inspect OUT-TO-DMZ
!
zone-pair security SELF-TO-OUT source Self destination outside
  service-policy type inspect SELF-TO-OUT
!
zone-pair security OUT-TO-SELF source outside destination Self
  service-policy type inspect SELF-TO-OUT
!
zone-pair security SELF-TO-IN source Self destination inside
  service-policy type inspect SELF-TO-ANY
!
zone-pair security SELF-TO-DMZ source Self destination dmz
  service-policy type inspect SELF-TO-ANY
!
zone-pair security IN-TO-SELF source inside destination Self
  service-policy type inspect ANY-TO-SELF
!
zone-pair security DMZ-TO-SELF source dmz destination Self
  service-policy type inspect ANY-TO-SELF
!
!and finally, we join our interfaces to the zones - technically, we could do this at any time, but by default a zone with no policy will drop all inter-zone traffic (except for the Self zone which allows all by default), so it can be a bit safer to enable filtering at the very end by prescriptively applying the zone-member command to the interfaces to enable them
!
int gig0/2
 zone-member outside
!
int gig0/1
 zone-member dmz
!
int gig0/0.101
 zone-member inside
!
int gig0/0.102
 zone-member inside
!
!
!--------------------
!   Verifications
!--------------------
!
show zone security
show zone-pair security
show access-list
show class-map type inspect
show policy-map type inspect 
show policy-map type inspect zone-pair <zone-pair policy name> sessions
show policy-firewall config
show policy-firewall sessions[zone-pair <zone-pair policy name>]
show policy-firewall stats

Leave a comment