ASA

Cisco ASA Inspection Engines: MPF and Custom Maps

Cisco ASA Inspection Engines: MPF and Custom Maps
In: ASA, Fundamentals

The Cisco ASA Modular Policy Framework (MPF) is the configuration model that decides which traffic gets which kind of treatment as it crosses the firewall. It is what binds inspection engines to specific traffic, what applies QoS or connection limits, and what sets timeouts that diverge from the platform defaults. The pieces are three: class-maps (matching traffic), policy-maps (the actions to apply), and service-policies (binding the policy-map to an interface or globally). This article walks the model, the default global policy that ships on every ASA, and how to add custom HTTP, FTP, or ESMTP inspection without breaking what is already working.

This is a Fundamentals article in the Cisco ASA cluster. The companion article on the data-plane side is Cisco ASA Packet Flow, which covers where the inspection engines actually fire in the per-packet pipeline.

The Three MPF Pieces

ConstructWhat it doesExample
class-map NAMEMatches traffic. ACL-style criteria, or built-in match default-inspection-traffic.class-map WEB-CLASS + match access-list WEB-ACL
policy-map NAMELists actions to apply to matched traffic. One or more class entries, each with one or more action lines.policy-map WEB-POLICY + class WEB-CLASS + inspect http
service-policy NAME {global | interface NAME}Activates the policy-map. Either globally (one policy across all interfaces) or per-interface.service-policy WEB-POLICY interface outside

One policy-map can have many class entries, and each class can have many actions. Activating the policy-map binds the whole thing at once.

The Default Global Policy

Every fresh ASA ships with a global service-policy already in place. It catches traffic with a built-in class and applies inspection for the standard application-layer protocols.

ASA-PERIM# show running-config policy-map global_policy
policy-map global_policy
 class inspection_default
  inspect dns preset_dns_map
  inspect ftp
  inspect h323 h225
  inspect h323 ras
  inspect ip-options
  inspect netbios
  inspect rsh
  inspect rtsp
  inspect skinny
  inspect esmtp
  inspect sqlnet
  inspect sunrpc
  inspect tftp
  inspect sip
  inspect xdmcp
 class class-default
  user-statistics accounting
!
ASA-PERIM# show running-config service-policy
service-policy global_policy global

Read it as: a class called inspection_default matches a built-in set of "ports we know about for the listed protocols" (DNS on 53, FTP on 21, etc.). The actions are inspect <protocol> for each application-layer engine. The service-policy line binds it globally.

The ASA does not include inspect icmp by default on every release. The lab's running config has it explicitly added (which is why pings come back). Confirm:

ASA-PERIM# show service-policy global | include icmp
      Inspect: icmp, packet 1244, lock fail 0, drop 0, reset-drop 0

If the line is missing, add it:

ASA-PERIM(config)# policy-map global_policy
ASA-PERIM(config-pmap)#  class inspection_default
ASA-PERIM(config-pmap-c)#  inspect icmp

Without inspect icmp, ICMP echo requests leave the firewall but echo replies have no matching conn entry and get dropped. ICMP is the easiest "is the ASA letting traffic through" test, so getting inspection on for it early is worth doing.

What an Inspection Engine Actually Does

Three things, depending on the protocol:

  1. Stateful tracking for connectionless protocols. ICMP is the canonical example: the ASA pretends ICMP is stateful so echo replies match echo requests.
  2. Pinhole opening for protocols with negotiated secondary ports. FTP active mode negotiates a data port over the control channel. Without inspection, the data channel hits the perimeter ACL and gets denied; with inspection, the ASA reads the PORT command, opens a temporary pinhole for the negotiated port, and closes it when the session ends.
  3. Application-layer security checks. The HTTP inspection engine can enforce HTTP method allow-lists, header sanity, URL length limits, and reject malformed requests. The ESMTP engine masks server banners, blocks dangerous SMTP verbs, and enforces RFC compliance on email transactions.

The first category is essential and almost always wanted. The second is required for any application that uses negotiated secondary ports. The third is application-layer firewalling that overlaps with what the next-gen successor (FTD) does in a more flexible model. ASA's application-layer inspection still works but is rarely the central piece of a modern security strategy.

