ASA

Deep Packet Inspection on the ASA: Application Inspection Engines in Practice

ASA application inspection showing the global and per-interface HTTP engines
In: ASA, CCIE, Labs, Network Security

A stateful firewall that only reads Layer 3 and Layer 4 headers is half a firewall. It can decide whether TCP port 21 is allowed, but it has no idea what the FTP control channel is negotiating on that port, and it cannot open the return data channel the protocol is about to ask for. Application inspection is what closes that gap on the ASA, and it is the feature that separates a real security appliance from a router with an ACL. This article is part of our Cisco ASA series and goes a layer deeper than our inspection engines overview, showing the default inspection policy in action on a real ASAv 9.24 in CML with live per-interface counters.

Deep packet inspection on the ASA means the firewall parses the application-layer payload of a connection, not just its headers. It does this for two reasons that a plain ACL can never handle: it opens pinholes for protocols that negotiate their own ports, and it enforces protocol conformance so that traffic claiming to be HTTP actually behaves like HTTP. Both matter, and both ship enabled by default.

The default inspection policy

Every ASA boots with application inspection already running. This is not something you turn on; it is something you inherit. The factory configuration wires up a complete Modular Policy Framework stack whose only job is to inspect the common protocols on every interface. If you have read our MPF walkthrough, this will look familiar, because it is the same three layers applied to the box itself.

  • global_policy is the default policy-map. It holds the inspection actions.
  • inspection_default is the default class-map inside it. It matches traffic with match default-inspection-traffic, the special classifier that selects the standard inspected protocols on their well-known ports.
  • service-policy global_policy global is the binding that applies the whole thing to every interface.

Put those together and you get a firewall that, out of the box, is inspecting DNS, FTP, ICMP, and a long list of other protocols everywhere, with no explicit configuration from you. That is a good default, and it is also why some traffic quietly works on an ASA that would fail on a stateless device: the inspection engines are silently opening the pinholes those protocols need.

What application inspection actually does

Two jobs, both invisible until you know to look for them.

Opening pinholes for port-negotiating protocols. Some protocols use one connection to negotiate a second, dynamically chosen port. FTP in active mode is the classic example: the client and server agree on a data port over the control channel, and the data connection then opens on that port. A stateless ACL cannot predict that port, so it either blocks the data channel or you have to open a huge range. The FTP inspection engine reads the control channel, sees the negotiated port, and opens a precise, temporary pinhole for exactly that connection. SIP, H.323, and several others work the same way. Inspection is the only clean way to allow these protocols without punching permanent holes in your policy.

Enforcing protocol conformance. The second job is a security control. Because the engine parses the payload, it can verify that traffic on a given port actually follows that protocol's rules. Malformed messages, illegal commands, and payloads that do not match the claimed protocol can be flagged or dropped. This is what lets an ASA reject traffic that is technically reaching an allowed port but is not really the protocol it claims to be, a trick attackers use to tunnel through firewalls.

Pinhole creation
Reads control channels (FTP, SIP) and opens precise, temporary ports for the negotiated data connection. A stateless ACL cannot do this.
Protocol conformance
Parses the payload and enforces the protocol's rules, dropping malformed or non-conformant traffic on an allowed port.
NAT fixup
Rewrites embedded IP addresses inside payloads (FTP, DNS) so NAT does not break the application.

Seeing the default and a custom engine side by side

The clearest way to understand inspection is to see the factory default and a custom per-interface engine at the same time. On our lab ASA we kept the default global inspection running and added a custom HTTP inspection on the DMZ interface, where a published nginx server lives. The show service-policy inspect http command prints both.

FW1# show service-policy inspect http
Global policy:
  Service-policy: global_policy
    Class-map: inspection_default
Interface dmz:
  Service-policy: PLZ-DMZ-POLICY
    Class-map: PLZ-HTTP-CLASS
      Inspect: http, packet 60, lock fail 0, drop 0, reset-drop 0

Read this top to bottom. The Global policy block is the factory default: global_policy holding inspection_default, applied everywhere. The Interface dmz block is our custom policy, where PLZ-HTTP-CLASS is running the HTTP inspection engine with a live packet 60 counter from real client traffic. Both are active. The interface policy handles the DMZ, the global policy handles the rest, and they coexist because the more specific interface policy takes precedence for HTTP on that one interface.

That packet 60 is genuine. It is sixty packets from real HTTP transactions a Linux client made against the published server, classified and handed to the inspection engine. drop 0 confirms every packet was conformant HTTP and passed. When you start writing custom Layer 7 policies that block specific content, this is the same counter that will show non-zero drops, which we cover in the custom inspection article.

Inspection is not the same as an ACL

It is worth being precise about the boundary, because this trips people up. An ACL is a permit or deny decision based on addresses and ports. It runs once, early in the packet flow, and it does not remember anything about the application. Inspection runs later, maintains state about the application session, and can act on the contents of the payload across many packets.

