
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 troubleshooting – https://www.cisco.com/c/en/us/support/docs/security/ios-firewall/117721-technote-iosfirewall-00.html
Note about self-zone – https://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