Custom Class-Maps: Match More Specifically

Sometimes the built-in inspection_default class is too broad and you want to apply an action to a narrower slice of traffic. Three matching styles cover almost everything:

! Match by ACL (the most common)
ASA-PERIM(config)# access-list WEB-ACL extended permit tcp any object DMZ-WEB eq https
ASA-PERIM(config)# class-map WEB-CLASS
ASA-PERIM(config-cmap)#  match access-list WEB-ACL
!
! Match by port (lighter than an ACL)
ASA-PERIM(config)# class-map SSH-CLASS
ASA-PERIM(config-cmap)#  match port tcp eq 22
!
! Match by destination IP only
ASA-PERIM(config)# class-map DMZ-CLASS
ASA-PERIM(config-cmap)#  match destination-address dmz 192.168.50.0 255.255.255.0

One class-map can have one match line. For more complex matching (multiple conditions ANDed or ORed), build the matching into an ACL and use match access-list.

Worked Example: Custom HTTP Inspection for the DMZ

Apply HTTP inspection only to traffic destined for the DMZ web server, with custom restrictions (only GET/POST allowed, no PUT/DELETE, max URI length 1024 bytes).

! 1. Define what custom HTTP inspection should do
ASA-PERIM(config)# policy-map type inspect http DMZ-HTTP-MAP
ASA-PERIM(config-pmap)#  parameters
ASA-PERIM(config-pmap-p)#   protocol-violation action drop-connection log
ASA-PERIM(config-pmap)#  match request method PUT
ASA-PERIM(config-pmap-c)#   drop-connection log
ASA-PERIM(config-pmap)#  match request method DELETE
ASA-PERIM(config-pmap-c)#   drop-connection log
ASA-PERIM(config-pmap)#  match request uri length gt 1024
ASA-PERIM(config-pmap-c)#   drop-connection log
!
! 2. Define the class-map that matches DMZ-bound web traffic
ASA-PERIM(config)# access-list DMZ-WEB-ACL extended permit tcp any object DMZ-WEB eq http
ASA-PERIM(config)# access-list DMZ-WEB-ACL extended permit tcp any object DMZ-WEB eq https
ASA-PERIM(config)# class-map DMZ-WEB-CLASS
ASA-PERIM(config-cmap)#  match access-list DMZ-WEB-ACL
!
! 3. Build the policy-map with the inspection action referencing the inspect map
ASA-PERIM(config)# policy-map DMZ-POLICY
ASA-PERIM(config-pmap)#  class DMZ-WEB-CLASS
ASA-PERIM(config-pmap-c)#   inspect http DMZ-HTTP-MAP
!
! 4. Bind it to the outside interface
ASA-PERIM(config)# service-policy DMZ-POLICY interface outside

The new service-policy on the outside interface coexists with the global one. Per-interface policies evaluate before global; if a packet matches an interface policy class, the interface policy wins and the global is skipped for that packet. If the packet does not match any class on the interface policy, the global policy is consulted next.

Verify the new policy is in place:

ASA-PERIM# show service-policy interface outside
Interface outside:
  Service-policy: DMZ-POLICY
    Class-map: DMZ-WEB-CLASS
      Inspect: http DMZ-HTTP-MAP, packet 87, lock fail 0, drop 0, reset-drop 0

The packet count climbing means the inspection engine is firing. The drop and reset-drop counters tell you whether any real packets are being rejected by the application-layer rules.

Connection Limits and Timeouts

MPF also drives per-flow connection limits and timeouts. Useful for limiting a high-fan-out source from exhausting the conn table, or for shortening the idle timeout on protocols you know are bursty.

ASA-PERIM(config)# policy-map global_policy
ASA-PERIM(config-pmap)#  class inspection_default
ASA-PERIM(config-pmap-c)#   set connection conn-max 100000
ASA-PERIM(config-pmap-c)#   set connection embryonic-conn-max 1000
ASA-PERIM(config-pmap-c)#   set connection per-client-max 5000
ASA-PERIM(config-pmap-c)#   set connection timeout idle 1:00:00
ASA-PERIM(config-pmap-c)#   set connection timeout half-closed 0:10:00