The two work together rather than competing. The ACL decides whether a connection is allowed to exist at all. Inspection then watches that allowed connection and enforces how it behaves, opening pinholes and dropping non-conformant messages. You need both. An allowed FTP session with no inspection cannot open its data channel cleanly; an inspected session that the ACL never permitted never gets inspected because it was dropped first. Where each of these sits in the overall processing order is exactly what our ASA packet flow article maps out.

How inspection keeps state

The word "stateful" carries a lot of weight here. When the ASA inspects a connection, it is not making an isolated decision on each packet; it is tracking the whole conversation. For FTP that means remembering that a control channel exists and that a specific data port was just negotiated, so the return connection can be matched to its parent. For ICMP it means recording that an echo request went out so the matching echo reply is allowed back in without a permanent permit rule. For DNS it means pairing a query with its response and tearing the pseudo-connection down once the answer arrives.

This state is why inspection can be both permissive and safe at once. It permits exactly the return traffic a legitimate session requires, for exactly as long as the session needs it, and not a moment longer. A stateless ACL cannot express "allow the reply to this specific request", so it has to allow a whole class of traffic all the time. Inspection replaces a broad standing rule with a narrow, temporary, session-scoped one, which is a strictly better security posture. The cost is CPU and memory to hold the state, which on a busy box is a real design consideration, but for the protocols that need it the trade is almost always worth making.

Troubleshooting inspection

When an inspected protocol misbehaves, the counters point you at the cause quickly. Start with show service-policy inspect <protocol> and read the packet and drop numbers. A climbing packet counter with drop 0 means the engine is seeing and passing traffic, so the problem is elsewhere. A non-zero drop means inspection itself is discarding packets, and the syslog will usually name the reason. A packet 0 counter means the engine is applied but no traffic is matching its class-map, which sends you back to check the classifier.

The classic inspection failure is a protocol that works until NAT gets involved, then breaks. That is almost always an embedded-address problem: the application put an IP address inside its payload, NAT rewrote the header but not the payload, and the two no longer agree. The relevant inspection engine is exactly what fixes this by rewriting the embedded address too, so the fix is usually to confirm inspection for that protocol is actually enabled rather than to touch NAT at all. It is a good reminder that inspection is not only a security control, it is frequently what makes an application work through the firewall in the first place.

A version caveat worth respecting

Application inspection has a long history, and Cisco has retired some of the older engines over the years. On the ASAv 9.24 we tested, several legacy inspection engines that appear in older documentation and study guides have been deprecated, so a command you copied from a 2015 configuration guide may simply not exist on a current build. The workhorses are all still present and current: HTTP, FTP, ICMP, and DNS inspection are exactly what you would expect and behave as documented.

The practical rule is to verify against your own version rather than trusting a study guide. Run show run policy-map and show service-policy on the actual box, and confirm the inspection you want is supported before you build a design around it. Inspection engines are one of the areas where the gap between old documentation and current firmware bites hardest, and the fix is simply to check the machine in front of you.

HTTP
Current
Layer 7 web inspection, the basis for URI and header filtering.
FTP
Current
Opens data-channel pinholes and rewrites embedded addresses for NAT.
ICMP
Current
Statefully matches echo replies to requests instead of blanket-permitting ICMP.
DNS
Current
Enforces message limits and guards against DNS-based attacks and spoofing.

When to add a custom inspection engine

The default policy is deliberately conservative. It inspects the common protocols with default parameters and no content filtering. You add a custom inspection engine when you need something the default does not do: block a specific URL, enforce a stricter HTTP policy, restrict FTP commands, or apply inspection only to one interface. In every case the pattern is the one from the MPF article: write a class-map to select the traffic, a policy-map to attach the inspection action, and a service-policy to bind it, usually to a specific interface so it overrides the global default for that traffic.

The most valuable custom engine is Layer 7 HTTP inspection, because it lets you match and drop on the contents of web requests, the URI, headers, methods, and body. That is where inspection stops being plumbing and becomes an active content control, and it is the subject of the next article in the series.

Key Takeaways

  • Application inspection reads the payload, not just headers. It does what a stateless ACL cannot: understand the application session across many packets.
  • It ships on by default. The factory global_policy / inspection_default / service-policy global stack inspects common protocols on every interface with no configuration from you.
  • Two core jobs. Opening pinholes for port-negotiating protocols like FTP and SIP, and enforcing protocol conformance to drop non-conformant traffic on allowed ports.
  • Default and custom engines coexist. show service-policy inspect http showed the global default and a per-interface HTTP engine with a live packet 60 counter at the same time.
  • Verify against your version. ASAv 9.24 deprecated some legacy engines. HTTP, FTP, ICMP, and DNS are current, but check the box rather than an old guide.

Application inspection is the foundation. The real power shows up when you write your own Layer 7 policy and block exactly what you choose. Keep going in the Cisco ASA series with custom HTTP inspection, where a real regex blocks a real URL for a real client, and revisit the inspection engines overview for the full catalog of what each engine handles.

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.