Walk through:

  • conn-max 100000: cap the total simultaneous conns matching this class. Useful for keeping a single application from hogging the table.
  • embryonic-conn-max 1000: cap on TCP half-open SYNs. The ASA's classic SYN-flood mitigation; below this the ASA proxies the SYN/ACK to validate the source.
  • per-client-max 5000: cap per source IP. Stops a single noisy client from hogging.
  • timeout idle: how long an idle conn lives before the ASA tears it down. Default is 1 hour; tune up for long-lived idle protocols.
  • timeout half-closed: TCP FIN/FIN-WAIT timeout. Default is 10 minutes; tune down to reclaim conns faster after one side has gone away.

QoS via MPF

The ASA's QoS support is narrower than IOS - it does priority queuing and policing on selected traffic, not full diffserv-style queuing.

ASA-PERIM(config)# class-map VOICE-CLASS
ASA-PERIM(config-cmap)#  match dscp ef
!
ASA-PERIM(config)# policy-map QOS-POLICY
ASA-PERIM(config-pmap)#  class VOICE-CLASS
ASA-PERIM(config-pmap-c)#   priority
!
ASA-PERIM(config)# service-policy QOS-POLICY interface outside

Voice traffic (DSCP EF) gets the priority queue on the outside interface. Most ASA deployments do not need this because the upstream router or WAN edge handles QoS; the ASA's job is forwarding and security, not shaping.

Verification Commands

CommandWhat it tells you
show service-policy globalWhat classes are on the global policy and their per-class hit/drop counters.
show service-policy interface NAMEThe interface-bound service-policy and its counters.
show running-config policy-mapAll policy-map definitions in the running config.
show running-config class-mapAll class-map definitions.
show running-config service-policyThe bindings (which policy-map is bound where).
show conn protocol tcpActive TCP conns; useful to see what inspection has tracked.
show inspect httpPer-engine internal counters and stats (replace http with the engine you care about).

Common Traps

Removing the global policy without replacing it. If you do no service-policy global_policy global without binding a replacement, you lose all default inspection. ICMP stops working, FTP active stops working, your DNS bonus features evaporate. If you are migrating to per-interface policies, build the new ones first and remove the global last - or keep the global and let per-interface policies layer on top.

Conflicting per-interface and global classes. Per-interface wins over global, even for the same class name. If you build an interface policy that covers inspection_default, you have just disabled the global engines for traffic on that interface. Be explicit about which interface policies cover which classes.

HTTP inspection breaking valid traffic. The default HTTP inspect map is permissive. Custom maps with strict rules (no PUT, max URI 256) are easy to write and easy to over-tighten. Test with the actual application before binding to a production interface; the application-layer reset comes back as a connection reset to the client, with no obvious clue at the client end.

Forgetting to count. Every class entry in a policy-map with no actions does nothing useful. The show service-policy output still shows it, with packet counters at zero or a constant. Watch for a class with growing matches but no actions - that is configuration that has no effect.

Key Takeaways

The Cisco ASA MPF is class-map matches traffic, policy-map applies actions, service-policy binds the policy globally or to an interface. The default global_policy ships with most application-layer inspections enabled and the lab adds inspect icmp so ping replies survive the firewall. Custom inspection adds rules for HTTP, FTP, ESMTP, and other protocols where you want application-layer security; per-interface policies override global for matching classes.

For where the inspection engines fire in the per-packet pipeline, see Cisco ASA Packet Flow. For confirmation that a specific flow is hitting an inspection class, run show service-policy and watch the packet counter for the class climb. The full reading order is on the Cisco ASA pillar.

Written by
More from Ping Labz
Great! You’ve successfully signed up.
Welcome back! You've successfully signed in.
You've successfully subscribed to Ping Labz.
Your link has expired.
Success! Check your email for magic link to sign-in.
Success! Your billing info has been updated.
Your billing was not updated.